summaryrefslogtreecommitdiffstats
path: root/lib/kotext/tests/kotextformattertest.cpp
blob: a02866460ee565cbbcb4e86a2841a6cab38749a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//KoTextFormatter test (also for profiling purposes), GPL v2, David Faure <faure@kde.org>

#include <tdeapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>

#include "KoTextFormatter.h"
#include "KoTextFormat.h"
#include "KoTextDocument.h"
#include "KoTextParag.h"
#include "KoTextZoomHandler.h"
#include "KoParagCounter.h"

#include <assert.h>

class KoTextFormatterTest
{
public:
    KoTextFormatterTest();
    ~KoTextFormatterTest() {
        delete zh;
        delete doc;
    }

    void speedTest();
    void counterAndBigChar();
    void oneLineTest();
    void noHeightTest();
    void noWidthEverTest();
    void tooWideChar();

private:
    KoTextZoomHandler* zh;
    KoTextDocument* doc;
};

// To test various cases with variable document widths: a custom KoTextFlow
class TextFlow : public KoTextFlow
{
public:
    TextFlow( int availableWidth, int availableHeight )
        : m_availableWidth( availableWidth ), m_availableHeight( availableHeight ),
          m_leftMargin( 0 )
    {
        setWidth( m_availableWidth );
    }
    virtual int availableHeight() const {
        return m_availableHeight;
    }
    void setLeftMargin( int lm ) {
        m_leftMargin = lm;
    }
    virtual void adjustMargins( int yp, int h, int reqMinWidth, int& leftMargin, int& rightMargin, int& pageWidth, KoTextParag* ) {
        Q_UNUSED(yp);
        Q_UNUSED(h);
        Q_UNUSED(reqMinWidth);
        Q_UNUSED(rightMargin);
        if ( m_leftMargin ) {
            leftMargin = m_leftMargin;
            pageWidth = m_availableWidth - m_leftMargin;
            kdDebug() << "adjustMargins: returning leftMargin=" << leftMargin << " pageWidth=" << pageWidth << endl;
        } else
            pageWidth = m_availableWidth;
    }
private:
    int m_availableWidth;
    int m_availableHeight;
    int m_leftMargin;
};

KoTextFormatterTest::KoTextFormatterTest()
{
    zh = new KoTextZoomHandler;
    TQFont defaultFont( "helvetica", 12 );
    KoTextFormatCollection* fc = new KoTextFormatCollection( defaultFont, TQt::black, "en_US", false /*no hyphenation*/ );
    KoTextFormatter* formatter = new KoTextFormatter;
    // fc and formatter are owned by the doc
    doc = new KoTextDocument( zh, fc, formatter );
}

void KoTextFormatterTest::speedTest()
{
    kdDebug() << k_funcinfo << endl;
    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "They burst into flames when it is time for them to die, and then they are reborn from the ashes" );

    // Format it 50 times
    for ( uint i = 0 ; i < 50 ; ++i )
    {
      parag->invalidate(0);
      parag->format();
    }
    doc->clear(false);
}

void KoTextFormatterTest::noHeightTest()
{
    kdDebug() << k_funcinfo << endl;
    // We test the case of going past maxY - by setting the available height to 0
    // Expected result: the formatter 'aborts', i.e. no line-breaking, but still
    // goes over each character to set them all correctly; and usually KWord
    // would create a new page and reformat the paragraph
    doc->setFlow( new TextFlow( 250, 0 ) ); // 250 is just enough for one char
    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "abcdefghi" );
    parag->format();
    assert( parag->lines() == 2 ); // one break, then we keep going
    doc->clear(false);
    doc->setFlow( new KoTextFlow ); // default
}

void KoTextFormatterTest::noWidthEverTest()
{
    kdDebug() << k_funcinfo << endl;
    // We test the case of formatting where there is no width (e.g. narrow
    // passage, or after last page).
    // Expected result: the formatter goes down until it finds more width
    // (TODO a test case where this happens)
    // If it doesn't find any (and hits maxY), then it 'aborts', i.e. no line-breaking,
    // but still goes over each character to set them all correctly; and usually KWord
    // would create a new page and reformat the paragraph
    TextFlow* flow = new TextFlow( 1000, 2000 );
    flow->setLeftMargin( 1000 );
    doc->setFlow( flow );

    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "abcdefghi" );
    parag->format();
    // The resulting paragraph is NOT marked as formatted. See kotextformatter.cc -r1.79
    assert( !parag->isValid() );
    doc->clear(false);
    doc->setFlow( new KoTextFlow ); // default
}

void KoTextFormatterTest::tooWideChar()
{
    kdDebug() << k_funcinfo << endl;
    // We test the case of formatting where there is not enough width
    // for the character (e.g. a very large inline table, larger than the document).
    // Expected result: the formatter goes down until it finds more width,
    // gives up, and come back up.
    doc->setFlow( new TextFlow( 10, 2000 ) );
    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "a" );
    parag->format();
    assert( parag->isValid() );
    assert( parag->lines() == 1 );

    doc->clear(false);
    doc->setFlow( new KoTextFlow ); // default
}

void KoTextFormatterTest::oneLineTest()
{
    kdDebug() << k_funcinfo << endl;
    // Normal case, only one line
    // Expected: the parag is as wide as the doc
    doc->setFlow( new TextFlow( 2000, 200 ) );
    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "abcdefghi" );
    parag->format();
    assert( parag->lines() == 1 );
    assert( parag->isValid() );
    assert( parag->rect().width() == 2000 );
    assert( parag->widthUsed() < 2000 );
    doc->clear(false);
    doc->setFlow( new KoTextFlow ); // default
}

void KoTextFormatterTest::counterAndBigChar()
{
    kdDebug() << k_funcinfo << endl;
    // Only one line, with a counter and a big char.
    // Bug #82609: the new height led to "formatting again" which restarted without taking the counter into account
    // Expected: the char starts after the counter
    doc->setFlow( new TextFlow( 2000, 200 ) );
    doc->clear(true);
    KoTextParag* parag = doc->firstParag();
    parag->append( "aB" );
    KoTextFormat f( *parag->at( 0 )->format() );
    f.setPointSize( 48 );
    parag->setFormat( 1, 1, doc->formatCollection()->format( &f ), true );
    KoParagCounter counter;
    counter.setNumbering( KoParagCounter::NUM_LIST );
    counter.setStyle( KoParagCounter::STYLE_NUM );
    parag->setCounter( &counter );
    parag->format();
    assert( parag->lines() == 1 );
    assert( parag->isValid() );
    assert( parag->rect().width() == 2000 );
    assert( parag->widthUsed() < 2000 );
    assert( parag->at(0)->x > 0 );
    doc->clear(false);
    doc->setFlow( new KoTextFlow ); // default
}

int main (int argc, char ** argv)
{
    TDEApplication app(argc, argv, "KoTextFormatter test");

    // Don't let locale settings lead to different hyphenation output
    TDEGlobal::locale()->setLanguage( TQString::fromLatin1( "en_US" ) );
    TDEGlobal::locale()->setCountry( TQString::fromLatin1( "C" ) );

    KoTextFormatterTest test;
    //test.speedTest();
    test.oneLineTest();
    test.counterAndBigChar();
    test.noHeightTest();
    test.noWidthEverTest();
    test.tooWideChar();

    return 0;
}