00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <QApplication>
00027 # include <QBitmap>
00028 # include <QDir>
00029 # include <QFile>
00030 # include <QFileInfo>
00031 # include <QMap>
00032 # include <QImageReader>
00033 # include <QPainter>
00034 # include <QPalette>
00035 # include <QSvgRenderer>
00036 # include <QStyleOption>
00037 # include <sstream>
00038 #endif
00039
00040 #ifdef FC_OS_WIN32
00041 #define QTWEBKIT
00042 #endif
00043
00044 #ifdef QTWEBKIT
00045 #include <QWebView>
00046 #include <QWebFrame>
00047 #endif
00048
00049 #include <string>
00050 #include <Inventor/fields/SoSFImage.h>
00051
00052 #include <Base/Console.h>
00053 #include <App/Application.h>
00054
00055 #include "BitmapFactory.h"
00056 #include "Icons/images.cpp"
00057 #include "Icons/Feature.xpm"
00058 #include "Icons/Document.xpm"
00059 #include "Icons/BmpFactoryIcons.cpp"
00060
00061 using namespace Gui;
00062
00063 namespace Gui {
00064 class BitmapFactoryInstP
00065 {
00066 public:
00067 QMap<std::string, const char**> xpmMap;
00068 QMap<std::string, QPixmap> xpmCache;
00069 QStringList paths;
00070 };
00071 }
00072
00073 BitmapFactoryInst* BitmapFactoryInst::_pcSingleton = NULL;
00074
00075 BitmapFactoryInst& BitmapFactoryInst::instance(void)
00076 {
00077 if (_pcSingleton == NULL)
00078 {
00079 _pcSingleton = new BitmapFactoryInst;
00080 _pcSingleton->addPath(QLatin1String(":/icons/"));
00081 _pcSingleton->addPath(QLatin1String(":/Icons/"));
00082 _pcSingleton->addPath(QString::fromUtf8(App::GetApplication().GetHomePath()));
00083 _pcSingleton->addPath(QString::fromUtf8(App::GetApplication().Config()["UserAppData"].c_str()));
00084
00085 RegisterIcons();
00086 }
00087
00088 return *_pcSingleton;
00089 }
00090
00091 void BitmapFactoryInst::destruct (void)
00092 {
00093 if (_pcSingleton != 0)
00094 delete _pcSingleton;
00095 _pcSingleton = 0;
00096 }
00097
00098 BitmapFactoryInst::BitmapFactoryInst()
00099 {
00100 d = new BitmapFactoryInstP;
00101 restoreCustomPaths();
00102 }
00103
00104 BitmapFactoryInst::~BitmapFactoryInst()
00105 {
00106 delete d;
00107 }
00108
00109 void BitmapFactoryInst::addCustomPath(const QString& path)
00110 {
00111 Base::Reference<ParameterGrp> group = App::GetApplication().GetParameterGroupByPath
00112 ("User parameter:BaseApp/Preferences/Bitmaps");
00113 std::vector<std::string> paths = group->GetASCIIs("CustomPath");
00114 std::stringstream str;
00115 str << "CustomPath" << paths.size();
00116 group->SetASCII(str.str().c_str(), (const char*)path.toUtf8());
00117 }
00118
00119 void BitmapFactoryInst::restoreCustomPaths()
00120 {
00121 Base::Reference<ParameterGrp> group = App::GetApplication().GetParameterGroupByPath
00122 ("User parameter:BaseApp/Preferences/Bitmaps");
00123 std::vector<std::string> paths = group->GetASCIIs("CustomPath");
00124 for (std::vector<std::string>::iterator it = paths.begin(); it != paths.end(); ++it) {
00125 addPath(QString::fromUtf8(it->c_str()));
00126 }
00127 }
00128
00129 void BitmapFactoryInst::addPath(const QString& path)
00130 {
00131 d->paths.push_back(path);
00132 }
00133
00134 void BitmapFactoryInst::removePath(const QString& path)
00135 {
00136 int pos = d->paths.indexOf(path);
00137 if (pos != -1) d->paths.removeAt(pos);
00138 }
00139
00140 QStringList BitmapFactoryInst::findIconFiles() const
00141 {
00142 QStringList files, filters;
00143 QList<QByteArray> formats = QImageReader::supportedImageFormats();
00144 for (QList<QByteArray>::iterator it = formats.begin(); it != formats.end(); ++it)
00145 filters << QString::fromAscii("*.%1").arg(QString::fromAscii(*it).toLower());
00146
00147 QStringList paths = d->paths;
00148 #if QT_VERSION >= 0x040500
00149 paths.removeDuplicates();
00150 #endif
00151 for (QStringList::ConstIterator pt = paths.begin(); pt != paths.end(); ++pt) {
00152 QDir d(*pt);
00153 d.setNameFilters(filters);
00154 QFileInfoList fi = d.entryInfoList();
00155 for (QFileInfoList::iterator it = fi.begin(); it != fi.end(); ++it)
00156 files << it->absoluteFilePath();
00157 }
00158
00159 return files;
00160 }
00161
00162 void BitmapFactoryInst::addXPM(const char* name, const char** pXPM)
00163 {
00164 d->xpmMap[name] = pXPM;
00165 }
00166
00167 void BitmapFactoryInst::addPixmapToCache(const char* name, const QPixmap& icon)
00168 {
00169 d->xpmCache[name] = icon;
00170 }
00171
00172 bool BitmapFactoryInst::findPixmapInCache(const char* name, QPixmap& px) const
00173 {
00174 QMap<std::string, QPixmap>::ConstIterator it = d->xpmCache.find(name);
00175 if (it != d->xpmCache.end()) {
00176 px = it.value();
00177 return true;
00178 }
00179 return false;
00180 }
00181
00182 QPixmap BitmapFactoryInst::pixmap(const char* name) const
00183 {
00184 if (!name || *name == '\0')
00185 return QPixmap(px);
00186
00187
00188 QMap<std::string, QPixmap>::ConstIterator it = d->xpmCache.find(name);
00189 if (it != d->xpmCache.end())
00190 return it.value();
00191
00192
00193 QPixmap icon;
00194 QMap<std::string,const char**>::ConstIterator It = d->xpmMap.find(name);
00195 if (It != d->xpmMap.end())
00196 icon = QPixmap(It.value());
00197
00198
00199 QString fn = QString::fromUtf8(name);
00200 if (icon.isNull() && QFile(fn).exists())
00201 icon.load(fn);
00202
00203
00204 if (icon.isNull()) {
00205 icon = pixmapFromSvg(name, QSize(24,24));
00206 }
00207
00208
00209 if (icon.isNull()) {
00210 bool found = false;
00211 QList<QByteArray> formats = QImageReader::supportedImageFormats();
00212 for (QStringList::ConstIterator pt = d->paths.begin(); pt != d->paths.end() && !found; ++pt) {
00213 QDir d(*pt);
00214 QString fileName = d.filePath(fn);
00215 if (QFile(fileName).exists()) {
00216 icon.load(fileName);
00217 found = true;
00218 break;
00219 } else {
00220 for (QList<QByteArray>::iterator fm = formats.begin(); fm != formats.end(); ++fm) {
00221 QString path = QString::fromAscii("%1.%2").arg(fileName).
00222 arg(QString::fromAscii((*fm).toLower().constData()));
00223 if (QFile(path).exists()) {
00224 icon.load(path);
00225 found = true;
00226 break;
00227 }
00228 }
00229 }
00230 }
00231 }
00232
00233 if (!icon.isNull()) {
00234 d->xpmCache[name] = icon;
00235 return icon;
00236 }
00237
00238 Base::Console().Warning("Cannot find icon: %s\n", name);
00239 return QPixmap(px);
00240 }
00241
00242 QPixmap BitmapFactoryInst::pixmapFromSvg(const char* name, const QSize& size) const
00243 {
00244
00245 QPixmap icon;
00246 QString iconPath;
00247 QString fn = QString::fromUtf8(name);
00248 if (QFile(fn).exists())
00249 iconPath = fn;
00250
00251
00252 if (iconPath.isEmpty()) {
00253 for (QStringList::ConstIterator pt = d->paths.begin(); pt != d->paths.end(); ++pt) {
00254 QDir d(*pt);
00255 QString fileName = d.filePath(fn);
00256 if (QFile(fileName).exists()) {
00257 iconPath = fileName;
00258 break;
00259 } else {
00260 fileName += QLatin1String(".svg");
00261 if (QFile(fileName).exists()) {
00262 iconPath = fileName;
00263 break;
00264 }
00265 }
00266 }
00267 }
00268
00269 if (!iconPath.isEmpty()) {
00270 QFile file(iconPath);
00271 if (file.open(QFile::ReadOnly | QFile::Text)) {
00272 QByteArray content = file.readAll();
00273 icon = pixmapFromSvg(content, size);
00274 }
00275 }
00276
00277 return icon;
00278 }
00279
00280 QPixmap BitmapFactoryInst::pixmapFromSvg(const QByteArray& contents, const QSize& size) const
00281 {
00282 #ifdef QTWEBKIT
00283 QWebView webView;
00284 QPalette pal = webView.palette();
00285 pal.setColor(QPalette::Background, Qt::transparent);
00286 webView.setPalette(pal);
00287 webView.setContent(contents, QString::fromAscii("image/svg+xml"));
00288 QString node = QString::fromAscii("document.rootElement.nodeName");
00289 QString root = webView.page()->mainFrame()->evaluateJavaScript(node).toString();
00290 if (root.isEmpty() || root.compare(QLatin1String("svg"), Qt::CaseInsensitive)) {
00291 return QPixmap();
00292 }
00293
00294 QString w = QString::fromAscii("document.rootElement.width.baseVal.value");
00295 QString h = QString::fromAscii("document.rootElement.height.baseVal.value");
00296 double ww = webView.page()->mainFrame()->evaluateJavaScript(w).toDouble();
00297 double hh = webView.page()->mainFrame()->evaluateJavaScript(h).toDouble();
00298 if (ww == 0.0 || hh == 0.0)
00299 return QPixmap();
00300 #endif
00301
00302 QImage image(size, QImage::Format_ARGB32_Premultiplied);
00303 image.fill(0x00000000);
00304
00305 QPainter p(&image);
00306 #ifdef QTWEBKIT
00307 qreal xs = size.isValid() ? size.width() / ww : 1.0;
00308 qreal ys = size.isValid() ? size.height() / hh : 1.0;
00309 p.scale(xs, ys);
00310
00311
00312 p.setRenderHint(QPainter::Antialiasing);
00313 p.setRenderHint(QPainter::TextAntialiasing);
00314 p.setRenderHint(QPainter::SmoothPixmapTransform);
00315 p.setOpacity(0);
00316 webView.page()->mainFrame()->render(&p);
00317 #else
00318
00319 Base::Console().SetEnabledMsgType("ReportOutput", ConsoleMsgType::MsgType_Wrn, false);
00320 QSvgRenderer svg(contents);
00321 Base::Console().SetEnabledMsgType("ReportOutput", ConsoleMsgType::MsgType_Wrn, true);
00322 svg.render(&p);
00323 #endif
00324 p.end();
00325
00326 return QPixmap::fromImage(image);
00327 }
00328
00329 QStringList BitmapFactoryInst::pixmapNames() const
00330 {
00331 QStringList names;
00332 for (QMap<std::string,const char**>::ConstIterator It = d->xpmMap.begin(); It != d->xpmMap.end(); ++It)
00333 names << QString::fromUtf8(It.key().c_str());
00334 for (QMap<std::string, QPixmap>::ConstIterator It = d->xpmCache.begin(); It != d->xpmCache.end(); ++It) {
00335 QString item = QString::fromUtf8(It.key().c_str());
00336 if (!names.contains(item))
00337 names << item;
00338 }
00339 return names;
00340 }
00341
00342 QPixmap BitmapFactoryInst::resize(int w, int h, const QPixmap& p, Qt::BGMode bgmode) const
00343 {
00344 if (bgmode == Qt::TransparentMode) {
00345 if (p.width() == 0 || p.height() == 0)
00346 w = 1;
00347
00348 QPixmap pix = p;
00349 int x = pix.width () > w ? 0 : (w - pix.width ())/2;
00350 int y = pix.height() > h ? 0 : (h - pix.height())/2;
00351
00352 if (x == 0 && y == 0)
00353 return pix;
00354
00355 QPixmap pm (w,h);
00356 QBitmap mask (w,h);
00357 mask.fill(Qt::color0);
00358
00359 QBitmap bm = pix.mask();
00360 if (!bm.isNull())
00361 {
00362 QPainter painter(&mask);
00363 painter.drawPixmap(QPoint(x, y), bm, QRect(0, 0, pix.width(), pix.height()));
00364 pm.setMask(mask);
00365 }
00366 else
00367 {
00368 pm.setMask(mask);
00369 pm = fillRect(x, y, pix.width(), pix.height(), pm, Qt::OpaqueMode);
00370 }
00371
00372 QPainter pt;
00373 pt.begin( &pm );
00374 pt.drawPixmap(x, y, pix);
00375 pt.end();
00376 return pm;
00377 } else {
00378 QPixmap pix = p;
00379
00380 if (pix.width() == 0 || pix.height() == 0)
00381 return pix;
00382
00383 QPalette pal = qApp->palette();
00384 QColor dl = pal.color(QPalette::Disabled, QPalette::Light);
00385 QColor dt = pal.color(QPalette::Disabled, QPalette::Text);
00386
00387 QPixmap pm = pix;
00388 pm = QPixmap(w,h);
00389 pm.fill(dl);
00390
00391 QPainter pt;
00392 pt.begin( &pm );
00393 pt.setPen( dl );
00394 pt.drawPixmap(1, 1, pix);
00395 pt.setPen( dt );
00396 pt.drawPixmap(0, 0, pix);
00397 pt.end();
00398 return pm;
00399 }
00400 }
00401
00402 QPixmap BitmapFactoryInst::fillRect(int x, int y, int w, int h, const QPixmap& p, Qt::BGMode bgmode) const
00403 {
00404 QBitmap b = p.mask();
00405 if (b.isNull())
00406 return p;
00407
00408 QPixmap pix = p;
00409
00410
00411 QPainter pt;
00412 pt.begin(&b);
00413 if (bgmode == Qt::OpaqueMode)
00414 pt.fillRect(x, y, w, h, Qt::color1);
00415 else
00416 pt.fillRect(x, y, w, h, Qt::color0);
00417 pt.end();
00418
00419 pix.setMask(b);
00420
00421 return pix;
00422 }
00423
00424 QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, bool vertical) const
00425 {
00426 int width = 0;
00427 int height = 0;
00428
00429 int x = 0;
00430 int y = 0;
00431
00432
00433 if (vertical) {
00434 y = p1.height();
00435 width = qMax( p1.width(), p2.width() );
00436 height = p1.height() + p2.height();
00437 } else {
00438 x = p1.width();
00439 width = p1.width() + p2.width();
00440 height = qMax( p1.height(), p2.height() );
00441 }
00442
00443 QPixmap res( width, height );
00444 QBitmap mask( width, height );
00445 QBitmap mask1 = p1.mask();
00446 QBitmap mask2 = p2.mask();
00447 mask.fill( Qt::color0 );
00448
00449 QPainter* pt1 = new QPainter(&res);
00450 pt1->drawPixmap(0, 0, p1);
00451 pt1->drawPixmap(x, y, p2);
00452 delete pt1;
00453
00454 QPainter* pt2 = new QPainter(&mask);
00455 pt2->drawPixmap(0, 0, mask1);
00456 pt2->drawPixmap(x, y, mask2);
00457 delete pt2;
00458
00459 res.setMask(mask);
00460 return res;
00461 }
00462
00463 QPixmap BitmapFactoryInst::merge(const QPixmap& p1, const QPixmap& p2, Position pos) const
00464 {
00465
00466 int x = 0, y = 0;
00467
00468 switch (pos)
00469 {
00470 case Qt::TopLeftCorner:
00471 break;
00472 case Qt::TopRightCorner:
00473 x = p1.width () - p2.width ();
00474 break;
00475 case Qt::BottomLeftCorner:
00476 y = p1.height() - p2.height();
00477 break;
00478 case Qt::BottomRightCorner:
00479 x = p1.width () - p2.width ();
00480 y = p1.height() - p2.height();
00481 break;
00482 }
00483
00484 QPixmap p = p1;
00485 p = fillRect(x, y, p2.width(), p2.height(), p, Qt::OpaqueMode);
00486
00487 QPainter pt;
00488 pt.begin( &p );
00489 pt.setPen(Qt::NoPen);
00490 pt.drawRect(x, y, p2.width(), p2.height());
00491 pt.drawPixmap(x, y, p2);
00492 pt.end();
00493
00494 return p;
00495 }
00496
00497 QPixmap BitmapFactoryInst::disabled(const QPixmap& p) const
00498 {
00499 QStyleOption opt;
00500 opt.palette = QApplication::palette();
00501 return QApplication::style()->generatedIconPixmap(QIcon::Disabled, p, &opt);
00502 }
00503
00504 void BitmapFactoryInst::convert(const QImage& p, SoSFImage& img) const
00505 {
00506 SbVec2s size;
00507 size[0] = p.width();
00508 size[1] = p.height();
00509
00510 int buffersize = p.numBytes();
00511 int numcomponents = buffersize / ( size[0] * size[1] );
00512
00513
00514 img.setValue(size, numcomponents, NULL);
00515
00516 unsigned char * bytes = img.startEditing(size, numcomponents);
00517
00518 int width = (int)size[0];
00519 int height = (int)size[1];
00520
00521 for (int y = 0; y < height; y++)
00522 {
00523 unsigned char * line = &bytes[width*numcomponents*(height-(y+1))];
00524 for (int x = 0; x < width; x++)
00525 {
00526 QRgb rgb = p.pixel(x,y);
00527 switch (numcomponents)
00528 {
00529 default:
00530 break;
00531 case 1:
00532 line[0] = qGray( rgb );
00533 break;
00534 case 2:
00535 line[0] = qGray( rgb );
00536 line[1] = qAlpha( rgb );
00537 break;
00538 case 3:
00539 line[0] = qRed( rgb );
00540 line[1] = qGreen( rgb );
00541 line[2] = qBlue( rgb );
00542 break;
00543 case 4:
00544 line[0] = qRed( rgb );
00545 line[1] = qGreen( rgb );
00546 line[2] = qBlue( rgb );
00547 line[3] = qAlpha( rgb );
00548 break;
00549 }
00550
00551 line += numcomponents;
00552 }
00553 }
00554
00555 img.finishEditing();
00556 }
00557
00558 void BitmapFactoryInst::convert(const SoSFImage& p, QImage& img) const
00559 {
00560 SbVec2s size;
00561 int numcomponents;
00562
00563 const unsigned char * bytes = p.getValue(size, numcomponents);
00564
00565 int width = (int)size[0];
00566 int height = (int)size[1];
00567
00568 img = QImage(width, height, QImage::Format_RGB32);
00569 QRgb * bits = (QRgb*) img.bits();
00570
00571 for (int y = 0; y < height; y++)
00572 {
00573 const unsigned char * line = &bytes[width*numcomponents*(height-(y+1))];
00574 for (int x = 0; x < width; x++)
00575 {
00576 switch (numcomponents)
00577 {
00578 default:
00579 case 1:
00580 *bits++ = qRgb(line[0], line[0], line[0]);
00581 break;
00582 case 2:
00583 *bits++ = qRgba(line[0], line[0], line[0], line[1]);
00584 break;
00585 case 3:
00586 *bits++ = qRgb(line[0], line[1], line[2]);
00587 break;
00588 case 4:
00589 *bits++ = qRgba(line[0], line[1], line[2], line[3]);
00590 break;
00591 }
00592
00593 line += numcomponents;
00594 }
00595 }
00596 }
00597