I am using the C++ library PoDoFo (http://podofo.sourceforge.net/) and what I am trying to achieve is embedding a PDF page into a new blank PDF document.
The documentation for the constructor I am using is here: http://podofo.sourceforge.net/doc/html/classPoDoFo_1_1PdfXObject.html#ad60d2bcfa51676961ce09ad274a6a6df
This is what my code currently looks like:
PoDoFo::PdfMemDocument existingDocument(filename);
PoDoFo::PdfStreamedDocument *newDocument = new PoDoFo::PdfStreamedDocument("new_document.pdf");
PoDoFo::PdfPage *newPage = newDocument->CreatePage(PoDoFo::PdfRect(0.0,0.0,300.0,300.0));
PoDoFo::PdfXObject *XObjectFromPage;
XObjectFromPage = new PoDoFo::PdfXObject(existingDocument, 1, newDocument);
PoDoFo::PdfPainter *painter = new PoDoFo::PdfPainter();
painter->SetPage(newPage);
painter->DrawXObject (50, 50, XObjectFromPage,1);
painter->FinishPage();
newDocument->Close();
When constructing the PdfXObject from an existing PDF document PdfError is thrown, perhaps I have made a mistake because I am new to C++ or there is potentially a bug in PoDoFo.
The error that is thrown has the following message:
PoDoFo encounter an error. Error: 48 ePdfError_ChangeOnImmutable
Error Description: Changing values on immutable objects is not allowed.
Callstack:
What is the correct way to construct a PdfXObject from an existing PDF page and embed it into a new PDF document?
To load an existing page into a XObject use something like this (srcDoc and g_outputdoc are PdfMemDocuments):
PdfPage* srcPage(srcDoc->GetPage(pageNumber));
//create XObject owned by outputDoc with size of srcPage
PdfXObject* xobject = new PdfXObject(srcPage->GetCropBox(), g_outputDoc)));
//fill the xObject with the content of the page + all references and ressources used on this page
g_outputDoc->FillXObjectFromDocumentPage(xobject , *srcDoc, pageNumber, false);
Your embedding part is right. Just draw the object using a pdfPainter :-)
The good part about this method is that all the references and ressources are copied too. The bad part about this is that all the references and all the ressources are copied every time ;) even though you embedd the same ressources with other pages...
Related
I'm working on a project in C# that involves parsing .pst files and my group has chosen to use the Redemption library to do so. We have successfully parsed the email files in to RDOMail objects, however now we want to write a subset of those emails to a new .pst file. I have successfully written the subset to .eml files using the email.SaveAs() function, but I'm at a loss to figure out how to save that list as a .pst. I've been sifting through the documentation, however it leaves much to be desired. Can anyone who has used Redemption point me in the right direction or provide an example?? Thanks in advance for your help!
You will need to create/open a PST file using RDOSession.Stores.AddPstStore (returns RDOPSTStore object). Once you have the store, you can open/create folders (starting with the RDOStore.IPMRootFolder), create messages (RDOFolder.Items.Add) and copy old messages into new messages (RDOMail.CopyTo(RDOMail/RDOFolder)).
I have been struggling to do this for the last few hours and would like to save that time to others
You have to install redemption and add it as a reference to your project for it to work
RDOSession session = new RDOSession(); // throws exception 1
session.LogonPstStore(#"c:\temp\output.pst");
RDOFolder folder = session.GetDefaultFolder(rdoDefaultFolders.olFolderInbox);
string[] fileEntries = Directory.GetFiles(#"C:\emlFiles\", "*.eml");
foreach (string filePath in fileEntries)
{
RDOMail mail = folder.Items.Add("IPM.Mail");
mail.Sent = true;
mail.Import(filePath, 1024);
// folder.Items.Add(mail);
mail.Save();
}
session.Logoff();
I also created a small sample windows forms app for it, I know the code is ugly but it does the trick
I'm currently working on a "save" mechanism, which allows a user to save the project his working on on hard disc. The output will be a XML file containing all kinds of data.
Now our project structure is about to change and we need to write a new xml file (create a new save method).
So now here comes the challenge: When saving I want the user to be able to choose which file format he will be creating (version1 (old) or version2 (new)).
Does anyone now how to achieve that? Is there a suitable design pattern around?
Remarks:
- The data we are saving can be seen as unrelated blocks, so it would actually be easy to exchange an old block with a new one.
- The whole goal of the thing is, it should be readable again when loading an old project. (I assume this can be done by tags, and just react on tags when loading?)
This sounds like a good application for the Strategy pattern.
You would create an abstract base class FileFormat (the Strategy interface) with two virtual functions, projectToXml and xmlToProject, which are supposed to turn your internal project representation into XML or vice versa.
Then you create two implementing subclasses FileFormatNew and FileFormatLegacy (these are the concrete strategies).
Your save functions would then additionally require an instance of FileFormat, and call the corresponding method of that object to do the data conversion. Your load function could choose the strategy to use by examining the XML tree for something which tells it which version it is.
And when you ever need to support another file format, you just have to create a new class which is a subclass of FileFormat.
Addendum after the exchange in the comments
When you are going to have a lot of versions with very small differences and you still want to use the Strategy pattern, you could make the FileFormat a composite of multiple strategies: A CircleStragegy, a RectangleStrategy, a LineStrategy etc.. In that case I wouldn't use different classes for different versions of the FileFormat. I would create a static factory function for each version which returns a FileFormat with the Strategy objects used in that version.
FileFormat FileFormat::createVersion1_0() {
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_1() {
// the 1.1 version introduced the new way to save lines
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyOld(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_2() {
// 1.2 uses the new format to save circles
return new FileFormat(
new LineStrategyNew(),
new CircleStrategyNew(),
new RectangleStragegyOld()
);
}
FileFormat FileFormat::createVersion1_3() {
// 1.3 uses a new format to save rectangles, but we realized that
// the new way to save lines wasn't that good after all, so we
// returned to the old way.
return new FileFormat(
new LineStrategyOld(),
new CircleStrategyNew(),
new RectangleStragegyNew()
);
}
Note: In real code you would of course use more descriptive suffixes than "Old" and "New" for your strategy class names.
What I'm trying to do is to fill ListView in Windows 8 Metro application dynamically with pre-loaded images.
for each item (URI) I'm doing it plain simple with the code like this (C++):
Windows::UI::Xaml::Media::Imaging::BitmapImage^ bitmapSrc =
ref new Windows::UI::Xaml::Media::Imaging::BitmapImage();
bitmapSrc->CreateOptions = Windows::UI::Xaml::Media::Imaging::BitmapCreateOptions::IgnoreImageCache;
bitmapSrc->UriSource = uri;
img->Source = bitmapSrc;
LoadListView->Items->Append(img);
but when I delete (in the app) source image described by URI and I create new file with the same name and try to reload it into the list then I fail and image shown is the old one (deleted). I presume some cache works here. I tried to avoid caching by IgnoreImageCache value in CreateOptions but it didn't work.
Any clues how to disable caching of BitmapSource (Image) potentially bound to ListView in Windows 8 app?
I tried several directions inspired by Silverlight and WPF, none worked unfortunately.
Encouraged by comments, I put answer I've found myself.
Broader context (and also C# perspective) is explained here:
http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/171dfe66-78b5-4340-bd78-244337f31287/
Shortly I believe it's a problem with reference counting here.
WinRT keeps the image loaded (cached) in BitmapImage^ as long as Uri is valid and asigned to the object instance, that in my example is added to the list.
Cleaning Uri from BitmapImage^ prior to releasing it from the list solved problem in my case.
According to example in question, below code solves the problem (included in the part where the list removal is performed):
auto item = (Image^)LoadListView->Items->GetAt(selected);
auto src = (Windows::UI::Xaml::Media::Imaging::BitmapImage^)item->Source;
src->UriSource = nullptr; //this line is critical
LoadListView->Items->RemoveAt(selected);
I am trying Share an Image in Windows 8 Metro C++ Application using Share Charm. To do so, I need to load image to StorageFile^ first. I assume it should looks like:
create_task(imageFile->GetFileFromPathAsync("Textures/title.png")).then([this](StorageFile^ storageFile)
{
imageFile = storageFile;
});
where imageFile is defined in header file
Windows::Storage::StorageFile^ imageFile;
This actual code would throw this exeption
An invalid parameter was passed to a function that considers invalid parameters fatal.
This seems to be very trivial, but there is a very little documentation about Sharing in Metro, and the only Microsoft example shows how to do sharing using FilePicker.
Would be very grateful if someone knows how to do it properly.
If "Textures" is coming from your application package, you should use StorageFile::GetFileFromApplicationUriAsync instead:
Uri^ uri = ref new Uri("ms-appx:///Assets/Logo.png");
create_task(StorageFile::GetFileFromApplicationUriAsync(uri)).then([](task<StorageFile^> t)
{
auto storageFile = t.get();
auto f = storageFile->FileType;
});
You can also use a task-based continuation (as I show above) in order to inspect the exception information more closely. In your case, the inner exception is: The specified path (Assets/Logo.png) contains one or more invalid characters.
This is due to the forward-slash, if you change it to a backslash you'll see: The specified path (Assets\Logo.png) is not an absolute path, and relative paths are not permitted.
If you want to use GetFileFromPathAsync I would recommend using
Windows::ApplicationModel::Package::Current->InstalledLocation
To figure out where your application is installed and building up your path from there.
I'm trying to set the text of a textfield using the Carbon API like this:
ControlID editId = {'EDIT', 3};
ControlRef ctrl;
GetControlByID(GetWindowRef(), &editId, &ctrl);
CFStringRef title = CFSTR("Test");
OSErr er = SetControlData(ctrl, kControlEntireControl, kControlEditTextTextTag, CFStringGetLength(title), title);
CFRelease(title);
I'm using the C++ code template of XCode, so GetWindowRef() is a call to the predefined TWindow class. The OSErr return value gives me noErr, but my textfield only contains garbage.
It doesn't matter if I set the attribute of my textfield to Unicode or not.
Any ideas what is wrong here?
What does the GetControlID(...) return? Is it noErr?
As a ControlRef is also a HIViewRef, you can also use the function:
HIViewSetText to set the text. This is documented to work with functions that accept kControlEditTextCFStringTag.
By the way, the line you wrote:
CFRelease(title);
Will cause problems. One should only release objects that have been made using functions that have Create or Copy in the API name. You'll want to read: "Introduction to Memory Management Programming Guide for Core Foundation" -- search in the Xcode documentation.
Finally this did the trick:
SetControlData(ctrl, kControlEditTextPart, kControlStaticTextCFStringTag, sizeof(title), &title);
Since this seems to be very old API, a better way seems to be:
HIViewSetText(ctrl, title);
Thx to Lyndsey for the hints.