00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qstring.h>
00022 #include <qtextcodec.h>
00023 #include <qfile.h>
00024
00025 #include <klocale.h>
00026 #include <kdebug.h>
00027
00028 #include <KWEFUtil.h>
00029 #include <KWEFBaseWorker.h>
00030
00031 #include "ExportFilter.h"
00032 #include "ExportCss.h"
00033
00034 QString HtmlCssWorker::escapeCssIdentifier(const QString& strText) const
00035 {
00036
00037
00038
00039
00040
00041 QString strReturn;
00042
00043
00044 const QChar qch0(strText[0]);
00045 if ((qch0<'a' || qch0>'z') && (qch0<'A' || qch0>'Z'))
00046 {
00047
00048 strReturn+="kWoRd_";
00049
00050 }
00051
00052 for (uint i=0; i<strText.length(); i++)
00053 {
00054 const QChar qch(strText.at(i));
00055 const ushort ch=qch.unicode();
00056
00057 if (((ch>='a') && (ch<='z'))
00058 || ((ch>='A') && (ch<='Z'))
00059 || ((ch>='0') && (ch<='9'))
00060 || (ch=='-') || (ch=='_'))
00061 {
00062
00063 strReturn+=qch;
00064 }
00065 else if ((ch<=' ') || (ch>=128 && ch<=160))
00066 {
00067
00068 strReturn+='_';
00069 }
00070 else if ((ch>=161) && (getCodec()->canEncode(qch)))
00071 {
00072
00073
00074 strReturn+=qch;
00075 }
00076 else
00077 {
00078
00079
00080
00081 strReturn+="--";
00082 strReturn+=QString::number(ch,16);
00083 strReturn+="--";
00084 }
00085 }
00086 return strReturn;
00087 }
00088
00089 QString HtmlCssWorker::textFormatToCss(const TextFormatting& formatOrigin,
00090 const TextFormatting& formatData, const bool force) const
00091 {
00092
00093
00094
00095
00096 QString strElement;
00097
00098
00099 QString fontName = formatData.fontName;
00100 if (!fontName.isEmpty()
00101 && (force || (formatOrigin.fontName!=formatData.fontName)))
00102 {
00103 strElement+="font-family: ";
00104 if (fontName.find(' ')==-1)
00105 strElement+=escapeHtmlText(fontName);
00106 else
00107 {
00108 strElement+='\'';
00109 strElement+=escapeHtmlText(fontName);
00110 strElement+='\'';
00111 }
00112
00113 strElement+="; ";
00114 }
00115
00116 if (force || (formatOrigin.italic!=formatData.italic))
00117 {
00118
00119 strElement+="font-style: ";
00120 if ( formatData.italic )
00121 {
00122 strElement+="italic";
00123 }
00124 else
00125 {
00126 strElement+="normal";
00127 }
00128 strElement+="; ";
00129 }
00130
00131 if (force || ((formatOrigin.weight>=75)!=(formatData.weight>=75)))
00132 {
00133 strElement+="font-weight: ";
00134 if ( formatData.weight >= 75 )
00135 {
00136 strElement+="bold";
00137 }
00138 else
00139 {
00140 strElement+="normal";
00141 }
00142 strElement+="; ";
00143 }
00144
00145 if (force || (formatOrigin.fontSize!=formatData.fontSize))
00146 {
00147 const int size=formatData.fontSize;
00148 if (size>0)
00149 {
00150
00151 strElement+="font-size: ";
00152 strElement+=QString::number(size,10);
00153 strElement+="pt; ";
00154 }
00155 }
00156
00157 if (force || (formatOrigin.fgColor!=formatData.fgColor))
00158 {
00159 if ( formatData.fgColor.isValid() )
00160 {
00161
00162 strElement+="color: ";
00163 strElement+=formatData.fgColor.name();
00164 strElement+="; ";
00165 }
00166 }
00167
00168 if (force || (formatOrigin.bgColor!=formatData.bgColor))
00169 {
00170 if ( formatData.bgColor.isValid() )
00171 {
00172
00173 strElement+="background-color: ";
00174 strElement+=formatData.bgColor.name();
00175 strElement+="; ";
00176 }
00177 }
00178
00179 if (force || (formatOrigin.underline!=formatData.underline)
00180 || (formatOrigin.strikeout!=formatData.strikeout))
00181 {
00182 strElement+="text-decoration: ";
00183 if ( formatData.underline )
00184 {
00185 strElement+="underline";
00186 }
00187 else if ( formatData.strikeout )
00188 {
00189 strElement+="line-through";
00190 }
00191 else
00192 {
00193 strElement+="none";
00194 }
00195 strElement+="; ";
00196 }
00197
00198 if (force || (formatOrigin.fontAttribute!=formatData.fontAttribute))
00199 {
00200 bool smallcaps=false;
00201 strElement+="text-transform: ";
00202 if ( formatData.fontAttribute=="uppercase" )
00203 {
00204 strElement+="uppercase";
00205 }
00206 else if ( formatData.fontAttribute=="lowercase" )
00207 {
00208 strElement+="lowercase";
00209 }
00210 else if ( formatData.fontAttribute=="smallcaps" )
00211 {
00212 strElement+="none";
00213 smallcaps=true;
00214 }
00215 else
00216 {
00217 strElement+="none";
00218 }
00219 strElement+="; ";
00220
00221 strElement+="font-variant:";
00222 if (smallcaps)
00223 strElement+="small-caps";
00224 else
00225 strElement+="normal";
00226 strElement+="; ";
00227 }
00228
00229
00230
00231 return strElement;
00232 }
00233
00234 QString HtmlCssWorker::getStartOfListOpeningTag(const CounterData::Style typeList, bool& ordered)
00235 {
00236 QString strResult;
00237 switch (typeList)
00238 {
00239 case CounterData::STYLE_CUSTOMBULLET:
00240 default:
00241 {
00242 ordered=false;
00243 strResult="<ul>\n";
00244 break;
00245 }
00246 case CounterData::STYLE_NONE:
00247 {
00248 ordered=false;
00249 strResult="<ul style=\"list-style-type:none\">\n";
00250 break;
00251 }
00252 case CounterData::STYLE_CIRCLEBULLET:
00253 {
00254 ordered=false;
00255 strResult="<ul style=\"list-style-type:circle\">\n";
00256 break;
00257 }
00258 case CounterData::STYLE_SQUAREBULLET:
00259 {
00260 ordered=false;
00261 strResult="<ul style=\"list-style-type:square\">\n";
00262 break;
00263 }
00264 case CounterData::STYLE_DISCBULLET:
00265 {
00266 ordered=false;
00267 strResult="<ul style=\"list-style-type:disc\">\n";
00268 break;
00269 }
00270 case CounterData::STYLE_NUM:
00271 {
00272 ordered=true;
00273 strResult="<ol style=\"list-style-type:decimal\">\n";
00274 break;
00275 }
00276 case CounterData::STYLE_ALPHAB_L:
00277 {
00278 ordered=true;
00279 strResult="<ol style=\"list-style-type:lower-alpha\">\n";
00280 break;
00281 }
00282 case CounterData::STYLE_ALPHAB_U:
00283 {
00284 ordered=true;
00285 strResult="<ol style=\"list-style-type:upper-alpha\">\n";
00286 break;
00287 }
00288 case CounterData::STYLE_ROM_NUM_L:
00289 {
00290 ordered=true;
00291 strResult="<ol style=\"list-style-type:lower-roman\">\n";
00292 break;
00293 }
00294 case CounterData::STYLE_ROM_NUM_U:
00295 {
00296 ordered=true;
00297 strResult="<ol style=\"list-style-type:upper-roman\">\n";
00298 break;
00299 }
00300 case CounterData::STYLE_CUSTOM:
00301 {
00302
00303 ordered=true;
00304 strResult="<ol>\n";
00305 break;
00306 }
00307 }
00308 return strResult;
00309 }
00310
00311 QString HtmlCssWorker::layoutToCss(const LayoutData& layoutOrigin,
00312 const LayoutData& layout, const bool force) const
00313 {
00314 QString strLayout;
00315
00316 if (force || (layoutOrigin.alignment!=layout.alignment))
00317 {
00318 if ( (layout.alignment=="left") || (layout.alignment== "right")
00319 || (layout.alignment=="center") || (layout.alignment=="justify"))
00320 {
00321 strLayout += QString("text-align:%1; ").arg(layout.alignment);
00322 }
00323 else if ( layout.alignment=="auto")
00324 {
00325
00326 }
00327 else
00328 {
00329 kdWarning(30503) << "Unknown alignment: " << layout.alignment << endl;
00330 }
00331 }
00332
00333 if ((layout.indentLeft>=0.0)
00334 && (force || (layoutOrigin.indentLeft!=layout.indentLeft)))
00335 {
00336 strLayout += QString("margin-left:%1pt; ").arg(layout.indentLeft);
00337 }
00338
00339 if ((layout.indentRight>=0.0)
00340 && (force || (layoutOrigin.indentRight!=layout.indentRight)))
00341 {
00342 strLayout += QString("margin-right:%1pt; ").arg(layout.indentRight);
00343 }
00344
00345 if (force || (layoutOrigin.indentLeft!=layout.indentLeft))
00346 {
00347 strLayout += QString("text-indent:%1pt; ").arg(layout.indentFirst);
00348 }
00349
00350 if ((layout.marginBottom>=0.0)
00351 && ( force || ( layoutOrigin.marginBottom != layout.marginBottom ) ) )
00352 {
00353 strLayout += QString("margin-bottom:%1pt; ").arg(layout.marginBottom);
00354 }
00355
00356 if ((layout.marginTop>=0.0)
00357 && ( force || ( layoutOrigin.marginTop != layout.marginTop ) ) )
00358 {
00359 strLayout += QString("margin-top:%1pt; ").arg(layout.marginTop);
00360 }
00361
00362 if (force
00363 || ( layoutOrigin.lineSpacingType != layout.lineSpacingType )
00364 || ( layoutOrigin.lineSpacing != layout.lineSpacing ) )
00365 {
00366 switch ( layout.lineSpacingType )
00367 {
00368 case LayoutData::LS_CUSTOM:
00369 {
00370
00371 #if 0
00372
00373 const QString height ( QString::number(layout.lineSpacing) );
00374 strLayout += "style:line-spacing:";
00375 strLayout += height;
00376 strLayout += "pt; ";
00377 #endif
00378 break;
00379 }
00380 case LayoutData::LS_SINGLE:
00381 {
00382 strLayout += "line-height:normal; ";
00383 break;
00384 }
00385 case LayoutData::LS_ONEANDHALF:
00386 {
00387 strLayout += "line-height:150%; ";
00388 break;
00389 }
00390 case LayoutData::LS_DOUBLE:
00391 {
00392 strLayout += "line-height:200%; ";
00393 break;
00394 }
00395 case LayoutData::LS_MULTIPLE:
00396 {
00397 const QString mult ( QString::number( qRound( layout.lineSpacing * 100 ) ) );
00398 strLayout += "line-height:";
00399 strLayout += mult;
00400 strLayout += "%; ";
00401 break;
00402 }
00403 case LayoutData::LS_FIXED:
00404 {
00405
00406 const QString height ( QString::number(layout.lineSpacing) );
00407 strLayout += "line-height:";
00408 strLayout += height;
00409 strLayout += "pt; ";
00410 break;
00411 }
00412 case LayoutData::LS_ATLEAST:
00413 {
00414
00415
00416
00417 const QString height ( QString::number(layout.lineSpacing) );
00418 strLayout += "line-height:";
00419 strLayout += height;
00420 strLayout += "pt; ";
00421 break;
00422 }
00423 default:
00424 {
00425 kdWarning(30503) << "Unsupported lineSpacingType: " << layout.lineSpacingType << " (Ignoring!)" << endl;
00426 break;
00427 }
00428 }
00429 }
00430
00431
00432 if (!force
00433 && ( layoutOrigin.shadowDirection == layout.shadowDirection )
00434 && ( layoutOrigin.shadowDistance == layout.shadowDistance ) )
00435 {
00436
00437 }
00438 else if ((!layout.shadowDirection) || (!layout.shadowDistance))
00439 {
00440 strLayout += "text-shadow:";
00441 strLayout+="none; ";
00442 }
00443 else
00444 {
00445 double xDistance,yDistance;
00446 const double distance=layout.shadowDistance;
00447 switch (layout.shadowDirection)
00448 {
00449 case 1:
00450 {
00451 xDistance= (-distance);
00452 yDistance= (-distance);
00453 break;
00454 }
00455 case 2:
00456 {
00457 xDistance= 0;
00458 yDistance= (-distance);
00459 break;
00460 }
00461 case 3:
00462 {
00463 xDistance= (distance);
00464 yDistance= (-distance);
00465 break;
00466 }
00467 case 4:
00468 {
00469 xDistance= (distance);
00470 yDistance= 0;
00471 break;
00472 }
00473 case 5:
00474 {
00475 xDistance= (distance);
00476 yDistance= (distance);
00477 break;
00478 }
00479 case 6:
00480 {
00481 xDistance= 0;
00482 yDistance= (distance);
00483 break;
00484 }
00485 case 7:
00486 {
00487 xDistance= (-distance);
00488 yDistance= (distance);
00489 break;
00490 }
00491 case 8:
00492 {
00493 xDistance= (distance);
00494 yDistance= 0;
00495 break;
00496 }
00497 default:
00498 {
00499 xDistance=0;
00500 yDistance=0;
00501 break;
00502 }
00503 }
00504 if ( (!xDistance) && (!yDistance) )
00505 {
00506 strLayout += "text-shadow:";
00507 strLayout+="none; ";
00508 }
00509 else
00510 {
00511 strLayout += "text-shadow:";
00512 strLayout+=QString("%1 %2pt %3pt; ").arg(layout.shadowColor.name())
00513 .arg(xDistance,0,'f',0).arg(yDistance,0,'f',0);
00514
00515 }
00516 }
00517
00518
00519
00520
00521 strLayout+=textFormatToCss(layoutOrigin.formatData.text,
00522 layout.formatData.text,force);
00523
00524 return strLayout;
00525 }
00526
00527 void HtmlCssWorker::openParagraph(const QString& strTag,
00528 const LayoutData& layout, QChar::Direction direction)
00529 {
00530 const LayoutData& styleLayout=m_styleMap[layout.styleName];
00531
00532 *m_streamOut << '<' << strTag;
00533
00534
00535 *m_streamOut << " class=\"" << escapeCssIdentifier(layout.styleName);
00536 *m_streamOut << "\"";
00537
00538 QString strStyle=layoutToCss(styleLayout,layout,false);
00539 if (!strStyle.isEmpty())
00540 {
00541 *m_streamOut << " style=\"" << strStyle;
00542 if (direction == QChar::DirRLE) {
00543 *m_streamOut << "direction: rtl; unicode-bidi: embed; ";
00544 } else if (direction == QChar::DirRLO) {
00545 *m_streamOut << "direction: rtl; unicode-bidi: override; ";
00546 }
00547 *m_streamOut<< "\"";
00548 }
00549
00550 *m_streamOut << ">";
00551
00552 if ( 1==layout.formatData.text.verticalAlignment )
00553 {
00554 *m_streamOut << "<sub>";
00555 }
00556 else if ( 2==layout.formatData.text.verticalAlignment )
00557 {
00558 *m_streamOut << "<sup>";
00559 }
00560 if ( layout.alignment == "center" ) *m_streamOut << "<center>";
00561 }
00562
00563 void HtmlCssWorker::closeParagraph(const QString& strTag,
00564 const LayoutData& layout)
00565 {
00566 if ( 2==layout.formatData.text.verticalAlignment )
00567 {
00568 *m_streamOut << "</sup>";
00569 }
00570 else if ( 1==layout.formatData.text.verticalAlignment )
00571 {
00572 *m_streamOut << "</sub>";
00573 }
00574
00575 if ( layout.alignment == "center" ) *m_streamOut << "</center>";
00576 *m_streamOut << "</" << strTag << ">\n";
00577 }
00578
00579 void HtmlCssWorker::openSpan(const FormatData& formatOrigin, const FormatData& format)
00580 {
00581 *m_streamOut << "<span style=\"";
00582 *m_streamOut << textFormatToCss(formatOrigin.text,format.text,false);
00583 *m_streamOut << "\">";
00584
00585 if ( 1==format.text.verticalAlignment )
00586 {
00587 *m_streamOut << "<sub>";
00588 }
00589 else if ( 2==format.text.verticalAlignment )
00590 {
00591 *m_streamOut << "<sup>";
00592 }
00593 }
00594
00595 void HtmlCssWorker::closeSpan(const FormatData& formatOrigin, const FormatData& format)
00596 {
00597 if ( 2==format.text.verticalAlignment )
00598 {
00599 *m_streamOut << "</sup>";
00600 }
00601 else if ( 1==format.text.verticalAlignment )
00602 {
00603 *m_streamOut << "</sub>";
00604 }
00605
00606 *m_streamOut << "</span>";
00607 }
00608
00609 bool HtmlCssWorker::doFullPaperFormat(const int format,
00610 const double width, const double height, const int orientation)
00611 {
00612 QString strWidth, strHeight, strUnits;
00613 KWEFUtil::GetNativePaperFormat(format, strWidth, strHeight, strUnits);
00614
00615 if ((strWidth.isEmpty())||(strHeight.isEmpty())||(strUnits.isEmpty()))
00616 {
00617
00618 strUnits="pt";
00619 strWidth=QString::number(width);
00620 strHeight=QString::number(height);
00621 }
00622 if (orientation==1)
00623 {
00624
00625 QString strTemp(strWidth);
00626 strWidth=strHeight;
00627 strHeight=strTemp;
00628 }
00629
00630 m_strPageSize="size: ";
00631 m_strPageSize+=strWidth;
00632 m_strPageSize+=strUnits;
00633 m_strPageSize+=" ";
00634 m_strPageSize+=strHeight;
00635 m_strPageSize+=strUnits;
00636 m_strPageSize+=";";
00637 return true;
00638 }
00639
00640 bool HtmlCssWorker::doFullPaperBorders (const double top, const double left,
00641 const double bottom, const double right)
00642 {
00643 m_strPaperBorders=" margin-top: ";
00644 m_strPaperBorders+=QString::number(top);
00645 m_strPaperBorders+="pt;\n";
00646 m_strPaperBorders+=" margin-left: ";
00647 m_strPaperBorders+=QString::number(left);
00648 m_strPaperBorders+="pt;\n";
00649 m_strPaperBorders+=" margin-bottom: ";
00650 m_strPaperBorders+=QString::number(bottom);
00651 m_strPaperBorders+="pt;\n";
00652 m_strPaperBorders+=" margin-right: ";
00653 m_strPaperBorders+=QString::number(right);
00654 m_strPaperBorders+="pt;\n";
00655
00656 return true;
00657 }
00658
00659 bool HtmlCssWorker::doOpenStyles(void)
00660 {
00661 *m_streamOut << "<style type=\"text/css\">\n";
00662 if (!isXML())
00663 {
00664
00665
00666 *m_streamOut << "<!--\n";
00667 }
00668
00669
00670 const QString strVersion("$Revision: 483471 $");
00671
00672
00673 *m_streamOut << "/* KWORD_CSS_EXPORT ="
00674 << strVersion.mid(10).remove('$')
00675 << "*/\n";
00676
00677
00678 *m_streamOut << "BODY\n{\n background-color: #FFFFFF\n}\n";
00679
00680 return true;
00681 }
00682
00683 bool HtmlCssWorker::doFullDefineStyle(LayoutData& layout)
00684 {
00685
00686 m_styleMap[layout.styleName]=layout;
00687
00688
00689
00690
00691 *m_streamOut << "." << escapeCssIdentifier(layout.styleName);
00692 *m_streamOut << "\n{\n " << layoutToCss(layout,layout,true) << "\n}\n";
00693
00694 return true;
00695 }
00696
00697 bool HtmlCssWorker::doCloseStyles(void)
00698 {
00699 if (!m_strPageSize.isEmpty())
00700 {
00701 *m_streamOut << "@page\n{\n ";
00702 *m_streamOut << m_strPageSize;
00703 *m_streamOut << "\n";
00704 *m_streamOut << m_strPaperBorders;
00705 *m_streamOut << "}\n";
00706 }
00707
00708 if (!isXML())
00709 {
00710
00711
00712 *m_streamOut << "-->\n";
00713 }
00714 *m_streamOut << "</style>\n";
00715
00716 return true;
00717 }
00718