00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <qpainter.h>
00030 #include <qbitmap.h>
00031 #include <qpixmap.h>
00032 #include <math.h>
00033 #include <limits.h>
00034
00035 #include <KDDrawText.h>
00036
00037 #ifndef M_PI
00038 #define M_PI 3.14159265358979323846
00039 #endif
00040
00041 void KDDrawText::drawRotatedText( QPainter* painter,
00042 float degrees,
00043 QPoint anchor,
00044 const QString& text,
00045 const QFont* font,
00046 int align,
00047 bool showAnchor,
00048 const QFontMetrics* fontMet,
00049 bool noFirstrotate,
00050 bool noBackrotate,
00051 KDDrawTextRegionAndTrueRect* infos,
00052 bool optimizeOutputForScreen )
00053 {
00054 drawRotatedTxt( painter,
00055 optimizeOutputForScreen,
00056 degrees,
00057 anchor,
00058 text,
00059 font,
00060 align,
00061 showAnchor,
00062 INT_MAX,
00063 INT_MAX,
00064 fontMet,
00065 false,
00066 0 != infos,
00067 noFirstrotate,
00068 noBackrotate,
00069 infos );
00070 }
00071
00072
00073 KDDrawTextRegionAndTrueRect KDDrawText::measureRotatedText(
00074 QPainter* painter,
00075 float degrees,
00076 QPoint anchor,
00077 const QString& text,
00078 const QFont* font,
00079 int align,
00080 const QFontMetrics* fontMet,
00081 bool noFirstrotate,
00082 bool noBackrotate,
00083 int addPercentOfHeightToRegion )
00084 {
00085 KDDrawTextRegionAndTrueRect infos;
00086 drawRotatedTxt( painter,
00087 false,
00088 degrees,
00089 anchor,
00090 text,
00091 font,
00092 align,
00093 false,
00094 INT_MAX,
00095 INT_MAX,
00096 fontMet,
00097 true,
00098 false,
00099 noFirstrotate,
00100 noBackrotate,
00101 &infos,
00102 addPercentOfHeightToRegion );
00103 return infos;
00104 }
00105
00106
00107 void KDDrawText::drawRotatedTxt( QPainter* painter,
00108 bool optimizeOutputForScreen,
00109 float degrees,
00110 QPoint anchor,
00111 const QString& text,
00112 const QFont* font,
00113 int align,
00114 bool showAnchor,
00115 int txtWidth,
00116 int txtHeight,
00117 const QFontMetrics* fontMet,
00118 bool calculateOnly,
00119 bool doNotCalculate,
00120 bool noFirstrotate,
00121 bool noBackrotate,
00122 KDDrawTextRegionAndTrueRect* infos,
00123 int addPercentOfHeightToRegion )
00124 {
00125
00126
00127
00128
00129 bool useInfos = doNotCalculate && infos;
00130 bool fontChanged = ( 0 != font );
00131 QFont oldFont;
00132 if( fontChanged ) {
00133 oldFont = painter->font();
00134 painter->setFont( *font );
00135 }
00136 else
00137 font = &painter->font();
00138
00139 bool mustBackrotate = false;
00140 if( !optimizeOutputForScreen && !noFirstrotate ){
00141 painter->rotate( degrees );
00142 if( !noBackrotate )
00143 mustBackrotate = true;
00144 }
00145
00146 QPoint pos = useInfos ? infos->pos : painter->xFormDev( anchor );
00147
00148 if( useInfos )
00149 {
00150 txtWidth = infos->width;
00151 txtHeight = infos->height;
00152 }
00153 else
00154 {
00155 int newHeight=0;
00156
00157
00158
00159 QFontMetrics* pFM=0;
00160 if( ! pFM ) {
00161 pFM = new QFontMetrics( painter->fontMetrics() );
00162 } else {
00163 pFM = const_cast<QFontMetrics*>(fontMet);
00164 }
00165
00166 int nLF = text.contains('\n');
00167 if( INT_MAX == txtWidth ) {
00168 if( nLF ){
00169 int tw;
00170 txtWidth = 0;
00171 int i0 = 0;
00172 int iLF = text.find('\n');
00173 while( -1 != iLF ){
00174 const QRect r(pFM->boundingRect( text.mid(i0, iLF-i0) ));
00175 tw = r.width()+ 2;
00176 newHeight = r.height();
00177 if( tw > txtWidth )
00178 txtWidth = tw;
00179 i0 = iLF+1;
00180 iLF = text.find('\n', i0);
00181 }
00182 if( iLF < (int)text.length() ){
00183 const QRect r(pFM->boundingRect( text.mid( i0 ) ));
00184 tw = r.width()+2;
00185 newHeight = r.height();
00186 if( tw > txtWidth )
00187 txtWidth = tw;
00188 i0 = iLF+1;
00189 }
00190 }else{
00191 const QRect r(painter->boundingRect( 0,0,1,1, Qt::AlignAuto, text ));
00192
00193
00194 txtWidth = r.width()+2;
00195 newHeight = r.height()+2;
00196 }
00197 }
00198 if( INT_MAX == txtWidth || INT_MAX == txtHeight ) {
00199 txtHeight = newHeight ? newHeight : pFM->height() * (1+nLF);
00200 }
00201 if( pFM != fontMet )
00202 delete pFM;
00203 if( infos ) {
00204 infos->pos = pos;
00205
00206 infos->width = txtWidth;
00207 infos->height = txtHeight;
00208 }
00209 }
00210 if( showAnchor ) {
00211 int d = txtHeight/4;
00212 QPen savePen = painter->pen();
00213 painter->setPen( QColor( Qt::darkRed ) );
00214 painter->drawLine( pos.x(), pos.y()-d,
00215 pos.x(), pos.y()+d );
00216 painter->drawLine( pos.x()-d, pos.y(),
00217 pos.x()+d, pos.y() );
00218 painter->setPen( savePen );
00219 }
00220 int x = useInfos ? infos->x : pos.x();
00221 int y = useInfos ? infos->y : pos.y();
00222
00223
00224
00225
00226
00227
00228
00229 if( !useInfos && !optimizeOutputForScreen ) {
00230 switch( align & ( Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter ) ) {
00231 case Qt::AlignLeft:
00232 break;
00233 case Qt::AlignRight:
00234
00235 x -= txtWidth;
00236 break;
00237 case Qt::AlignHCenter:
00238 x -= txtWidth - txtWidth/2;
00239 break;
00240 }
00241 switch( align & ( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter ) ) {
00242 case Qt::AlignTop:
00243 break;
00244 case Qt::AlignBottom:
00245 y -= txtHeight;
00246 break;
00247 case Qt::AlignVCenter:
00248 y -= txtHeight/2;
00249 break;
00250 }
00251 }
00252 if( infos && !useInfos ) {
00253 painter->xForm( pos );
00254 infos->x = x - 4;
00255 infos->y = y - 4;
00256
00257
00258
00259
00260
00261
00262
00263 QRect rect( painter->boundingRect( x, y,
00264 txtWidth, txtHeight,
00265 Qt::AlignLeft + Qt::AlignTop,
00266 text ) );
00267
00268
00269 QPoint topLeft( painter->xForm( rect.topLeft() ) );
00270 QPoint topRight( painter->xForm( rect.topRight() ) );
00271 QPoint bottomRight( painter->xForm( rect.bottomRight() ) );
00272 QPoint bottomLeft( painter->xForm( rect.bottomLeft() ) );
00273
00274 int additor = addPercentOfHeightToRegion * txtHeight / 100;
00275 QPointArray points;
00276 points.setPoints( 4, topLeft.x()-additor, topLeft.y()-additor,
00277 topRight.x()+additor, topRight.y()-additor,
00278 bottomRight.x()+additor, bottomRight.y()+additor,
00279 bottomLeft.x()-additor, bottomLeft.y()+additor );
00280 infos->region = QRegion( points );
00281 }
00282
00283
00284
00285 {
00286 int d = txtHeight/4;
00287 QPen savePen = painter->pen();
00288 if( showAnchor ) {
00289 painter->setPen( QColor( Qt::blue ) );
00290 painter->drawLine( x, y-d,
00291 x, y+d );
00292 painter->drawLine( x-d, y,
00293 x+d, y );
00294 painter->setPen( QColor( Qt::darkGreen ) );
00295 painter->drawRect(x,y,txtWidth,txtHeight);
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 }
00306 painter->setPen( savePen );
00307 }
00308
00309 if( mustBackrotate && optimizeOutputForScreen ){
00310 painter->rotate( -degrees );
00311 mustBackrotate = false;
00312 }
00313
00314 if( !calculateOnly ){
00315
00316 if( !optimizeOutputForScreen ){
00317
00318
00319
00320
00321
00322
00323 painter->drawText( x, y,
00324 txtWidth, txtHeight,
00325 Qt::AlignLeft + Qt::AlignTop,
00326 text );
00327
00328
00329
00330
00331
00332
00333 }else{
00334
00335 QPixmap pm( txtWidth+2, txtHeight+2, 1 );
00336
00337
00338
00339 pm.fill(Qt::color0);
00340 QPainter p;
00341 p.begin( &pm );
00342 if( showAnchor ){
00343 p.drawRect(0,0, txtWidth,txtHeight);
00344 p.drawLine(0,0, txtWidth,txtHeight);
00345 p.drawLine(0,txtHeight, txtWidth,0);
00346 }
00347 p.setFont(painter->font());
00348
00349 p.drawText( 0, 0, txtWidth, txtHeight,
00350 Qt::AlignLeft + Qt::AlignTop,
00351 text );
00352
00353
00354
00355
00356
00357
00358
00359 QBitmap mask;
00360 mask = pm;
00361 pm.setMask( mask );
00362 QWMatrix m;
00363 m.rotate( degrees );
00364 QPixmap theRotatedPixmap = pm.xForm(m);
00365
00366
00367 double degreesRad = degrees;
00368 while( degreesRad > 360 )
00369 degreesRad -= 360;
00370 degreesRad *= M_PI / 180.0;
00371 double cosA = cos( degreesRad );
00372 double sinA = sin( degreesRad );
00373 QPoint pTopLeft( 0,
00374 0 );
00375 QPoint pBotLeft( static_cast < int > ( 0 * cosA - txtHeight * sinA ),
00376 static_cast < int > ( txtHeight * cosA + 0 * sinA ) );
00377 QPoint pTopRight( static_cast < int > ( txtWidth * cosA - 0 * sinA ),
00378 static_cast < int > ( 0 * cosA + txtWidth * sinA ) );
00379 QPoint pBotRight( static_cast < int > ( txtWidth * cosA - txtHeight * sinA ),
00380 static_cast < int > ( txtHeight * cosA + txtWidth * sinA ) );
00381
00382
00383
00384 {
00385 QPoint pDeltaTL( QMIN(0, QMIN(pBotLeft.x(), QMIN(pTopRight.x(), pBotRight.x()))),
00386 QMIN(0, QMIN(pBotLeft.y(), QMIN(pTopRight.y(), pBotRight.y()))) );
00387 pTopLeft -= pDeltaTL;
00388 pBotLeft -= pDeltaTL;
00389 pTopRight -= pDeltaTL;
00390 pBotRight -= pDeltaTL;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 int hAlign = align & ( Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter );
00414 int vAlign = align & ( Qt::AlignTop | Qt::AlignBottom | Qt::AlignVCenter );
00415
00416 QPoint pixPoint;
00417 switch( hAlign ) {
00418 case Qt::AlignLeft:
00419 switch( vAlign ) {
00420 case Qt::AlignTop:
00421 pixPoint = pTopLeft;
00422 break;
00423 case Qt::AlignBottom:
00424 pixPoint = pBotLeft;
00425 break;
00426 case Qt::AlignVCenter:
00427 default:
00428 pixPoint = QPoint( (pTopLeft.x() + pBotLeft.x()) / 2,
00429 (pTopLeft.y() + pBotLeft.y()) / 2 );
00430 break;
00431 }
00432 break;
00433 case Qt::AlignRight:
00434 switch( vAlign ) {
00435 case Qt::AlignTop:
00436 pixPoint = pTopRight;
00437 break;
00438 case Qt::AlignBottom:
00439 pixPoint = pBotRight;
00440 break;
00441 case Qt::AlignVCenter:
00442 default:
00443 pixPoint = QPoint( (pTopRight.x() + pBotRight.x()) / 2,
00444 (pTopRight.y() + pBotRight.y()) / 2 );
00445 break;
00446 }
00447 break;
00448 case Qt::AlignHCenter:
00449 default:
00450 switch( vAlign ) {
00451 case Qt::AlignTop:
00452 pixPoint = QPoint( (pTopLeft.x() + pTopRight.x()) / 2,
00453 (pTopLeft.y() + pTopRight.y()) / 2 );
00454 break;
00455 case Qt::AlignBottom:
00456 pixPoint = QPoint( (pBotLeft.x() + pBotRight.x()) / 2,
00457 (pBotLeft.y() + pBotRight.y()) / 2 );
00458 break;
00459 case Qt::AlignVCenter:
00460 default:
00461 pixPoint = QPoint( (pTopLeft.x() + pBotRight.x()) / 2,
00462 (pTopLeft.y() + pBotRight.y()) / 2 );
00463 break;
00464 }
00465 break;
00466 }
00467
00468
00469 painter->drawPixmap( QPoint( x - pixPoint.x(),
00470 y - pixPoint.y() ),
00471 theRotatedPixmap );
00472 p.end();
00473 }
00474 }
00475
00476 if( mustBackrotate )
00477 painter->rotate( -degrees );
00478
00479 if( fontChanged )
00480 painter->setFont( oldFont );
00481 }
00482
00483