lib

elementtype.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
3 Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <tqfont.h>
22#include <tqfontmetrics.h>
23#include <tqpainter.h>
24
25#include <kdebug.h>
26
27#include "basicelement.h"
28#include "contextstyle.h"
29#include "elementtype.h"
30#include "sequenceelement.h"
31#include "sequenceparser.h"
32#include "textelement.h"
33
34
35KFORMULA_NAMESPACE_BEGIN
36
37int ElementType::evilDestructionCount = 0;
38
39/*
40 * Converts CharStyle and CharFamily to the MathML 'mathvariant'
41 * attribute (see MathML spec 3.2.2).
42 */
43TQString format2variant( CharStyle style, CharFamily family )
44{
45 TQString result;
46
47 switch( family ) {
48 case normalFamily:
49 case anyFamily:
50 switch( style ) {
51 case normalChar:
52 result = "normal"; break;
53 case boldChar:
54 result = "bold"; break;
55 case italicChar:
56 result = "italic"; break;
57 case boldItalicChar:
58 result = "bold-italic"; break;
59 case anyChar:
60 break;
61 }
62 break;
63 case scriptFamily:
64 result = "script";
65 if ( style == boldChar || style == boldItalicChar )
66 result = "bold-" + result;
67 break;
68 case frakturFamily:
69 result = "fraktur";
70 if ( style == boldChar || style == boldItalicChar )
71 result = "bold-" + result;
72 break;
73 case doubleStruckFamily:
74 result = "double-struck"; break;
75 }
76
77 return result;
78}
79
80ElementType::ElementType( SequenceParser* parser )
81 : from( parser->getStart() ), to( parser->getEnd() ), prev( 0 )
82{
83 evilDestructionCount++;
84}
85
86ElementType::~ElementType()
87{
88 delete prev;
89 evilDestructionCount--;
90}
91
92
93TQString ElementType::text( SequenceElement* seq ) const
94{
95 TQString str;
96 for ( uint i=start(); i<end(); ++i ) {
97 str.append( seq->getChild( i )->getCharacter() );
98 }
99 return str;
100}
101
102
105 double )
106{
107 return 0;
108}
109
110luPt ElementType::getSpaceAfter( MultiElementType*,
111 const ContextStyle&,
113 double )
114{
115 return 0;
116}
117
118luPt ElementType::getSpaceAfter( OperatorType*,
119 const ContextStyle&,
121 double )
122{
123 return 0;
124}
125
126luPt ElementType::getSpaceAfter( RelationType*,
127 const ContextStyle&,
129 double )
130{
131 return 0;
132}
133
134luPt ElementType::getSpaceAfter( PunctuationType*,
135 const ContextStyle&,
137 double )
138{
139 return 0;
140}
141
142luPt ElementType::getSpaceAfter( BracketType*,
143 const ContextStyle&,
145 double )
146{
147 return 0;
148}
149
150luPt ElementType::getSpaceAfter( ComplexElementType*,
151 const ContextStyle&,
153 double )
154{
155 return 0;
156}
157
158luPt ElementType::getSpaceAfter( InnerElementType*,
159 const ContextStyle&,
161 double )
162{
163 return 0;
164}
165
166luPt ElementType::thinSpaceIfNotScript( const ContextStyle& context,
168 double factor )
169{
170 if ( !context.isScript( tstyle ) ) {
171 return context.getThinSpace( tstyle, factor );
172 }
173 return 0;
174}
175
176luPt ElementType::mediumSpaceIfNotScript( const ContextStyle& context,
178 double factor )
179{
180 if ( !context.isScript( tstyle ) ) {
181 return context.getMediumSpace( tstyle, factor );
182 }
183 return 0;
184}
185
186luPt ElementType::thickSpaceIfNotScript( const ContextStyle& context,
188 double factor )
189{
190 if ( !context.isScript( tstyle ) ) {
191 return context.getThickSpace( tstyle, factor );
192 }
193 return 0;
194}
195
196
197TQFont ElementType::getFont(const ContextStyle& context)
198{
199 return context.getDefaultFont();
200}
201
202void ElementType::setUpPainter(const ContextStyle& context, TQPainter& painter)
203{
204 painter.setPen(context.getDefaultColor());
205}
206
207void ElementType::append( ElementType* element )
208{
209 element->prev = this;
210}
211
212void ElementType::output()
213{
214 kdDebug( DEBUGID ) << start() << " - " << end() << endl;
215}
216
217void ElementType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
218{
219 for ( uint i = from; i < to; ++i ) {
220 se->getChild( i )->writeMathML( doc, de, oasisFormat );
221 }
222}
223
224
225SequenceType::SequenceType( SequenceParser* parser )
226 : ElementType( parser ), last( 0 )
227{
228 while ( true ) {
229 parser->nextToken();
230 //cerr << "SequenceType::SequenceType(): " << parser->getTokenType() << " "
231 // << parser->getStart() << " " << parser->getEnd() << endl;
232 if ( parser->getTokenType() == END ) {
233 break;
234 }
235 ElementType* nextType = parser->getPrimitive();
236 if ( nextType == 0 ) {
237 break;
238 }
239 if ( last != 0 ) {
240 last->append( nextType );
241 }
242 last = nextType;
243 }
244}
245
246SequenceType::~SequenceType()
247{
248 delete last;
249}
250
251
252void SequenceType::output()
253{
254}
255
256
257MultiElementType::MultiElementType( SequenceParser* parser )
258 : ElementType( parser )
259{
260 for ( uint i = start(); i < end(); i++ ) {
261 parser->setElementType( i, this );
262 }
263 m_text = parser->text();
264}
265
266
269 double factor )
270{
271 if ( getPrev() != 0 ) {
272 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
273 }
274 return 0;
275}
276
277luPt MultiElementType::getSpaceAfter( OperatorType*,
278 const ContextStyle& context,
280 double factor )
281{
282 return mediumSpaceIfNotScript( context, tstyle, factor );
283}
284
285luPt MultiElementType::getSpaceAfter( RelationType*,
286 const ContextStyle& context,
288 double factor )
289{
290 return thickSpaceIfNotScript( context, tstyle, factor );
291}
292
293luPt MultiElementType::getSpaceAfter( InnerElementType*,
294 const ContextStyle& context,
296 double factor )
297{
298 return thinSpaceIfNotScript( context, tstyle, factor );
299}
300
301
302TextType::TextType( SequenceParser* parser )
303 : MultiElementType( parser )
304{
305}
306
307void TextType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
308{
309 for ( uint i = start(); i < end(); ++i ) {
310 TQDomElement text = doc.createElement( oasisFormat ? "math:mi" : "mi" );
311 BasicElement* be = se->getChild( i );
312 TextElement* te = static_cast<TextElement*>( be );
313 TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily());
314 if ( !mathvariant.isNull() )
315 text.setAttribute( "mathvariant", mathvariant );
316
317 text.appendChild( doc.createTextNode( be->getCharacter() ) );
318
319 de.appendChild( text );
320 if ( i != end() - 1 ) {
321 TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
322 op.appendChild( doc.createEntityReference( "InvisibleTimes" ) );
323 de.appendChild( op );
324 }
325 }
326}
327
328
329NameType::NameType( SequenceParser* parser )
330 : MultiElementType( parser )
331{
332}
333
334void NameType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
335{
336 se->getChild( start() )->writeMathML( doc, de, oasisFormat );
337
338 /*
339 TQDomElement name = doc.createElement( "mi" );
340 TQString value;
341 for ( uint i = start(); i < end(); ++i ) {
342 BasicElement* be = se->getChild( i );
343 //TextElement* te = static_cast<TextElement*>( be );
344 value += be->getCharacter();
345 }
346 name.appendChild( doc.createTextNode( value ) );
347 de.appendChild( name );*/
348}
349
350
351TQFont NameType::getFont(const ContextStyle& context)
352{
353 return context.getNameFont();
354}
355
356NumberType::NumberType( SequenceParser* parser )
357 : MultiElementType( parser )
358{
359}
360
361TQFont NumberType::getFont(const ContextStyle& context)
362{
363 return context.getNumberFont();
364}
365
366void NumberType::setUpPainter(const ContextStyle& context, TQPainter& painter)
367{
368 painter.setPen(context.getNumberColor());
369}
370
371void NumberType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
372{
373 TQDomElement name = doc.createElement( oasisFormat ? "math:mn" : "mn" );
374 TQString value;
375 for ( uint i = start(); i < end(); ++i ) {
376 BasicElement* be = se->getChild( i );
377 value += be->getCharacter();
378 }
379 TextElement* te = static_cast<TextElement*>( se->getChild( start() ) );
380 TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
381 if ( !mathvariant.isNull() )
382 name.setAttribute( "mathvariant", mathvariant );
383
384 name.appendChild( doc.createTextNode( value ) );
385 de.appendChild( name );
386}
387
388
389SingleElementType::SingleElementType( SequenceParser* parser )
390 : ElementType( parser )
391{
392 parser->setElementType( start(), this );
393}
394
395AbstractOperatorType::AbstractOperatorType( SequenceParser* parser )
396 : SingleElementType( parser )
397{
398}
399
400void AbstractOperatorType::saveMathML( SequenceElement* se, TQDomDocument& doc, TQDomElement de, bool oasisFormat )
401{
402 TQDomElement op = doc.createElement( oasisFormat ? "math:mo" : "mo" );
403 BasicElement* be = se->getChild( start() );
404 if ( be->getCharacter().latin1() != 0 ) {
405 // latin-1 char
406 op.appendChild( doc.createTextNode( be->getCharacter() ) );
407 }
408 else {
409 // unicode char
410 TQString s;
411 op.appendChild( doc.createEntityReference( s.sprintf( "#x%05X", be->getCharacter().unicode() ) ) );
412 }
413 TextElement* te = static_cast<TextElement*>( be );
414 TQString mathvariant = format2variant( te->getCharStyle(), te->getCharFamily() );
415 if ( !mathvariant.isNull() )
416 op.setAttribute( "mathvariant", mathvariant );
417
418 de.appendChild( op );
419}
420
421OperatorType::OperatorType( SequenceParser* parser )
422 : AbstractOperatorType( parser )
423{
424}
425
426luPt OperatorType::getSpaceBefore( const ContextStyle& context,
428 double factor )
429{
430 if ( getPrev() != 0 ) {
431 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
432 }
433 return 0;
434}
435
436luPt OperatorType::getSpaceAfter( MultiElementType*,
437 const ContextStyle& context,
439 double factor )
440{
441 return mediumSpaceIfNotScript( context, tstyle, factor );
442}
443
444luPt OperatorType::getSpaceAfter( BracketType*,
445 const ContextStyle& context,
447 double factor )
448{
449 return mediumSpaceIfNotScript( context, tstyle, factor );
450}
451
452luPt OperatorType::getSpaceAfter( ComplexElementType*,
453 const ContextStyle& context,
455 double factor )
456{
457 return mediumSpaceIfNotScript( context, tstyle, factor );
458}
459
460luPt OperatorType::getSpaceAfter( InnerElementType*,
461 const ContextStyle& context,
463 double factor )
464{
465 return mediumSpaceIfNotScript( context, tstyle, factor );
466}
467
468
469TQFont OperatorType::getFont(const ContextStyle& context)
470{
471 return context.getOperatorFont();
472}
473
474void OperatorType::setUpPainter(const ContextStyle& context, TQPainter& painter)
475{
476 painter.setPen(context.getOperatorColor());
477}
478
479
480RelationType::RelationType( SequenceParser* parser )
481 : AbstractOperatorType( parser )
482{
483}
484
485luPt RelationType::getSpaceBefore( const ContextStyle& context,
487 double factor )
488{
489 if ( getPrev() != 0 ) {
490 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
491 }
492 return 0;
493}
494
495luPt RelationType::getSpaceAfter( MultiElementType*,
496 const ContextStyle& context,
498 double factor )
499{
500 return thickSpaceIfNotScript( context, tstyle, factor );
501}
502
503luPt RelationType::getSpaceAfter( BracketType*,
504 const ContextStyle& context,
506 double factor )
507{
508 return thickSpaceIfNotScript( context, tstyle, factor );
509}
510
511luPt RelationType::getSpaceAfter( ComplexElementType*,
512 const ContextStyle& context,
514 double factor )
515{
516 return thickSpaceIfNotScript( context, tstyle, factor );
517}
518
519luPt RelationType::getSpaceAfter( InnerElementType*,
520 const ContextStyle& context,
522 double factor )
523{
524 return thickSpaceIfNotScript( context, tstyle, factor );
525}
526
527TQFont RelationType::getFont( const ContextStyle& context )
528{
529 return context.getOperatorFont();
530}
531
532void RelationType::setUpPainter( const ContextStyle& context, TQPainter& painter )
533{
534 painter.setPen(context.getOperatorColor());
535}
536
537
538
539PunctuationType::PunctuationType( SequenceParser* parser )
540 : AbstractOperatorType( parser )
541{
542}
543
544luPt PunctuationType::getSpaceBefore( const ContextStyle& context,
546 double factor )
547{
548 if ( getPrev() != 0 ) {
549 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
550 }
551 return 0;
552}
553
554luPt PunctuationType::getSpaceAfter( MultiElementType*,
555 const ContextStyle& context,
557 double factor )
558{
559 return thinSpaceIfNotScript( context, tstyle, factor );
560}
561
562luPt PunctuationType::getSpaceAfter( RelationType*,
563 const ContextStyle& context,
565 double factor )
566{
567 return thickSpaceIfNotScript( context, tstyle, factor );
568}
569
570luPt PunctuationType::getSpaceAfter( PunctuationType*,
571 const ContextStyle& context,
573 double factor )
574{
575 return thinSpaceIfNotScript( context, tstyle, factor );
576}
577
578luPt PunctuationType::getSpaceAfter( BracketType*,
579 const ContextStyle& context,
581 double factor )
582{
583 return thinSpaceIfNotScript( context, tstyle, factor );
584}
585
586luPt PunctuationType::getSpaceAfter( ComplexElementType*,
587 const ContextStyle& context,
589 double factor )
590{
591 return thinSpaceIfNotScript( context, tstyle, factor );
592}
593
594luPt PunctuationType::getSpaceAfter( InnerElementType*,
595 const ContextStyle& context,
597 double factor )
598{
599 return thinSpaceIfNotScript( context, tstyle, factor );
600}
601
602TQFont PunctuationType::getFont( const ContextStyle& context )
603{
604 return context.getOperatorFont();
605}
606
607void PunctuationType::setUpPainter( const ContextStyle& context, TQPainter& painter )
608{
609 painter.setPen( context.getDefaultColor() );
610}
611
612
613BracketType::BracketType( SequenceParser* parser )
614 : SingleElementType( parser )
615{
616}
617
618luPt BracketType::getSpaceBefore( const ContextStyle& context,
620 double factor )
621{
622 if ( getPrev() != 0 ) {
623 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
624 }
625 return 0;
626}
627
628luPt BracketType::getSpaceAfter( OperatorType*,
629 const ContextStyle& context,
631 double factor )
632{
633 return mediumSpaceIfNotScript( context, tstyle, factor );
634}
635
636luPt BracketType::getSpaceAfter( RelationType*,
637 const ContextStyle& context,
639 double factor )
640{
641 return thickSpaceIfNotScript( context, tstyle, factor );
642}
643
644luPt BracketType::getSpaceAfter( InnerElementType*,
645 const ContextStyle& context,
647 double factor )
648{
649 return thinSpaceIfNotScript( context, tstyle, factor );
650}
651
652
653ComplexElementType::ComplexElementType( SequenceParser* parser )
654 : SingleElementType( parser )
655{
656}
657
658luPt ComplexElementType::getSpaceBefore( const ContextStyle& context,
660 double factor )
661{
662 if ( getPrev() != 0 ) {
663 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
664 }
665 return 0;
666}
667
668luPt ComplexElementType::getSpaceAfter( OperatorType*,
669 const ContextStyle& context,
671 double factor )
672{
673 return mediumSpaceIfNotScript( context, tstyle, factor );
674}
675
676luPt ComplexElementType::getSpaceAfter( RelationType*,
677 const ContextStyle& context,
679 double factor )
680{
681 return thickSpaceIfNotScript( context, tstyle, factor );
682}
683
684luPt ComplexElementType::getSpaceAfter( InnerElementType*,
685 const ContextStyle& context,
687 double factor )
688{
689 return thinSpaceIfNotScript( context, tstyle, factor );
690}
691
692
693InnerElementType::InnerElementType( SequenceParser* parser )
694 : SingleElementType( parser )
695{
696}
697
698luPt InnerElementType::getSpaceBefore( const ContextStyle& context,
700 double factor )
701{
702 if ( getPrev() != 0 ) {
703 return getPrev()->getSpaceAfter( this, context, tstyle, factor );
704 }
705 return 0;
706}
707
708luPt InnerElementType::getSpaceAfter( MultiElementType*,
709 const ContextStyle& context,
711 double factor )
712{
713 return thinSpaceIfNotScript( context, tstyle, factor );
714}
715
716luPt InnerElementType::getSpaceAfter( OperatorType*,
717 const ContextStyle& context,
719 double factor )
720{
721 return mediumSpaceIfNotScript( context, tstyle, factor );
722}
723
724luPt InnerElementType::getSpaceAfter( RelationType*,
725 const ContextStyle& context,
727 double factor )
728{
729 return thickSpaceIfNotScript( context, tstyle, factor );
730}
731
732luPt InnerElementType::getSpaceAfter( PunctuationType*,
733 const ContextStyle& context,
735 double factor )
736{
737 return thinSpaceIfNotScript( context, tstyle, factor );
738}
739
740luPt InnerElementType::getSpaceAfter( BracketType*,
741 const ContextStyle& context,
743 double factor )
744{
745 return thinSpaceIfNotScript( context, tstyle, factor );
746}
747
748luPt InnerElementType::getSpaceAfter( ComplexElementType*,
749 const ContextStyle& context,
751 double factor )
752{
753 return thinSpaceIfNotScript( context, tstyle, factor );
754}
755
756luPt InnerElementType::getSpaceAfter( InnerElementType*,
757 const ContextStyle& context,
759 double factor )
760{
761 return thinSpaceIfNotScript( context, tstyle, factor );
762}
763
764
765KFORMULA_NAMESPACE_END
Basis of every formula element.
virtual TQChar getCharacter() const
virtual void writeMathML(TQDomDocument &doc, TQDomNode &parent, bool oasisFormat=false) const
Same as above, just MathML.
Contains all the style information for the formela.
TextStyle
Textstyles like in TeX.
Basis of all types.
Definition elementtype.h:52
virtual TQFont getFont(const ContextStyle &context)
virtual TQString text(SequenceElement *seq) const
uint start() const
Definition elementtype.h:71
void append(ElementType *)
Adds a type at the end of the list.
virtual luPt getSpaceBefore(const ContextStyle &context, ContextStyle::TextStyle tstyle, double factor)
uint end() const
Definition elementtype.h:76
virtual void setUpPainter(const ContextStyle &context, TQPainter &painter)
sets the painters pen to a appropriate value
Basis for all tokens that run along several elements.
virtual luPt getSpaceBefore(const ContextStyle &context, ContextStyle::TextStyle tstyle, double factor)
virtual TQFont getFont(const ContextStyle &context)
virtual void setUpPainter(const ContextStyle &context, TQPainter &painter)
sets the painters pen to a appropriate value
virtual TQFont getFont(const ContextStyle &context)
The element that contains a number of children.
virtual BasicElement * getChild(FormulaCursor *, Direction=beforeCursor)
Returns the child at the cursor.
The parser that gets the element list and returns a syntax tree.
void nextToken()
Reads the next token.
ElementType * getPrimitive()
void setElementType(uint pos, ElementType *type)
Tells the element about its new type.
Basis for all tokens that consist of one element only.
const char * name(StdAction id)