Can someone provide an example of how to load a .svg file and display it using C/C++ and any library? I'm wondering if you will use SDL, cairo, or what.
Helltone,
check out http://cairographics.org/cairomm/
Might make things a little easier.
As Pavel put it, QtSvg is the way to go i believe. It is easier to use but in our team we have faced performance issues with QtSvg especially on Linux. So we decided to directly parse the SVG file XML by hand and render it using Qt itself. This turned out to be much faster.
pseudocode:-
// Read the SVG file using XML parser (SAX)
void SvgReader::readFile()
{
QFile file(<some svg filename>);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
qWarning("Cannot open file");
return;
}
QString localName;
QXmlStreamAttributes attributes;
pXml = new QXmlStreamReader(&file);
pXml->setNamespaceProcessing(false);
while (!pXml->atEnd()) {
switch (pXml->readNext()) {
case QXmlStreamReader::StartElement:
localName = pXml->name().toString();
if (localName.compare(<some element path>) == 0) {
attributes = pXml->attributes();
QStringRef data = attributes.value(<some attribute name>);
// parse/use your data;
}
// similarly other case statements
}
}
}
QtSvg module might be helpful.
you may try boost.svg_plot
You can try lunasvg.
#include <lunasvg/document.h>
int main()
{
auto document = Document::loadFromFile("example.svg");
auto bitmap = document->renderToBitmap();
// do something useful with bitmap here.
}
Related
I'm having problem with parsing yaml files using yaml-cpp, I'm making a application using wxWidgets and I'm trying to read the frame size from a yaml file which looks like,
---
This is the configuration file for the Sample Browser,
feel free to edit this file as needed
...
Window:
SizeW: 1280
SizeH: 720
Media:
Autoplay: false
And this the code that should handle the parsing,
int sizeH, sizeW;
try
{
YAML::Node config = YAML::LoadFile("/home/apoorv/repos/cpp-projects/wxWidgets/SampleBrowser/build/config.yaml");
if (!config["Window"])
{
wxLogDebug("Error! Cannot fetch values.");
}
sizeH = config["SizeH"].as<int>();
sizeW = config["SizeW"].as<int>();
}
catch(const YAML::ParserException& ex)
{
std::cout << ex.what() << std::endl;
}
this->SetSize(sizeW, sizeH);
But when I try to parse this file and set the frame size this->SetSize() it errors out saying *** Caught unhandled unknown exception; terminating.
Since SizeH and SizeW are children of Window, your two lines should look like
sizeH = config["Window"]["SizeH"].as<int>();
sizeW = config["Window"]["SizeW"].as<int>();
or, merged with the previous check,
if (auto window = config["Window"]) {
sizeH = window["SizeH"].as<int>();
sizeW = window["SizeW"].as<int>();
} else {
wxLogDebug("Error! Cannot fetch values.");
}
Generally, the error handling is bad. In your code, if an error is encountered, sizeH and sizeW are not set but are still given to SetSize. This is undefined behavior. You should initialize them with some default values, e.g.
int sizeH = 480, sizeW = 640;
Also, since you keep us in the dark about what this is, there may be other errors.
It's fine to try to do this for learning yaml-cpp, but if you really want to save/restore your frame geometry, you should use wxPersistentTLW instead. To use it, just call wxPersistentRegisterAndRestore(frame, "NameToIdentifyYourFrame") after creating your frame, see the manual for more details.
In the cross-platform environment it is better to save the client size of the window, as for GTK what's important is the client size. There might be other OSes/toolkits where this is the case.
I am attempting to load a wxIcon in Windows by loading from a system DLL (as the mime system told me that the icon for such a file type was in the DLL), eg.
wxIcon icon;
icon.LoadFile("C:\\WINDOWS\\system32\\zipfldr.dll", wxICON_DEFAULT_TYPE);
This fails but I was wondering if there was any way in the codebase of loading this, other than resorting to native Win32 functions.
Also, if there are native Win32 functions, does anyone know what they are?
EDIT: I have tried the following with no success:
::wxInitAllImageHandlers();
wxMimeTypesManager manager;
wxFileType* type = manager.GetFileTypeFromExtension("sys");
wxIconLocation location;
if (type->GetIcon(&location))
{
// location is something like C:\WINDOWS\system32\imageres.dll
wxIcon icon;
if (!icon.LoadFile(location.GetFileName(), wxBITMAP_TYPE_ICON /*I have tried wxICON_DEFAULT_TYPE too*/))
{
// Failed!
}
}
EDIT 2: In response to VZ, I have tried the following with no success sadly:
::wxInitAllImageHandlers();
wxMimeTypesManager manager;
wxFileType* type = manager.GetFileTypeFromExtension("sys");
wxIconLocation location;
if (type->GetIcon(&location))
{
// location is something like C:\WINDOWS\system32\imageres.dll,
//with an appropriate index as retrieved by location.GetIndex(), which is -67.
wxIcon icon(location);
if (!icon.IsOk())
{
BREAK;
// Failed!
}
}
EDIT 3:
Thanks for everyone's help - works fine if I use wxBITMAP_TYPE_ICO instead of wxBITMAP_TYPE_ICON (notice the N), and also I was putting my test code in my app's constructor instead of in ::OnInit. It worked in OnInit but not in the constructor so that's a lesson learned!
Thanks everyone for the help and speedy responses, much appreciated as always.
It should work if you specify type wxBITMAP_TYPE_ICO.
The first argument to LoadFile() must specify the icon resource ID when using wxBITMAP_TYPE_ICO (which is indeed what you need to use when loading icons from files, and not resources of the current module), i.e. you're also missing the ;N part at the end, where N is the value returned by wxFileTypeInfo::GetIconIndex().
But to avoid dealing with this explicitly, you should just use wxFileType::GetIcon() and construct wxIcon from the wxIconLocation filled in by it.
For example, this:
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index 0d91f7fc75..3623aacc56 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
## -123,6 +123,12 ## bool MyApp::OnInit()
if ( !wxApp::OnInit() )
return false;
+ wxIcon icon(wxIconLocation(R"(c:\Windows\system32\imageres.dll)", -67));
+ if ( icon.IsOk() )
+ {
+ wxLogMessage("Loaded icon of size %d*%d", icon.GetWidth(), icon.GetHeight());
+ }
+
// create the main application window
MyFrame *frame = new MyFrame("Minimal wxWidgets App");
shows the expected message about loading the icon of size 32 by 32.
I need to get current page in my document, with set range. I found that it is possible to do by:
Range.Information(wdActiveEndPageNumber) //example in C#
but i have problem with that. In documentation, information is visible as property. So when i use
QString number = myRange->property("Information(wdActiveEndPageNumber)").toString()
i'm getting nothing. I also tried dynamicCall, but either doesn't work. Simple properties as Text or Start works perfectly fine, but i have no idea what to do with these enumerations.
Whole code:
QAxObject *word, *doc;
word = new QAxObject("Word.Application", this);
word->setProperty("DisplayAlerts", false);
word->setProperty("Visible", true);
doc = word->querySubObject("Documents");
doc->dynamicCall("Open(const QString&)", "path to file");
QAxObject *act = word->querySubObject("ActiveDocument");
QAxObject *next = act->querySubObject("Content");
next->dynamicCall("Select()");
next->dynamicCall("Copy()");
QClipboard *clip = QApplication::clipboard();
myTextEdit->setText(clip->text());
QString number = next->property("Information(3)").toString();
QMessageBox::information(this, tr("cos"), tr("%1").arg(number)); //here i need to know how many pages i've got
Okay, after much research, I found that there is no possibility yet to take value from Information enum. Maybe in future version of Qt, but nowadays I had to create library in Visual Basic and invoke functions from C++ code.
Just found a really cool answer to this question here:
http://www.qtforum.org/article/31970/how-do-i-get-use-the-ienumerable-interface-in-qt.html
Here the answer again.
With returnList containing your enum..
QAxObject *enum1 = returnList->querySubObject("_NewEnum");
IEnumVARIANT* enumInterface; //to get this, include <windows.h>
enum1->queryInterface(IID_IEnumVARIANT, (void**)&enumInterface);
enumInterface->Reset(); //start at the beginning of the list.
for (int i=0;i<returnList->dynamicCall("Count").toInt();i++)
{
VARIANT *theItem;
enumInterface->Next(1,theItem,NULL);
QAxObject *item = new QAxObject((IUnknown *)theItem->punkVal);
qDebug() << item->dynamicCall("Caption");
}
I have used QT Phonon to play audio file.
The problem is that i need the ability to change the play rate, while keeping the ability to seek the file.
It seems from test that once you add the Phonon speed Effect, mediaObject.isSeekable becomes false.
Does anybody know how to use Phonon, while keeping seekable ability with the speed effect?
Here is some sample code to add a speed effect:
QList<Phonon::EffectDescription> effectDescriptions =
Phonon::BackendCapabilities::availableAudioEffects();
foreach(Phonon::EffectDescription effectDesc, effectDescriptions)
{
if(effectDesc.name() == "speed")
{
speedEffect = new Phonon::Effect(effectDesc);
path.insertEffect(speedEffect);
QList<Phonon::EffectParameter> parameters = speedEffect->parameters();
foreach(Phonon::EffectParameter param, parameters)
{
if(param.name() == "speed")
{
speedParameter = param;
}
}
break;
}
}
I have a small but itching problem. How do I get the correct case for a Windows path in Qt?
Let's say i have a path c:\documents and settings\wolfgang\documents stored in a QString str and i want to know the correct case, here C:\Document and Settings\Wolfgang\Documents. QDir(str).absolutePath() doesn't get me the path with correct case.
Any suggestions, since I have no clue what else i could try?
Thank you for your time!
There isn't a simple way to do this, but you can try doing a QDir.entryList, and then do a case insensitive search on the results. This will provide you with the correct filename. You'll then need to get the absolutePath for that result.
This should give you the preserved-case for the path/filename.
I think the solution currently accepted by the OP, with listing all children items on each directory level of the path, is really inefficient, quick and dirty. There must be a better way. Because this problem with case-correct path relates only to Windows (other platforms are case-sensitive, AFAIK), I think it is perfectly correct to use #ifdef and call to Windows API and write something like this:
#if defined(Q_OS_WIN32)
#include <Windows.h>
// Returns case-correct absolute path. The path must exist.
// If it does not exist, returns empty string.
QString getCaseCorrectPath(QString path)
{
if (path.isEmpty())
return QString();
// clean-up the path
path = QFileInfo(path).canonicalFilePath();
// get individual parts of the path
QStringList parts = path.split('/');
if (parts.isEmpty())
return QString();
// we start with the drive path
QString correctPath = parts.takeFirst().toUpper() + '\\';
// now we incrementally add parts one by one
for (const QString &part : qAsConst(parts))
{
QString tempPath = correctPath + '\\' + part;
WIN32_FIND_DATA data = {};
HANDLE sh = FindFirstFile(LPCWSTR(tempPath.utf16()), &data);
if (sh == INVALID_HANDLE_VALUE)
return QString();
FindClose(sh);
// add the correct name
correctPath += QString::fromWCharArray(data.cFileName);
}
return correctPath;
}
#endif
I have not tested it, there might be some minor issues. Please let me know if it does not work.
You can use QFileInfo for that and the function
QString QFileInfo::absoluteFilePath () const will return the absolute file path.
E.g:
QFileInfo yourFileInfo(yourPath);
QString correctedCasePath = yourFileInfo.absoluteFilePath ();
Another advantage is that, yourPath can be a QFile or QString so that you can use it directly with the handle currently you are having. Besides these, there are other operations are also available through QFileInfo that can obtain useful information about the file being referred to..
Hope it helps..