.NET library for typesetting documents (PDF or similar)?
Asked Answered
C

7

7

EDIT: Better explanation: Before setting a bounty for this question I want to state clearer what I need:

I need .NET library for generating printable documents. Users should be able to print exactly the same document that they see either using my application or using external tool (like Adobe Acrobat reader). It does not have to be library for generating PDF documents, any document format that satisfies above condition will do.

I need the library to support following scenarios:

Scenario 1:

  1. I create text in some font and color.
  2. I ask the library for the width if this text if printed.
  3. I compute position([X,Y] coordinates on page) of this text based on information from 2. and have the library to print in at this position on a page.

Scenario 2:

  1. I create a text with some parts of it in superscript. All parts of text (normal and superscript) are in same (but variable) font.
  2. I ask the library what is the width if this text when printed. I get correct answer that also takes kerning between normal text and superscript into account.
  3. I compute position([X,Y] coordinates) on a page where this text should be printed (using its width from step 2.). I let the library to print it at this position. Printed on the page it has exactly the width that was returned by library in previous step.

Note for second scenario: I have text with some parts in superscript - example AAA{v-superscript text}BBB (where text in {} braces is superscript). The library needs to be able to print this text using correct kerning. Without right kerning there will be the same gap between last A and first superscript v as between last superscript t and first B. For the user it will look like there is a space between A and superscript v but no space after the last superscript letter. So the text will look ugly. If the library is to handle this correctly it would have method to print the whole text AAA{v-superscript text}BBB at once with specification that a part of it is in superscript. Then it would use correct kerning between normal text and superscript.

Scenario 3:

  1. I want to print picture that consists of lines, circles, filled circles, letters and bezier curves on exact point in a page. I need to specify width of lines and circles. All shapes needs to be printed in pixel precision.

The library should be free of charge and not GPL (LGPL is ok). Is there something that allows me to do what I need ? Can it be done with iTextSharp (version 4.1.6 that is LGPL not AGPL)? Or perhaps with Fixed document ? Thank you for any suggestions.


Original question:

I need to typeset complex documents in .NET (C#) application for the user. Primary use of those documents will be for printing.

Documents will contain text and simple generated graphics. Layout of text and graphic will be complex and needs to be computed (in another words text position in document needs to be controlled by my code, it will not be done automatically by chosen library).

Here are my API requirements:

  1. function that returns exact width for given string and given font in which text should appear
  2. ability to position text to exact position on the page
  3. have text with some part of it in super script
  4. function to get exact width of some text that has some part of it in superscript
  5. ability to add pictures or even better option to draw simple graphics (line of given thickness, filled circle of given radius/diameter)

It does not have to be library for creating PDF documents - any other "what you see is what will be printed" document format will also do. If there is WPF component that can displays such documents it is an advantage. I know there is iTextSharp but is not easy to achieve 4. requirement with iTextSharp. Of course some PDF generation library that satisfies requirements above will be great solution too.

Thank you for ANY suggestions, I'm also happy to provide details or clearer explanation.

Caveman answered 12/4, 2011 at 0:15 Comment(7)
Have you looked at XPS/XpsDocumentWriter/etc. yet?Gripsack
@Logan Capaldo: That name sounds familiar to me... If it is that format that has native WPF control to display it than I have had look on it some time ago. But I did not figure out if there is simple way to generate such documents in WPF. I have question with no answers about it here: stackoverflow.com/questions/4634445/how-to-work-with-fixedpage .Caveman
@Logan Capaldo: But XPS document is not fixed right ? So it does not display exactly the same layout as will be printed ?Caveman
@drasto: Wikipedia says "Like Adobe Systems's PDF format, XPS is a fixed-layout document format designed to preserve document fidelity, providing device-independent document appearance." Seems like what you asked for.Unabridged
@Martinho Fernandes : yes look like that. Just don't know if it also offers API for creating documents that allows me to do all the thinks described in my question...Caveman
I did some goggling and it seems that there is no tutorial or any resource on how to generate documents. There are some answers on SO that shows how to create documents XPS from some FixedPages but I still don't know how to create FixedPage with some content in .NET. My question stackoverflow.com/questions/4634445/how-to-work-with-fixedpage is still unanswered.Caveman
Editing my answer again.Urbannal
S
3

You can look to Docotic.Pdf Library (disclaimer: I work for Bit Miracle). It has user-friendly API and good set of samples that you can view online or run in sample viewer application.

Also it satisfies your requirements:

  • function that returns exact width for given string and given font in which text should appear

You can use the PdfCanvas.MeasureText() method for this.

  • ability to position text to exact position on the page

There are many overloads that allows to show text in arbitrary position or area.
https://bitmiracle.com/pdf-library/api/pdfcanvas-drawstring
https://bitmiracle.com/pdf-library/api/pdfcanvas-drawtext

  • have text with some part of it in super script

The PdfCanvas.TextRise property allows to show superscript text. You can use it in combination with PdfCanvas.FontSize property for control a size of superscript text. The code sample: https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Text/TextRise

  • function to get exact width of some text that has some part of it in superscript

If you will use different font or font size for superscript text the direct call of PdfCanvas.MeasureText() method will produce incorrect results.

There are workarounds:

-measure each part of string drawn with different fonts separately and then sum all widths.

-if you want to get width of drawn text you can simply subtract initial text position from the final text position after drawing.

  • ability to add pictures or even better option to draw simple graphics (line of given thickness, filled circle of given radius/diameter)

Supported. Look at these samples:
https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Graphics
https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Images


PDF viewer component is in our plans, but currently Docotic.Pdf doesn't offer such functionality.

Update: You can now rasterize, render, or print PDF documents using Docotic.Pdf. Look at the following articles:
https://bitmiracle.com/pdf-library/pdf-image/convert
https://bitmiracle.com/pdf-library/draw-print-pdf

Stab answered 12/4, 2011 at 17:42 Comment(3)
Is there some place where I can see output of this example for superscript that you provided: bitmiracle.com/pdf-library/help/text-rise.aspx ? Do you have free trial/demo/GPL version or something that I can try before paying ?Caveman
Of course. You can download and evaluate Docotic. It comes with sample viewer and set of samples for Visual Studio 2005-2010. Evaluation version has some limitations, you can read details hereStab
Some links in the comments above are no longer work. Here are the correct ones: for bitmiracle.com/pdf-library/help/text-rise.aspx and for download and evaluate.Stab
U
2

Rather than looking for other libraries, how about looking for a better way to compute the width of mixed-size/style text?

float width = ColumText.getWidth(phrase);

Phrase extends ArrayList with various text layout functions and attributes. Paragraph extends Phrase. Each chunk has a specific Font with its own color, size, and underlying PDF font. Each chunk has its own "text rise" to adjust its baseline.

What version of iText are you using? ColumnText has been around for Quite Some Time.


So you want kerning between normal & superscript letters? That doesn't sound like a very good idea to me. Kerning is an adjustment so 'T' can overhang "j" for example. Kerning values assume a shared baseline and font size. You'll never share a baseline, and almost certainly have different font sizes when dealing with superscript text. And even if you decide it's a good idea to use those values (and I'd disagree), do you kern in the base text's point size, or the superscript's font size?

My point is that I think your goal here (kerned superscript/subscript text boundaries with normal text) is going to result in worse layout, not better.

Or am I misunderstanding you? Let me re-read your comment:

But when you also want to position it this text that includes superscript on the page you need to use PdfContentByte.

Not entirely sure what you mean there. If you want to place text in an arbitrary location on the page, yes, you're pretty much required to use PdfContentByte.

When using it I did not find the way to print complex text that includes superscript at once.

All the text in a given "show text" command must share the same font/size/color/etc. That's the way PDF works, its not some limitation of iText.

I think it only allows to print one text chunk in the time.

Correct.

So I cannot measure text with superscript taking kerning into account and then put it on the some position on the page

You need to add all the widths of the different chunks together. I can't believe kerning between normal and superscript text is a good idea, but a PDF sample showing the problem could persuade me otherwise.

It seems to me you need to use BaseFont.getWidthPointKerned(String text, float fontSize). Superscript, subscript, or normal, it's all about the point size and font. And if you Absolutely Insist, you can use BaseFont.getKerning(int c1, int c2) to get the kerning value between any two letters within the same font, and use that to determine inter-chunk kerning.


Another way to draw text with iText & PdfContentByte is with ColumnText. I believe iText uses ColumnText when laying out paragraphs, but I'd have to go look at the code to be sure.

At any rate, your code might look something like this:

ColumnText colTx = new ColumnText(contByte);
// paragraphs are phrases.
colTx.addText(phraseWithSuperAndSubScriptStuff);
colTx.setSimpleColumn(llx, lly, urx, ury);
colTx.go();
Urbannal answered 12/4, 2011 at 23:19 Comment(6)
@Mark Storer: My problem with iTextSharp is that when you want to have text in superscript that follows after text that is not in superscript. iTextSharp does right kerning when you use it in standard way. But when you also want to position it this text that includes superscript on the page you need to use PdfContentByte. When using it I did not find the way to print complex text that includes superscript at once. I think it only allows to print one text chunk in the time.So I cannot measure text with superscript taking kerning into account and then put it on the some position on the page...Caveman
...without splitting it into chunks and printing separate chunks on the page. But this way I loose kerning between those chunks (at the border between superscript and not-superscript text). And so the result is the the text either looks bad (without kerning before superscript) but I can measure it and print on specified position - or it looks good and I can measure it but it I cannot print it on custom position on the page (I cannot use ColumText with PdfContentByte). I can download latest version of iTextSharp that is not a problem. Now I'm using version that is like 1 year old.Caveman
@Mark Storer it is only now that I mentioned that you edited your answer. You understood my comments correctly. There was a typo but you got it right. About kerning between normal and superscript text:Last time when I was testing how to print text that contains normal and superscript parts with PdfContentByte (so that I can print it in an arbitrary location) I did following: printed normal text Normal text at [30, 30]. Measured Normal text using BaseFont.getWidthPointKerned. Lets say returned value was 101. So I printed superscript part superscript text at [131, 30] using same...Caveman
...font family but smaller size with some text rise set. But the result did not look good. In particular it was not the same as the result produced when I did not use PdfContentByte but Paragraph that consisted of 2 chunks (Normal text and superscript text where second chunk was set to be superscript - there is a way to do it but I don't remember methods names...). The result produced when using Paragraph instead of PdfContentByte looked good and it was actually the think I wanted. There was smaller gap between Normal text and superscript text. I thought that was because...Caveman
...Paragraph used kerning to compute distance between those chunks (Normal text and superscript text). But Paragraph cannot be used with PdfContentByte at least I did not find a way to do that. So I cannot print Paragraph in an arbitrary position. This is why I wanted kerning between normal text and superscript. If the ugly text was there from other reason I just want to get same results (as with Paragraph) on arbitrary location.Caveman
@Mark Storer: Well I want to avard the bounty and your last edit might very well be the solution I'm looking for. I have no time to test if it really does what I want - bounty is over in 8 minutes. I'll test your suggestion and suggestions of others later and possibly accept some answer or set new bounty if the problem is not solved. Thank you and also thanks to all others who posted answers.Caveman
S
1

Here is an article on constructing FixedDocument objects on MSDN.

If you are using WPF, and you want to create Print Quality documents, the FixedDocument and XPS technologies built in are probably what you should be learning. And since you can eventually access the entire FixedDocument in the object model, it may tell you your width numbers as well. I haven't experimented with that yet.

Sickroom answered 12/4, 2011 at 2:20 Comment(1)
Well before I decide to use it I need to know that it is possible to do what I need to do with it. So I need to know how to get text width information and how is it possible to typeset super script. And how is it possible to measure super script text.Caveman
S
1

Our product, PDFOne .NET may suit your requirements. It comes with royalty-free commercial license.

  1. function that returns exact width for given string and given font in which text should appear
    You can use the PDFFont.GetTextWidth() method for this.
  2. ability to position text to exact position on the page
    You could use one of the many PDFDocument.WriteText() overloads for this
  3. have text with some part of it in super script
    PDF does not have any this concept in its textouts. What appears to us as a superstring is just another string with a different font size and position. You just need to call another textout for this.
  4. function to get exact width of some text that has some part of it in superscript
    Refer previous response.
  5. ability to add pictures or even better option to draw simple graphics (line of given thickness, filled circle of given radius/diameter) - PDFOne .NET has render images, squares, rectangles, arcs, Bezeir curves, ellipses, circles, rectangles, polylines, polygons, rectangles, watermarks, stamps, several types of annotations,...

PDFOne .NET also comes with a PDF printer component and PDF viewer component.

DISCLAIMER: I work for Gnostice.

Sproul answered 12/4, 2011 at 5:10 Comment(2)
+1 good answer. However when you write in 3. that what appears as superscript is just another text in another position I think it is not what I desire. If I only add smaller text shifted little up as superscript it will look ugly because there will be no kerning between normal text and superscript. Considering example A^v there will be a lot of space between A and superscript v. In another case E^b there will be much less space then in previous case. So I need cannot position superscript correctly without kerning information. And then I also need that information to measure it.Caveman
I must correct myself regarding superscript and subscript textouts. I referred this question to our developers (post-answer) and they say that PDF does not require separate textouts, i.e., it can achieved with a single textout. We will be adding support for such strings in upcoming versions. Currently, our products would require separate textouts.Sproul
D
1

I think you might be overthinking your problem, while WPF has great printing abilities. You can print any visual (visuals are almost all WPF classes) exactly as you see them on the screen in a really easy way. There is a good tutorial here: http://www.switchonthecode.com/tutorials/printing-in-wpf

Dozy answered 21/4, 2011 at 1:43 Comment(7)
Looks good but how can I have some text with superscript in WPF ? I don't think it is possible to have a Label that has some parts of text in superscript (and kerned). And how would I measure text then ? just by getting value of AcctualWidth of the Label?Caveman
Hi, I didn't try it myself, but I think that here is a solution to superscript mixed with normal text: #2096083. And for the width, yes, it's more or less that easy. WPF can measure the width of any visual and you get it from it's properties. I coded something similar but I don't have it here. I'll check it later at home. good luck!Enrobe
@tinchou: Good link! Again I like this more and more... I was nearly decided to use iTextSharp and try to get Mark Storer's suggestions work but now I'm reconsidering it. Any code that you could provide would be extremely helpful. Visuals can be converted to FixedDocument as well is that right ?Caveman
hi again, drasto. I think you should try this, it won't take long to see how easy it is. although, there are some limitations with typo variants: first, you need opentype fonts (like palatino). you can read the description here: msdn.microsoft.com/en-us/library/… and unfortunately, there's a terrible bug: connect.microsoft.com/VisualStudio/feedback/details/545057/… I also checked my code and I just used a FormattedText's width propertyEnrobe
and at last, as you will be using the common windows printing window, you will have the choice to "print" to an XPS document. (I had some margin issues with printing to xps, but I never solved them because my app was for real printing, and it went well). (sorry, i'm realizing that I am writing terribly bad and short!)Enrobe
@tinchou +1 If I had this your comment yesterday it would save me 3 hours of experimenting, goggling etc. :( However I managed to get 'superscript' effect by having Span inside TextBlock cotaining all my text. I simply set BaselineAlignment="Top" on that Span and I setting its FontSize to be less then surrounding text. It works for all fonts and even for single numbers but it does not look exactly as I want it to. I'll ask separate question about this later (if you would like to answer just check my profile from time to time and filter questions by tag superscript).Caveman
@tinchou Also I don't understand what is FormattedText for and I don't know how to use it. I have seen some examples that looked really difficult. I did not get it. Looks like it is very low API that I'm generally tying to avoid.Caveman
T
1

Sounds like you need to get some experience in GDI+.

I worked for a mortgage company and they are very particular on how they want their reports laid out. Down to pixel precision. Unfortunately GDI+ does not measure Text very well. Therefore your better alternative would be to use windows API

[DllImport("gdi32.dll")]
static extern bool GetTextExtentPoint(IntPtr hdc, string lpString, 
                                      int cbString, ref Size lpSize);

you pass the handle of the Bitmap you are drawing on. Much more accurate.

alternatively you may look into using TextRenderer

http://msdn.microsoft.com/en-us/library/system.windows.forms.textrenderer(v=VS.80).aspx

I cant make any claims as to how accurate it is.

Tilburg answered 22/4, 2011 at 5:57 Comment(2)
+1 Thank you it looks nice but as in the case of other answers I don't see how to do scenario 2 from my answer with GDI+. You provided answer on how to measure and print normal text, how to measure and print superscript text but no way to measure and print them together and kerned together (see note to scenario 2). If there is a way that I don't see please provide simple code example/method link/description how to do it.Caveman
I guess the difference in text is that the (super/sub)script text has a different size then the normal text. GDI+ Gives you the tools to do the painting. You shall have to do the parsing of the requests and measure what your strings are, then you can draw them where you want. My recommendation is, Draw the first set of normal text, then the super or subscript text, And finally the next set of normal text. It is my opinion that this is what any other application will do. But this will give you the most control over your product.Tilburg
S
0
  1. LaTeX: LaTeX for PDF generation in production
  2. For Pay libraries like Aspose: http://www.aspose.com/categories/.net-components/aspose.pdf-for-.net/default.aspx
  3. plain HTML with good CSS can work pretty well too.
  4. Microsoft Open XML: http://msdn.microsoft.com/en-us/library/bb448854.aspx

For what it's worth, I think iTextSharp is the easiest one of the bunch. You can do what you want in all of them, but they each have pros and cons.

Sexagesima answered 12/4, 2011 at 2:2 Comment(5)
Latex: I need programmatic access to width of strings that will be in my document to compute layout. That cannot be done with latex. Html: where do I get width of strings ? Open XML - see previous comments to original question.Caveman
I'm far from an expert in LaTeX, but I'm pretty sure you can do anything you want. You can specify the width of a node as is discussed here: tex.stackexchange.com/questions/7660/… Html: control fonts with css and calculate width of strings based on length and font information. Open XML: the SDK I linked is very rich, I'm sure you can do what you need. Like I said, you can do what you need with all the libraries, it may require some creativity and hard work. I don't think there's an easy way out here.Sexagesima
I know very well what can be done in LaTeX and also what cannot be done. You can use information width of some string within LaTeX itself but you cannot access it externally from .NET code. I cannot let LaTeX to do layout alone without .NET because my layout is too complex for LaTeX - I need full featured programing language to compute it. And NO you CANNOT do anything you want in LaTeX. This is what you cannot do: #2600144 . And that is the reason why I cannot use it.Caveman
I still don't understand how to get width of strings in Html... Based on which font information ? If I use information from .NET font the width will never be the same as the one showed in html. I'm not 100% sure but I'd bet there is different kerning at least... And Html is not good solution for programmatic generated documents and for printing anyway.Caveman
As in, you could measure how wide a font-size: 12px courier new "hello world" string is and then base your calculations on that. Regardless, I gave several other options. Hope they helped.Sexagesima

© 2022 - 2024 — McMap. All rights reserved.