23#include <tqfontdatabase.h>
24#include <tqapplication.h>
26#include <kstaticdeleter.h>
28#include <kstandarddirs.h>
29#include <tdeio/netaccess.h>
31#include <tdemessagebox.h>
36KFORMULA_NAMESPACE_BEGIN
38#include "unicodetable.cpp"
40bool FontStyle::m_installed =
false;
44 if (!m_installed && install)
46 m_symbolTable.init( style->getMathFont() );
56 const TQStringList lst = db.families();
57 for ( TQStringList::const_iterator it = lst.begin(), end = lst.end() ; it != end ; ++it ) {
58 const TQString name = *it;
59 int i = name.find(
'[');
60 TQString family = name;
63 const int li = name.findRev(
']');
65 if (name[i - 1] ==
' ')
67 family = name.left(i);
70 m_fontNames.append( family.lower() );
73 bool hasFont(
const TQString& fontName )
const {
74 return m_fontNames.find( fontName ) != m_fontNames.end();
76 TQStringList m_fontNames;
78static FontList* s_fontList = 0;
79static KStaticDeleter<FontList> s_fontList_sd;
81void FontStyle::testFont( TQStringList& missing,
const TQString& fontName ) {
83 s_fontList_sd.setObject( s_fontList,
new FontList() );
84 if ( !s_fontList->hasFont( fontName ) ) {
85 kdWarning(39001) <<
"Font '" << fontName <<
"' not found" << endl;
86 missing.append( fontName );
91TQStringList FontStyle::missingFonts(
bool install )
93 if (!m_installed && install)
96 TQStringList missing = missingFontsInternal();
100TQStringList FontStyle::missingFontsInternal()
102 TQStringList missing;
104 testFont( missing,
"cmex10" );
105 testFont( missing,
"arev sans");
110void FontStyle::installFonts()
114 TQStringList missing = missingFontsInternal();
115 if (!missing.isEmpty())
117 TQStringList urlList;
118 for (TQStringList::iterator it = missing.begin(); it != missing.end(); ++it)
120 if ( *it ==
"arev sans" ) {
121 if (!TDEIO::NetAccess::exists(
"fonts:/Personal/Arev.ttf",
true, NULL))
122 urlList.append(locate(
"data",
"kformula/fonts/Arev.ttf"));
123 if (!TDEIO::NetAccess::exists(
"fonts:/Personal/ArevIt.ttf",
true, NULL))
124 urlList.append(locate(
"data",
"kformula/fonts/ArevIt.ttf"));
125 if (!TDEIO::NetAccess::exists(
"fonts:/Personal/ArevBd.ttf",
true, NULL))
126 urlList.append(locate(
"data",
"kformula/fonts/ArevBd.ttf"));
127 if (!TDEIO::NetAccess::exists(
"fonts:/Personal/ArevBI.ttf",
true, NULL))
128 urlList.append(locate(
"data",
"kformula/fonts/ArevBI.ttf"));
131 if (!TDEIO::NetAccess::exists(
"fonts:/Personal/" + *it +
".ttf",
true, NULL))
132 urlList.append(locate(
"data",
"kformula/fonts/" + *it +
".ttf"));
135 TDEIO::copy(urlList,
"fonts:/Personal/",
false);
137 i18n(
"Some fonts have been installed to assure that symbols in formulas are properly visualized. You must restart the application in order so that changes take effect"));
142Artwork* FontStyle::createArtwork( SymbolType type )
const
144 return new Artwork( type );
149const TQChar leftRoundBracket[] = {
154const TQChar leftSquareBracket[] = {
159const TQChar leftCurlyBracket[] = {
166const TQChar leftLineBracket[] = {
171const TQChar rightLineBracket[] = {
177const TQChar rightRoundBracket[] = {
182const TQChar rightSquareBracket[] = {
187const TQChar rightCurlyBracket[] = {
195static const char cmex_LeftSquareBracket = 163;
196static const char cmex_RightSquareBracket = 164;
197static const char cmex_LeftCurlyBracket = 169;
198static const char cmex_RightCurlyBracket = 170;
199static const char cmex_LeftCornerBracket = 173;
200static const char cmex_RightCornerBracket = 174;
201static const char cmex_LeftRoundBracket = 161;
202static const char cmex_RightRoundBracket = 162;
203static const char cmex_SlashBracket = 177;
204static const char cmex_BackSlashBracket = 178;
209static const char cmex_Int = 90;
210static const char cmex_Sum = 88;
211static const char cmex_Prod = 89;
215static short cmex_nextchar(
short ch )
218 case 161:
return 179;
219 case 162:
return 180;
220 case 163:
return 104;
221 case 164:
return 105;
222 case 169:
return 110;
223 case 170:
return 111;
224 case 165:
return 106;
225 case 166:
return 107;
226 case 167:
return 108;
227 case 168:
return 109;
233 case 179:
return 181;
234 case 180:
return 182;
235 case 104:
return 183;
236 case 105:
return 184;
237 case 110:
return 189;
238 case 111:
return 190;
239 case 106:
return 185;
240 case 107:
return 186;
241 case 108:
return 187;
242 case 109:
return 188;
248 case 181:
return 195;
266bool Artwork::calcCMDelimiterSize(
const ContextStyle& context,
271 TQFont f(
"cmex10" );
272 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
273 TQFontMetrics fm( f );
275 for (
char i=1; c != 0; ++i ) {
276 LuPixelRect bound = fm.boundingRect( c );
279 if ( height >= parentSize ) {
287 setBaseline( baseline );
291 c = cmex_nextchar( c );
300 uchar c, luPt fontSize )
302 TQFont f(
"cmex10" );
303 f.setPointSizeFloat( context.layoutUnitPtToPt( fontSize ) );
304 TQFontMetrics fm( f );
308 c = cmex_nextchar( c );
315 LuPixelRect bound = fm.boundingRect( cmChar );
323 setBaseline( baseline );
327void Artwork::drawCMDelimiter( TQPainter& painter,
const ContextStyle& style,
328 luPixel x, luPixel y,
331 TQFont f(
"cmex10" );
334 painter.setFont( f );
336 style.layoutUnitToPixelY( y + getBaseline() ),
337 TQString( TQChar( cmChar ) ) );
341 TQFontMetrics fm( f );
342 LuPixelRect bound = fm.boundingRect( cmChar );
343 painter.setBrush(TQt::NoBrush);
344 painter.setPen(TQt::green);
346 style.layoutUnitToPixelY( y ),
353Artwork::Artwork(SymbolType t)
354 : baseline( -1 ), type(t)
368 case LeftSquareBracket:
369 if ( calcCMDelimiterSize( style, cmex_LeftSquareBracket,
370 mySize, parentSize ) ) {
373 calcRoundBracket( style, leftSquareBracket, parentSize, mySize );
375 case RightSquareBracket:
376 if ( calcCMDelimiterSize( style, cmex_RightSquareBracket,
377 mySize, parentSize ) ) {
380 calcRoundBracket( style, rightSquareBracket, parentSize, mySize );
382 case LeftLineBracket:
383 calcRoundBracket( style, leftLineBracket, parentSize, mySize );
384 setWidth( getWidth()/2 );
386 case RightLineBracket:
387 calcRoundBracket( style, rightLineBracket, parentSize, mySize );
388 setWidth( getWidth()/2 );
391 if ( calcCMDelimiterSize( style, cmex_SlashBracket,
392 mySize, parentSize ) ) {
395 calcLargest( style, cmex_SlashBracket, mySize );
397 case BackSlashBracket:
398 if ( calcCMDelimiterSize( style, cmex_BackSlashBracket,
399 mySize, parentSize ) ) {
402 calcLargest( style, cmex_BackSlashBracket, mySize );
404 case LeftCornerBracket:
405 if ( calcCMDelimiterSize( style, cmex_LeftCornerBracket,
406 mySize, parentSize ) ) {
409 calcLargest( style, cmex_LeftCornerBracket, mySize );
411 case RightCornerBracket:
412 if ( calcCMDelimiterSize( style, cmex_RightCornerBracket,
413 mySize, parentSize ) ) {
416 calcLargest( style, cmex_RightCornerBracket, mySize );
418 case LeftRoundBracket:
419 if ( calcCMDelimiterSize( style, cmex_LeftRoundBracket,
420 mySize, parentSize ) ) {
423 calcRoundBracket( style, leftRoundBracket, parentSize, mySize );
425 case RightRoundBracket:
426 if ( calcCMDelimiterSize( style, cmex_RightRoundBracket,
427 mySize, parentSize ) ) {
430 calcRoundBracket( style, rightRoundBracket, parentSize, mySize );
433 setHeight(parentSize);
437 case LeftCurlyBracket:
438 if ( calcCMDelimiterSize( style, cmex_LeftCurlyBracket,
439 mySize, parentSize ) ) {
442 calcCurlyBracket( style, leftCurlyBracket, parentSize, mySize );
444 case RightCurlyBracket:
445 if ( calcCMDelimiterSize( style, cmex_RightCurlyBracket,
446 mySize, parentSize ) ) {
449 calcCurlyBracket( style, rightCurlyBracket, parentSize, mySize );
452 calcCharSize( style, style.getBracketFont(), mySize, cmex_Int );
455 calcCharSize( style, style.getBracketFont(), mySize, cmex_Sum );
458 calcCharSize( style, style.getBracketFont(), mySize, cmex_Prod );
469 case LeftSquareBracket:
470 calcCharSize(style, mySize, leftSquareBracketChar);
472 case RightSquareBracket:
473 calcCharSize(style, mySize, rightSquareBracketChar);
475 case LeftLineBracket:
476 case RightLineBracket:
477 calcCharSize(style, mySize, verticalLineChar);
480 calcCharSize(style, mySize, slashChar);
482 case BackSlashBracket:
483 calcCharSize(style, mySize, backSlashChar);
485 case LeftCornerBracket:
486 calcCharSize(style, mySize, leftAngleBracketChar);
488 case RightCornerBracket:
489 calcCharSize(style, mySize, rightAngleBracketChar);
491 case LeftRoundBracket:
492 calcCharSize(style, mySize, leftParenthesisChar);
494 case RightRoundBracket:
495 calcCharSize(style, mySize, rightParenthesisChar);
503 case LeftCurlyBracket:
504 calcCharSize(style, mySize, leftCurlyBracketChar);
506 case RightCurlyBracket:
507 calcCharSize(style, mySize, rightCurlyBracketChar);
517void Artwork::draw(TQPainter& painter,
const LuPixelRect& ,
519 StyleAttributes& style,
const LuPixelPoint& parentOrigin)
522 luPixel myX = parentOrigin.x() + getX();
523 luPixel myY = parentOrigin.y() + getY();
529 painter.setPen(context.getDefaultColor());
532 case LeftSquareBracket:
533 drawCharacter(painter, context, myX, myY, mySize, leftSquareBracketChar);
535 case RightSquareBracket:
536 drawCharacter(painter, context, myX, myY, mySize, rightSquareBracketChar);
538 case LeftCurlyBracket:
539 drawCharacter(painter, context, myX, myY, mySize, leftCurlyBracketChar);
541 case RightCurlyBracket:
542 drawCharacter(painter, context, myX, myY, mySize, rightCurlyBracketChar);
544 case LeftLineBracket:
545 case RightLineBracket:
546 drawCharacter(painter, context, myX, myY, mySize, verticalLineChar);
549 drawCharacter(painter, context, myX, myY, mySize, slashChar);
551 case BackSlashBracket:
552 drawCharacter(painter, context, myX, myY, mySize, backSlashChar);
554 case LeftCornerBracket:
555 drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
557 case RightCornerBracket:
558 drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
560 case LeftRoundBracket:
561 drawCharacter(painter, context, myX, myY, mySize, leftParenthesisChar);
563 case RightRoundBracket:
564 drawCharacter(painter, context, myX, myY, mySize, rightParenthesisChar);
575void Artwork::draw(TQPainter& painter,
const LuPixelRect& ,
577 StyleAttributes& style, luPt ,
const LuPixelPoint& origin)
580 luPixel myX = origin.x() + getX();
581 luPixel myY = origin.y() + getY();
587 painter.setPen(context.getDefaultColor());
590 case LeftSquareBracket:
591 if ( cmChar != -1 ) {
592 drawCMDelimiter( painter, context, myX, myY, mySize );
595 drawBigRoundBracket( painter, context, leftSquareBracket, myX, myY, mySize );
598 case RightSquareBracket:
599 if ( cmChar != -1 ) {
600 drawCMDelimiter( painter, context, myX, myY, mySize );
603 drawBigRoundBracket( painter, context, rightSquareBracket, myX, myY, mySize );
606 case LeftCurlyBracket:
607 if ( cmChar != -1 ) {
608 drawCMDelimiter( painter, context, myX, myY, mySize );
611 drawBigCurlyBracket( painter, context, leftCurlyBracket, myX, myY, mySize );
614 case RightCurlyBracket:
615 if ( cmChar != -1 ) {
616 drawCMDelimiter( painter, context, myX, myY, mySize );
619 drawBigCurlyBracket( painter, context, rightCurlyBracket, myX, myY, mySize );
622 case LeftLineBracket: {
623 luPixel halfWidth = getWidth()/2;
624 drawBigRoundBracket( painter, context, leftLineBracket,
625 myX-halfWidth, myY, mySize );
628 case RightLineBracket: {
629 luPixel halfWidth = getWidth()/2;
630 drawBigRoundBracket( painter, context, rightLineBracket,
631 myX-halfWidth, myY, mySize );
635 if ( cmChar != -1 ) {
636 drawCMDelimiter( painter, context, myX, myY, mySize );
639 case BackSlashBracket:
640 if ( cmChar != -1 ) {
641 drawCMDelimiter( painter, context, myX, myY, mySize );
644 case LeftCornerBracket:
645 if ( cmChar != -1 ) {
646 drawCMDelimiter( painter, context, myX, myY, mySize );
648 else drawCharacter(painter, context, myX, myY, mySize, leftAngleBracketChar);
650 case RightCornerBracket:
651 if ( cmChar != -1 ) {
652 drawCMDelimiter( painter, context, myX, myY, mySize );
654 else drawCharacter(painter, context, myX, myY, mySize, rightAngleBracketChar);
656 case LeftRoundBracket:
657 if ( cmChar != -1 ) {
658 drawCMDelimiter( painter, context, myX, myY, mySize );
661 drawBigRoundBracket( painter, context, leftRoundBracket, myX, myY, mySize );
664 case RightRoundBracket:
665 if ( cmChar != -1 ) {
666 drawCMDelimiter( painter, context, myX, myY, mySize );
669 drawBigRoundBracket( painter, context, rightRoundBracket, myX, myY, mySize );
675 drawCharacter(painter, context, TQFont(
"cmex10" ), myX, myY, mySize, cmex_Int);
678 drawCharacter(painter, context, TQFont(
"cmex10" ), myX, myY, mySize, cmex_Sum);
681 drawCharacter(painter, context, TQFont(
"cmex10" ), myX, myY, mySize, cmex_Prod);
694void Artwork::calcCharSize(
const ContextStyle& style, luPt height, TQChar ch )
696 calcCharSize( style, style.getMathFont(), height, ch );
700void Artwork::drawCharacter( TQPainter& painter,
const ContextStyle& style,
701 luPixel x, luPixel y,
702 luPt height, TQChar ch )
704 drawCharacter( painter, style, style.getMathFont(), x, y, height, ch );
708void Artwork::calcCharSize(
const ContextStyle& style, TQFont f,
709 luPt height, TQChar c )
711 f.setPointSizeFloat( style.layoutUnitPtToPt( height ) );
715 LuPixelRect bound = fm.boundingRect( c );
721void Artwork::drawCharacter( TQPainter& painter,
const ContextStyle& style,
723 luPixel x, luPixel y, luPt height, uchar c )
727 painter.setFont( f );
729 style.layoutUnitToPixelY( y+getBaseline() ),
730 TQString( TQChar( c ) ) );
734void Artwork::calcRoundBracket(
const ContextStyle& style,
const TQChar chars[],
735 luPt height, luPt charHeight )
737 uchar uppercorner = chars[0];
738 uchar lowercorner = chars[1];
741 TQFont f = style.getBracketFont();
742 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
743 TQFontMetrics fm( f );
744 LuPtRect upperBound = fm.boundingRect( uppercorner );
745 LuPtRect lowerBound = fm.boundingRect( lowercorner );
749 luPt edgeHeight = style.
ptToLayoutUnitPt( upperBound.height()+lowerBound.height() );
753 setHeight( TQMAX( edgeHeight, height ) );
756void Artwork::drawBigRoundBracket( TQPainter& p,
const ContextStyle& style,
const TQChar chars[],
757 luPixel x, luPixel y, luPt charHeight )
759 uchar uppercorner = chars[0];
760 uchar lowercorner = chars[1];
761 uchar line = chars[2];
763 TQFont f = style.getBracketFont();
768 TQRect upperBound = fm.boundingRect(uppercorner);
769 TQRect lowerBound = fm.boundingRect(lowercorner);
770 TQRect lineBound = fm.boundingRect(line);
773 pixel ptY = style.layoutUnitToPixelY( y );
774 pixel height = style.layoutUnitToPixelY( getHeight() );
782 p.drawText( ptX, ptY-upperBound.top(), TQString( TQChar( uppercorner ) ) );
783 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
784 TQString( TQChar( lowercorner ) ) );
790 pixel gap = height - upperBound.height() - lowerBound.height();
791 pixel lineHeight = lineBound.height() - safety;
792 int lineCount = tqRound(
static_cast<double>( gap ) / lineHeight );
793 pixel start = upperBound.height()-lineBound.top() - safety;
795 for (
int i = 0; i < lineCount; i++) {
796 p.drawText( ptX, ptY+start+i*lineHeight, TQString(TQChar(line)));
798 pixel remaining = gap - lineCount*lineHeight;
799 pixel dist = ( lineHeight - remaining ) / 2;
800 p.drawText( ptX, ptY+height-upperBound.height()+dist-lineBound.height()-lineBound.top(),
801 TQString( TQChar( line ) ) );
804void Artwork::calcCurlyBracket(
const ContextStyle& style,
const TQChar chars[],
805 luPt height, luPt charHeight )
807 uchar uppercorner = chars[0];
808 uchar lowercorner = chars[1];
810 uchar middle = chars[3];
812 TQFont f = style.getBracketFont();
813 f.setPointSizeFloat( style.layoutUnitPtToPt( charHeight ) );
814 TQFontMetrics fm( f );
815 LuPtRect upperBound = fm.boundingRect( uppercorner );
816 LuPtRect lowerBound = fm.boundingRect( lowercorner );
818 LuPtRect middleBound = fm.boundingRect( middle );
823 middleBound.height() );
827 setHeight( TQMAX( edgeHeight, height ) );
830void Artwork::drawBigCurlyBracket( TQPainter& p,
const ContextStyle& style,
const TQChar chars[],
831 luPixel x, luPixel y, luPt charHeight )
834 TQFont f = style.getBracketFont();
838 uchar uppercorner = chars[0];
839 uchar lowercorner = chars[1];
840 uchar line = chars[2];
841 uchar middle = chars[3];
843 TQFontMetrics fm(p.fontMetrics());
844 TQRect upperBound = fm.boundingRect(uppercorner);
845 TQRect lowerBound = fm.boundingRect(lowercorner);
846 TQRect middleBound = fm.boundingRect(middle);
847 TQRect lineBound = fm.boundingRect(line);
850 pixel ptY = style.layoutUnitToPixelY( y );
851 pixel height = style.layoutUnitToPixelY( getHeight() );
856 p.drawText( ptX, ptY-upperBound.top(), TQString( TQChar( uppercorner ) ) );
857 p.drawText( ptX, ptY+(height-middleBound.height())/2-middleBound.top(),
858 TQString( TQChar( middle ) ) );
859 p.drawText( ptX, ptY+height-lowerBound.top()-lowerBound.height(),
860 TQString( TQChar( lowercorner ) ) );
868 pixel lineHeight = lineBound.height() - safety;
869 pixel gap = height/2 - upperBound.height() - middleBound.height() / 2;
872 TQString ch = TQString(TQChar(line));
873 int lineCount = tqRound( gap / lineHeight ) + 1;
875 pixel start = (height - middleBound.height()) / 2 + safety;
876 for (
int i = 0; i < lineCount; i++) {
877 p.drawText( ptX, ptY-lineBound.top()+TQMAX( start-(i+1)*lineHeight,
878 upperBound.width() ),
882 start = (height + middleBound.height()) / 2 - safety;
883 for (
int i = 0; i < lineCount; i++) {
884 p.drawText( ptX, ptY-lineBound.top()+TQMIN( start+i*lineHeight,
885 height-upperBound.width()-lineBound.height() ),
891KFORMULA_NAMESPACE_END
Contains all the style information for the formela.
luPt getAdjustedSize(TextStyle tstyle, double factor) const
Calculates the font size corresponding to the given TextStyle.
TextStyle
Textstyles like in TeX.
bool init(ContextStyle *context, bool install=true)
lazy init support.
static void information(TQWidget *parent, const TQString &text, const TQString &caption=TQString::null, const TQString &dontShowAgainName=TQString::null, int options=Notify)
double layoutUnitToFontSize(int luSize, bool) const
Given the font size for the font in layout units, in pt (use pointSize()) this returns the font size ...
static double ptToLayoutUnitPt(double pt)
Not zoom dependent.
int layoutUnitToPixelX(int lupix) const
The "layout unit pixel" -> "[zoomed] view pixel" conversions.