<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-807055817343774432</atom:id><lastBuildDate>Sat, 18 May 2013 12:13:53 +0000</lastBuildDate><category>html css2 css3 pdf</category><category>cryptography</category><category>pdf</category><title>The PDF</title><description>This is where .NET and PDF come together. We develop a handful of .NET components that create, manipulate and render PDF documents. This blog is used to post insights about the PDF format and how to use our software.</description><link>http://blog.tallcomponents.com/</link><managingEditor>noreply@blogger.com (Frank Rem)</managingEditor><generator>Blogger</generator><openSearch:totalResults>33</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/thepdf" /><feedburner:info uri="thepdf" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-4738607286295874716</guid><pubDate>Mon, 28 Jan 2013 14:21:00 +0000</pubDate><atom:updated>2013-02-06T08:55:29.951+01:00</atom:updated><title>Cross-platform limitations of Mono.</title><description>&lt;p&gt;Some customers indicated that they were having issues running PDFRasterizer.Net on Mono. And although we do not officially support mono, we decided to do some experiments with it nonetheless. &lt;/p&gt; &lt;h2&gt;Running a sample in MonoDevelop on Windows&lt;/h2&gt; &lt;p&gt;So, we installed MonoDevelop, and we tried to run some of the PDFRasterizer.NET samples. This immediately led to the following error:&lt;/p&gt; &lt;p&gt;Error CS1566: Error reading resource file '…\TallComponents.PDF.Rasterizer_3.0.84.2\Code Samples\CS\ViewPDF\MainForm.resources' -- 'The system cannot find the file specified. ' (CS1566) (ViewPDF_vs2010)&lt;/p&gt; &lt;p&gt;In order to solve this issue we had to manually call resgen on all the .resx files. This allowed us to build the project, but when trying to debug it, we got the following:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-KkBRtvyCUi4/UQaJQd6pA7I/AAAAAAAAAd8/5geS5uV9iX8/s1600-h/image%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-v40kAcaIRLY/UQaJRcdY4dI/AAAAAAAAAeE/DrtLbD8Vn_U/image_thumb%25255B3%25255D.png?imgmax=800" width="581" height="240"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Luckily, this appeared to be rather an issue with running the MonoDevelop debugger than anything else. Without debugging, things appeared to be fine, so we did not pursue debugging in Windows any further.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-ww9SxIwuyAk/UQaJSixkyVI/AAAAAAAAAeM/RVTTVzvxVBQ/s1600-h/image%25255B11%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-0GWVBNroh9A/UQaJTnViWmI/AAAAAAAAAeU/QrO5A0odAV4/image_thumb%25255B5%25255D.png?imgmax=800" width="352" height="418"&gt;&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;Running a sample in MonoDevelop on OSX&lt;/h2&gt; &lt;p&gt;Then, we figured that we should also try things on Mac OSX. At first this gave some weird compile errors, like:&lt;/p&gt; &lt;p&gt;…/TallComponents.PDF.Rasterizer_3.0.84.2/Code Samples/CS/ViewPDF/MainForm.cs(35,35): Error CS0584: Internal compiler error: Method not found: 'TallComponents.PDF.Rasterizer.Document.ConvertToWpf'. (CS0584) (ViewPDF_vs2010)&lt;/p&gt; &lt;p&gt;This was strange because we used a sample that made no reference to any WPF functionality at all. It occurred to us however that this sample referenced a .Net 4.0 assembly, and we remembered some old blogs talking about MonoDevelop having issues with that. So we removed the .Net 4.0 PDFRasterizer.NET assembly and added the .Net 2.0 one instead. This looked quite hopeful at first, and interestingly we had no trouble running the debugger here:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-3v8zpoZ2TkQ/UQaJUxfJoFI/AAAAAAAAAec/YQirG_ZxSWQ/s1600-h/image%25255B34%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-stlmyTh6ITI/UQaJVmAKtMI/AAAAAAAAAek/NMumwSn1VPA/image_thumb%25255B18%25255D.png?imgmax=800" width="378" height="381"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;But then we noticed that the evaluation banner was missing. The banner should have been there because we were running in evaluation mode. We started looking further. On OSX, PDFRasterizer.NET turned out to be plagued by basically 2 problems:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Some pages would render completely blank, or only partially.  &lt;li&gt;Mono would just quit on some pages, leaving no further option to debug:&lt;a href="http://lh3.ggpht.com/-49Mg6Ob7w1c/UQaJWjkiVRI/AAAAAAAAAes/s3yOItnd36g/s1600-h/image%25255B52%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-F6D7JJbqh6c/UQaJXuGkQkI/AAAAAAAAAew/Pn-dFzPmhQM/image_thumb%25255B28%25255D.png?imgmax=800" width="559" height="288"&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h2&gt;&lt;/h2&gt; &lt;h2&gt;Compiling in MonoDevelop&lt;/h2&gt; &lt;p&gt;In order to track this down, we decided to try and get our PDFRasterizer.NET sources compiled under MonoDevelop. We started doing so on Windows, soon to discover that the MonoDevelop compiler&amp;nbsp; (3.0.5) has some limitations compared to standard Microsoft .Net. Amongst others:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;it gives errors on vars.  &lt;li&gt;it gives errors on extension methods  &lt;li&gt;one needs to specify brackets for some #if evaluations&lt;!--EndFragment--&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;After “fixing” these, we went on to OSX with our sources. Here we discovered that some further issues were flagged. These were relatively minor, but it was certainly a surprise to find out that these differences exist between the PC and the Mac version of MonoDevelop. More so, because we also discovered that the Windows issues mentioned above were &lt;em&gt;not&lt;/em&gt; flagged by the compiler on OSX at all. Both versions are the latest stable versions for both platforms, which at this point means 3.0.5 for windows and 3.1.1 for OSX.&lt;/p&gt; &lt;h2&gt;Debugging&lt;/h2&gt; &lt;p&gt;In any case, after having fixed these compilation issues, it became more or less possible to debug PDFRasterizer.Net on OSX. Apart from the occasional crash, we were able to identify the following 2 runtime issues:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;there were runtime differences in casts from (negative) doubles to uints. Once we were aware of this, this was easy to fix.  &lt;li&gt;The System.Drawing implementation on OSX turned out to behave differently with respect to clipping. In OSX the clipping area becomes empty at unpredictable times, leading to loss of graphics. If we turned off clipping altogether, we were able render additional graphics on some problematic pages , but part of the page would still be rendered incorrectly due to improper clipping handling.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The following pictures illustrate the latter. With clipping enabled, we would get the following on OSX:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-hoI_y5U-I3w/UQaJYsT2M8I/AAAAAAAAAe8/n6qkEFMMBIc/s1600-h/image%25255B46%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-9iseq5O468A/UQaJZmJTMMI/AAAAAAAAAfE/iInh6De8ouc/image_thumb%25255B24%25255D.png?imgmax=800" width="364" height="414"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Whereas with clipping entirely disabled, we would get:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-vhkrpjZM-KU/UQaJa7ucPpI/AAAAAAAAAfM/DFfNOODyX2M/s1600-h/image%25255B47%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-65chQiQ7zF8/UQaJb7yPTSI/AAAAAAAAAfU/ooCi0rCWLgE/image_thumb%25255B25%25255D.png?imgmax=800" width="384" height="374"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Notice that the last result does show additional images (as it should), but also that the colors that are projected in the topmost images are wrong in both cases. This happens because clipping is used to draw the “intersections” of various colors. Clearly this goes wrong no matter whether clipping is turned on or not. For comparison, the &lt;em&gt;same&lt;/em&gt; code – with clipping enabled - renders the following on MonoDevelop on Windows:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/--u1B6honoaE/UQaJdEviF8I/AAAAAAAAAfc/_gayXLBlvZ4/s1600-h/image%25255B51%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-UO51c2FafSk/UQaJeQ1d-VI/AAAAAAAAAfk/OZfbxjB7ZI0/image_thumb%25255B27%25255D.png?imgmax=800" width="369" height="355"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In itself this issue was already a showstopper for us. Unfortunately, having compiled the system on MonoDevelop itself also did not preclude the crashes that we encountered earlier. There were still PDF files that we were unable to debug at all, because Mono just quits on them.&lt;/p&gt; &lt;h2&gt;Conclusion&lt;/h2&gt; &lt;p&gt;All in all, it was very disappointing to discover that Mono is not as platform-independent as it claims to be, while also being very unstable on OSX. This means that it is currently impossible for us to have a workable solution for Mono on various platforms.&lt;/p&gt; &lt;p&gt;Apart for improvements in Mono itself, our hopes are now mainly on our own “TallBitmap” renderer, which will allow us to render PDF pages without relying on System.Drawing, and thus without depending on Mono’s implementation of this functionality on various platforms.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/pQktWqI8OFw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/pQktWqI8OFw/cross-platform-limitations-of-mono.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-v40kAcaIRLY/UQaJRcdY4dI/AAAAAAAAAeE/DrtLbD8Vn_U/s72-c/image_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2013/01/cross-platform-limitations-of-mono.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-399130012294526515</guid><pubDate>Tue, 11 Dec 2012 13:32:00 +0000</pubDate><atom:updated>2012-12-11T14:59:12.347+01:00</atom:updated><title>Making PDF rasterizer extensible - First design meeting</title><description>Starting with version 4.0 of PDFRasterizer.NET, we will make our PDF render engine extensible in the sense that you can plug-in your own output device. This should enable developers to render (or convert) PDF to e.g. SVG, HTML5 or something else. This also serves an internal purpose; conversions that we already offer (e.g. render PDF to a GDI bitmap or XPS) will be implemented using this same plug-in API.&lt;br /&gt;
&lt;br /&gt;
This article reports about our first design meeting. Much of what is included here will evolve over time. We will make small iterations and implement mutliple output devices to continuously validate the plug-in API. We will try to release these iterations as often as possible. To join the beta program, send a request to &lt;a href="mailto:sales@tallcomponents.com"&gt;sales@tallcomponents.com&lt;/a&gt;.&amp;nbsp;We welcome any feedback obviously.&lt;br /&gt;
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uN1nhLSjizA/UMclpW5O3PI/AAAAAAAAAbs/ZYNktnQu9rQ/s1600/whiteboard-11-12-2012.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="201" src="http://4.bp.blogspot.com/-uN1nhLSjizA/UMclpW5O3PI/AAAAAAAAAbs/ZYNktnQu9rQ/s400/whiteboard-11-12-2012.JPG" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Whiteboard notes&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;h2&gt;
OutputDevice&lt;/h2&gt;
&lt;div&gt;
The starting point of the plug-in API will be the OutputDevice class that must be specialized (inherited). It represents the device/format to which you want to render. By overriding a set of methods you implement your own output device (class MyOutputDevice). These methods will likely fall into one of two categories: 1. resource factories and 2. drawing methods. We will make the model such that you may choose to not implement everything and rely on the base class to simplify things if desired. A typical example is to not draw glyphs but rely on the base class to convert them to paths and render those instead. Another example is to support RGB only and have the base class do the color conversions for you.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h2&gt;
Resources&lt;/h2&gt;
&lt;div&gt;
The PDF imaging model includes the following&lt;i&gt; resource types&lt;/i&gt;:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Paths&lt;/li&gt;
&lt;li&gt;Fonts&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Color spaces&lt;/li&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Patterns&lt;/li&gt;
&lt;li&gt;Shadings&lt;/li&gt;
&lt;li&gt;Groups&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
The OutputDevice class has virtual methods that return instances of these resources. These &lt;i&gt;resource factory methods&lt;/i&gt; will be called when the given resource is required during rendering. The API model includes a base class for each resource type. The implentation of the override returns a specialization of the resource (e.g. SvgFont). If the resource is not supported, the virtual is not overridden.&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
Drawing&lt;/h2&gt;
&lt;div&gt;
The second category of methods are the&lt;i&gt; drawing methods&lt;/i&gt;. These are virtual methods of OutputDevice and can be overridden in MyOutputDevice. The drawing methods include at least:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;DrawText&lt;/li&gt;
&lt;li&gt;DrawPath (stroke and fill)&lt;/li&gt;
&lt;li&gt;DrawImage&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
When these methods are called, the corresponding resources (e.g. Path when DrawPath is called and Font when DrawText is called) will either be passed with the method, or it will be accessible through the graphics state. This is yet to be decided.&lt;/div&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
Graphics State&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
Like many other imaging models, PDF has the notion of a &lt;i&gt;graphics state&lt;/i&gt;. Here is part of what is included in the graphics state:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;current transformation matrix (CTM)&lt;/li&gt;
&lt;li&gt;current path&lt;/li&gt;
&lt;li&gt;current font and font size&lt;/li&gt;
&lt;li&gt;current color space and color (both for stroking and filling)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
Operations inside a PDF document modify the graphics state in order to achieve the desired result when a drawing operation is performed.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
How the graphics state will be part of the plug-in API is not sure yet. There several options:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;We offer it as a base property of OutputDevice.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;We offer overridables that will be called when the graphics state is modified. These methods can either be members of OutputDevice or of a class called GraphicsState that can be specialized.&lt;/li&gt;
&lt;li&gt;We pass the relevant information to the drawing methods.&lt;/li&gt;
&lt;li&gt;A combination of the three above.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
Finally, there are operations that explicity save and restore the graphics state and there are operations that do this implicitly. This results in a stack of graphics states. Consequently, there may also be a property that reflects this stack while the current state is simply the top element of this stack.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Final words&lt;/h2&gt;
As said, we will release iterations of the plug-in API in the coming weeks and months.&amp;nbsp;To join the beta program, send a request to&amp;nbsp;&lt;a href="mailto:sales@tallcomponents.com"&gt;sales@tallcomponents.com&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Looking forward to your feedback!&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
Author: Frank Rem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/uAiRJAiImbQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/uAiRJAiImbQ/making-pdf-rasterizer-extensible-first.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-uN1nhLSjizA/UMclpW5O3PI/AAAAAAAAAbs/ZYNktnQu9rQ/s72-c/whiteboard-11-12-2012.JPG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/12/making-pdf-rasterizer-extensible-first.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-8006490728664321907</guid><pubDate>Tue, 04 Dec 2012 12:54:00 +0000</pubDate><atom:updated>2012-12-04T13:54:09.321+01:00</atom:updated><title>TeamCity Security</title><description>We were busy setting up a TeamCity server and an agent in order to get some continuous integration going. The setup we wanted was:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;Have the TeamCity server setup in the cloud. We are not all working in the same office, so we need to have general access to it.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Run the agents locally in one or more of our offices. Fast hardware is not that expensive, and machines in the cloud cost money too. And after setting up these local machines, there is basically no need to attend them further.&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
A colleague had already set up TeamCity on our server, and I was going to set up the first agent locally. I thought that it was going to be simple to do this securely, but unfortunately I hit a few bumps.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;br /&gt;Service Account&lt;/h2&gt;
&lt;br /&gt;
The first bump was a minor one. During the installation, I was asked which account the agent was going to run in. I could either specify “system account” (the default), or some specific account. I did not want to use system account, because that would give the agent administrative rights. Specifying another account however, gave an authorization error.&lt;br /&gt;
&lt;br /&gt;
The way to solve this in Windows is rather simple, but you have to know how to do it. Instead of specifying a specific account, you will have to tell the installer to use the system account and let it proceed. Then, after it is finished, you can go to the services control panel and change the logon account for the TeamCity Build Agent service. If you pass the right credentials, you will see a popup that mentions that the account has been given the right to run as a service.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;br /&gt;Agent Connection&lt;/h2&gt;
&lt;br /&gt;
When I fired up the new agent, it did not get a connection to the server. I looked in the logs. It said that the connection was lost. I remembered that the installer asked for an agent port. I looked up the documentation:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://confluence.jetbrains.net/display/TCD7/Setting+up+and+Running+Additional+Build+Agents" title="http://confluence.jetbrains.net/display/TCD7/Setting+up+and+Running+Additional+Build+Agents"&gt;http://confluence.jetbrains.net/display/TCD7/Setting+up+and+Running+Additional+Build+Agents&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
It says: “&lt;em&gt;Server should be able to open HTTP connections to the agent&lt;/em&gt;”.&lt;br /&gt;
&lt;br /&gt;
I could not find an option to turn this off. I can understand that it is sometimes useful to give the server a direct link to the agent. But in this case, I would have to open up a port in our office to a machine in our own local network. I expected that this was just an option, and that I could turn the connection to the agent off. After all, other web based app’s can also do their thing without opening connections to their clients. The agent would just have to poll for work. But alas, no option.&lt;br /&gt;
&lt;br /&gt;
And then I read:&amp;nbsp; "&lt;em&gt;Please note that by default, these connections are not secured and thus are exposing possibly sensitive data to any third party that can listen to the traffic between the server and the agents. Moreover, since the agent and server can send "commands" to each other an attacker that can send HTTP requests and capture responses can in theory trick agent into executing arbitrary command and perform other actions with a security impact.&lt;/em&gt;"&lt;br /&gt;
&lt;br /&gt;
The connection to the server can be configured to use https, but for the connection to the agent this option &lt;em&gt;does not exist&lt;/em&gt;. All the settings that are configured in the TeamCity web GUI are passed over this link. This includes configured authentication information for the version control system.&lt;br /&gt;
&lt;br /&gt;
In short: in order to do this securely, I would have to set up a VPN between the server and the agent.&lt;br /&gt;
&lt;br /&gt;
This however would require changes at our remote server, and if not done properly it might disrupt it. And possibly I might have to configure our local router too, which could cause trouble on our local network. That was a bit too much for an initial setup.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;br /&gt;Firewall&lt;/h2&gt;
&lt;br /&gt;
To be able to deal with this, I set up the agent firewall so that it only accepts connections for a single port from our TeamCity server. I also limited outgoing connections to one or two ports on our server. Our internal network is now invisible to the agent machine, and if it gets compromised, there is nowhere to go (assuming an attacker cannot intercept responses to our server).&lt;br /&gt;
&lt;br /&gt;
Also, we avoided the standard TeamCity mechanism for checking out sources. Its server-side checkout might send sources to the agent out in the open, while for its agent-side checkout it might tell the world about some credentials used for our version control system.&lt;br /&gt;
&lt;br /&gt;
Instead, we let the agent check out the sources over https via TortoiseSVN, using locally stored credentials. Sure, if the machine gets compromised over the agent link it may be possible to find them, but given the firewall rules it will be hard to get them out.&lt;br /&gt;
&lt;br /&gt;
And finally, we made sure that the team city agent does not have write access to our version control system. A matter of damage control.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;br /&gt;COMPROMISE&lt;/h2&gt;
&lt;br /&gt;
I know that this setup is not ideal, and it may well be that we go for a VPN solution after all. But a VPN raises questions too. Our TeamCity server is basically a “public” machine. If it gets compromised we will not be happy, but it will just be the server. If it were part of a VPN on the other hand, the situation might be worse: via the compromised server it may be possible to easily reach other machines within the VPN and compromise these too.&lt;br /&gt;
&lt;br /&gt;
In any case, what amazes me the most is that a well-known system like TeamCity requires a connection to the agent. Without it, we could just have used https to the server and be done with it. No VPN setup, no special router configuration, no firewall restrictions (or at least less severe ones), and no restrictions on using TeamCity’s check-out mechanism.&lt;br /&gt;
&lt;br /&gt;
It surely would have made things a lot simpler.&lt;br /&gt;
&lt;br /&gt;
Author: Marco Kesseler&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/2o6M8t6zBks" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/2o6M8t6zBks/teamcity-security.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/12/teamcity-security.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-8782380235431810377</guid><pubDate>Thu, 15 Nov 2012 13:51:00 +0000</pubDate><atom:updated>2012-11-15T14:51:35.058+01:00</atom:updated><title>WinRT edition of PDFRasterizer now 3-4 times faster</title><description>&lt;br /&gt;
&lt;div class="MsoPlainText"&gt;
We have just released maintenance update 4.0.0.4 of PDFRasterizer.NET. The
most significant changes are:&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class="MsoPlainText"&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;There is now an unsafe variant of the WinRT edition to
speed things up. We measured 3-4 times faster rendering! We are still
investigating implications for the Windows 8 App Store Certification process.
Any feedback is welcome!&lt;/li&gt;
&lt;li&gt;When drawing using the WinRT edition, you can now
cancel draw jobs in progress. You typically do this when flipping away from a
page before it has finished.&lt;/li&gt;
&lt;/ul&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;br /&gt;


&lt;div class="MsoPlainText"&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class="MsoPlainText"&gt;
To join the beta program, just &lt;a href="mailto:sales@tallcomponents.com?subject=I%20want%20to%20join%20the%20PDFRasterizer.NET%204.0%20beta%20program"&gt;send a request&lt;/a&gt;!&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/do9CoiYD6iA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/do9CoiYD6iA/winrt-edition-of-pdfrasterizer-now-3-4.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/11/winrt-edition-of-pdfrasterizer-now-3-4.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-1014169183154771368</guid><pubDate>Thu, 18 Oct 2012 07:29:00 +0000</pubDate><atom:updated>2012-10-18T09:29:59.287+02:00</atom:updated><title>Rasterizing PDF on WinRT </title><description>Today we released a beta version of PDFRasterizer.NET 4.0 (4.0.0.3) that includes a WinRT edition.&amp;nbsp;It took us a little bit longer than we hoped for. I want to explain why. In addition it also includes a Silverlight 4 edition. If you are interested, send a request to &lt;a href="mailto:sales@tallcomponents.com"&gt;sales@tallcomponents.com&lt;/a&gt; and we will provide download instructions.&lt;br /&gt;
&lt;h4&gt;
&lt;/h4&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
Known restriction of current beta (4.0.0.3)&lt;/h2&gt;
&lt;span style="font-weight: normal;"&gt;This version does not support:&lt;/span&gt;&lt;br /&gt;
&lt;div style="font-weight: normal;"&gt;
&lt;ul&gt;
&lt;li&gt;Soft masks.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Non-embedded fonts. This is related to not having access to system fonts from WinRT.&lt;/li&gt;
&lt;li&gt;Shadings other than gradient, radial, function based (shadings are slow)&lt;/li&gt;
&lt;li&gt;IccProfiles. We revert to the alternate colorspace.&lt;/li&gt;
&lt;li&gt;Special colors (such as CMYK) are not entirely correct. E.g. too bright or too pale.&lt;/li&gt;
&lt;li&gt;Blendings&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2&gt;
&lt;/h2&gt;
&lt;h2&gt;
So why did it take us so long?&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
The main problem with rasterizing PDF documents are the restrictions of the graphics API of WinRT itself. Amongst others, it only supports rectangular clipping paths. This alone is a showstopper.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We struggled with similar problems when using GDI+ or WPF as the graphics API. But their shortcomings always came down to not being able to render edge cases (exotic shadings and blend modes). But even then we could revert to a bitmap-based workaround.&amp;nbsp;If a graphics API is able to render to bitmaps, one can implement extensions in terms of operations on these bitmaps. This is not an ideal solution (espcially w.r.t. printing), but it often works well for on-screen solutions.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
This bitmap-based solution is unavailable when developing for WinRT. There is no equivalent for GDI+ code like this:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: csharp;"&gt;// Create bitmap
Bitmap bitmap = new Bitmap(500, 500, PixelFormat.Format32bppRgb);

// Create graphics object from bitmap
Graphics graphics = Graphics.FromImage(bitmap);

// Create pen
Pen blackPen = new Pen(Color.Black, 3);

// Create points that define line
Point point1 = new Point(100, 100);
Point point2 = new Point(500, 100);

// Draw line to bitmap
graphics.DrawLine(blackPen, point1, point2);&lt;/pre&gt;
&lt;br /&gt;
When developing for WinRT, you can create a WriteableBitmap which can only be manipulated by setting pixel values. There is no way to e.g. stroke or fill a path.&lt;br /&gt;
&lt;br /&gt;
Because of the shortcomings of GDI+ and WPF, we had considered developing our own graphics engine before. WinRT gave us that last push.&lt;br /&gt;
&lt;br /&gt;
On May 15, I sent off an internal e-mail to the development team announcing a new internal project. Here is the first part of this e-mail:&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;Until now we relied heavily on the graphics API as provided by Microsoft such as GDI+ and WPF for rendering PDF documents. Because of this we were not able to render all PDF features such as complex shadings and complex blend modes. With the introduction of new platforms such as WinRT and Silverlight, even less exotic graphical features have become unavailable. Because of this we have decided to develop an internal module (100% managed code) that frees us from the graphical capabilities that Microsoft decides to offer. Let's call this module TallBitmap.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;span style="font-family: Courier New, Courier, monospace;"&gt;The graphical feature set of TallBitmap should cover all graphical features of PDF such as:&lt;br /&gt;
- path construction and painting (PDF spec 4.4)&lt;br /&gt;
- fill rules (non-zero winding number, even-odd)&lt;br /&gt;
- clipping&lt;br /&gt;
- patterns (PDF spec 4.6). Including shading patterns.&lt;br /&gt;
- transpareny and blend modes (PDF spec Chapter 7)&lt;br /&gt;
- clipping&lt;br /&gt;
- dash patterns&lt;br /&gt;
- join style / cap style&lt;br /&gt;
- images (PDF spec 4.8). Note that the library does not have to include decoding. The library assumes that the images have been decoded.&lt;br /&gt;
&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;
For five months, two of our engineers spent 50% of their time implementing TallBitmap. They worked in sprints of five days and alternated this with support.&lt;br /&gt;
&lt;br /&gt;
Today, this work paid off when we released a WinRT edition of our PDF render engine that is based on our internal module TallBitmap.&lt;br /&gt;
&lt;br /&gt;
Frank Rem, CEO&lt;/div&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/R0UKqdq85t4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/R0UKqdq85t4/rasterizing-pdf-on-winrt.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>4</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/10/rasterizing-pdf-on-winrt.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-3380748800885089042</guid><pubDate>Wed, 17 Oct 2012 14:08:00 +0000</pubDate><atom:updated>2012-10-17T16:08:05.211+02:00</atom:updated><title>WinRT edition of PDFRasterizer.NET available</title><description>We have just released a PDFRasterizer.NET 4.0 Beta that includes a WinRT edition. To join the beta group, send a request to &lt;a href="mailto:sales@tallcomponents.com"&gt;sales@tallcomponents.com&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/6pC2XAOs4zQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/6pC2XAOs4zQ/winrt-edition-of-pdfrasterizernet.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/10/winrt-edition-of-pdfrasterizernet.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-159110003505079058</guid><pubDate>Mon, 01 Oct 2012 12:09:00 +0000</pubDate><atom:updated>2012-10-01T14:09:45.796+02:00</atom:updated><title>PDFWebViewer.NET Discontinued</title><description>As of today, we have discontinued PDFWebViewer.NET 1.0. We will not release version 2.0.&lt;br /&gt;
&lt;br /&gt;
Here is why:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;PDFWebViewer.NET's sales was neglectable compared to flagship products such us PDFKit.NET and PDFRasterizer.NET while the support and maintenance effort was unproportionally high.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;We strongly believe in separation of concerns when it comes to designing software components. PDFWebViewer.NET does not meet this design criterium.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
The first reason is obvious. Let's elaborate on the second one.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
PDFWebViewer.NET is an ASP.NET control that provides a browser-side view on a server side PDF document. It implements features such as zooming, panning, interactive links, etc.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
On the browser side, we need to support different types of browsers and different versions of individual browsers. Nowadays this includes browsers on mobile devices in addition to browsers on desktops. But also, server-side we need to support different types of web application frameworks such as plain vanilla ASP.NET, MVC and what will be released next. &amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In contrast to this dependency on browser flavors and web application frameworks, components such as &lt;a href="http://www.tallcomponents.com/pdfkit4.aspx"&gt;PDFKit.NET&lt;/a&gt; and &lt;a href="http://www.tallcomponents.com/pdfrasterizer3.aspx"&gt;PDFRasterizer.NET&lt;/a&gt; have a fully UI-less API and thus are much less coupled to technologies that come and go.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In order to not spread ourselves too thin, we need to focus on core functionality. That is why we decided to discontinue PDFWebViewer.NET 1.0 and not release its successor 2.0.&lt;/div&gt;
&lt;h3&gt;
&lt;br /&gt;&lt;/h3&gt;
&lt;h3&gt;
Existing Customers&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;
Internally, PDFWebViewer.NET 1.0 and WebViewer.NET 2.0 are build on top of &lt;a href="http://www.tallcomponents.com/pdfkit4.aspx"&gt;PDFKit.NET 4.0&lt;/a&gt; and &lt;a href="http://www.tallcomponents.com/pdfrasterizer3.aspx"&gt;PDFRasterizer.NET 3.0&lt;/a&gt;. We have released the source code of both major versions on CodePlex under the &lt;a href="http://opensource.org/licenses/ms-pl"&gt;Microsoft Public License&lt;/a&gt;. You will see that the downloads include the &lt;a href="http://www.tallcomponents.com/pdfkit4.aspx"&gt;PDFKit.NET 4.0&lt;/a&gt; and &lt;a href="http://www.tallcomponents.com/pdfrasterizer3.aspx"&gt;PDFRasterizer.NET 3.0&lt;/a&gt; assemblies.&amp;nbsp;&lt;a href="mailto:support@tallcomponents.com"&gt;Contact support&lt;/a&gt; to convert your PDFWebViewer.NET licenses to PDFKit.NET 4.0 and PDFRasterizer.NET 3.0 licenses at no cost.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Download source code:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pdfwebviewer1.codeplex.com/"&gt;PDFWebViewer.NET 1.0 CodePlex project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://webviewer2.codeplex.com/"&gt;WebViewer.NET 2.0 CodePlex project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/KxSEGCHeNwY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/KxSEGCHeNwY/pdfwebviewernet-discontinued.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/10/pdfwebviewernet-discontinued.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-2617090056216492065</guid><pubDate>Thu, 28 Jun 2012 15:19:00 +0000</pubDate><atom:updated>2012-06-28T17:19:18.820+02:00</atom:updated><title>Windows 8 Release Preview – back to earth</title><description>&lt;p&gt;Hurray, we got a workaround for the problem of the previous blog. This works:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;for (ulong i = 0; i &amp;lt; stream.Size; i++)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.Seek(i);&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; byte[] data = new byte[1];&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; await stream.ReadAsync(data.AsBuffer(), 1, InputStreamOptions.None);&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (stream.Position &amp;gt; stream.Size)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Never happens, which is as expected.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&lt;font face="Arial"&gt;The credits for finding this go to Gionata from paperlit.com. Thanks!&lt;/font&gt;&lt;/p&gt;&lt;/font&gt; &lt;p&gt;Note that the main difference appears to be:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read);&lt;/font&gt;&lt;/p&gt; &lt;p&gt;As opposed to:&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;Stream stream = await file.OpenStreamForReadAsync();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Weird, eh? One would say that both expressions are basically synonymous.&lt;/p&gt; &lt;p&gt;Well, this means back to work, were it not for the summer holidays…&lt;/p&gt; &lt;p&gt;Author: Marco Kesseler&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/yzpN0RlXfBY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/yzpN0RlXfBY/windows-8-release-preview-back-to-earth.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/06/windows-8-release-preview-back-to-earth.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-5778633895705175565</guid><pubDate>Tue, 12 Jun 2012 12:37:00 +0000</pubDate><atom:updated>2012-06-12T14:38:04.048+02:00</atom:updated><title>Windows 8 Release Preview – to boldly go where…</title><description>&lt;p&gt;Windows 8 continues to amaze me. I recently upgraded to the Windows 8 Release Preview and tried to run one of our projects. After dealing with some of the changes, it returned an error that I could not quite place.&lt;/p&gt; &lt;p&gt;Debugging revealed that stream.ReadByte() would sometimes leave the stream position far beyond the end of the stream. This only happened in combination with a call to stream.Seek().&lt;/p&gt; &lt;p&gt;So, I wrote the following test. It opens a file, and then tries to seek increasingly further in it – but not beyond the end - and at all these positions it reads a single byte. As soon as this leads to a position beyond the end of the stream, it prints how far from the end of the stream we were actually trying to read.&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;var file = await fileOpenPicker.PickSingleFileAsync();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;if (file != null)&lt;br&gt;{&lt;br&gt;&amp;nbsp;&amp;nbsp; Stream stream = await file.OpenStreamForReadAsync();&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; for (long i = 0; i &amp;lt; stream.Length; i++)&lt;br&gt;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; stream.Seek(i, SeekOrigin.Begin);&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (stream.ReadByte() &amp;gt;= 0)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (stream.Position &amp;gt;= stream.Length)&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Diagnostics.Debug.WriteLine(stream.Length - i);&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp; }&lt;br&gt;}&lt;/font&gt;&lt;/p&gt; &lt;p&gt;And the result is: things start to go wrong at 8192 bytes before the end of the stream. For every file I tested. Always.&lt;/p&gt; &lt;p&gt;Now I am starting to become a bit paranoid. Is it just me? Am I doing something wrong? Is my metro system hosed? I have Googled for this issue, but found nothing. Am I the only one trying to do these things on Windows 8? I cannot believe it.&lt;/p&gt; &lt;p&gt;Author: Marco Kesseler&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/azVJuEsXwv8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/azVJuEsXwv8/windows-8-release-preview-to-boldly-go.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/06/windows-8-release-preview-to-boldly-go.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-3252353580317240464</guid><pubDate>Tue, 01 May 2012 09:10:00 +0000</pubDate><atom:updated>2012-05-01T11:12:00.108+02:00</atom:updated><title>Searching Text and Recognizing Columns</title><description>In order to find text, it is important to scan content in the correct order. For example, take a look at the following piece of text:&lt;br /&gt;
&lt;a href="http://lh4.ggpht.com/-E77uPzEvbOs/T5k0VAlaHLI/AAAAAAAAAYA/1htDp5Sqc2s/s1600-h/2%252520columns%25255B5%25255D.png"&gt;&lt;img alt="2 columns" border="0" src="http://lh3.ggpht.com/-Ciq_AwD4-U0/T5k0V0T-v5I/AAAAAAAAAYI/J2qnhMl0mCM/2%252520columns_thumb%25255B3%25255D.png?imgmax=800" style="background-image: none; border-bottom-color: initial; border-bottom-style: initial; border-bottom-width: 0px; border-left-color: initial; border-left-style: initial; border-left-width: 0px; border-right-color: initial; border-right-style: initial; border-right-width: 0px; border-top-color: initial; border-top-style: initial; border-top-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="2 columns" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
We will read it as follows:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;em&gt;The National Transportation Safety Board said a 12-member team&lt;/em&gt;....&lt;/blockquote&gt;
We definitely do not read it like this:&lt;br /&gt;
&lt;blockquote class="tr_bq"&gt;
&lt;em&gt;The National Transpor- House Speaker John tation Safety Board said a Boehner said ...&lt;/em&gt;&lt;/blockquote&gt;
From this it is clear that text in its nature is a sequential stream of information. In order to get a correct search result, we should preserve this sequence.&lt;br /&gt;
Ok, it is quite easy for me as a human being to recognize the columns in the text. My recognition system has been practiced in doing that for a long time (still need to practice to apply different image filters directly in my brain). But what about machines? How does software recognize layout structure of a text within a PDF file?&lt;br /&gt;
Most PDF documents do not store this layout information. If you look inside the document you can barely distinguish columns, paragraphs, sentences or even words. You can however extract runs of characters and their coordinates within a page.&lt;br /&gt;
So how to obtain the information about the text strcture? In this article we are going to build word position histograms in order to recognize columns.&lt;br /&gt;
&lt;h2&gt;
&lt;br /&gt;&lt;/h2&gt;
&lt;h2&gt;

Using histograms as a first guess to finding columns&lt;/h2&gt;
How we can make the initial guess? Let’s take a look where the words begin. All the words on the left side of the column have the same X coordinate. Therefor it should be interesting to build a histogram that shows the frequence of a word start along the horizontal axis.&lt;br /&gt;
In order to build the histogram I use &lt;a href="http://www.tallcomponents.com/pdfkit4.aspx"&gt;PDFKit.NET&lt;/a&gt; as it allows to extract all glyphs on the page. The glyphs are used to get the position of each word and based on that data I can construct the histograms.&amp;nbsp; From the picture below you can see how the histogram corresponds to the page. The histogram clearly shows two peaks. These peaks are probably the left edges of the columns.&lt;br /&gt;
&lt;a href="http://lh6.ggpht.com/--W4Sy_lFEJE/T5k0W80l3PI/AAAAAAAAAYQ/Y7jZJIZzA7g/s1600-h/001%25255B4%25255D.png"&gt;&lt;img alt="001" border="0" height="399" src="http://lh4.ggpht.com/-JHC9aIBTeTI/T5k0XyhjU4I/AAAAAAAAAYY/l_svNl6n6kY/001_thumb%25255B2%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="001" width="290" /&gt;&lt;/a&gt;&lt;br /&gt;
The histogram of the following page has six big peaks and we conclude that the page has six columns.&lt;br /&gt;
&lt;div align="center"&gt;
&lt;a href="http://lh3.ggpht.com/-INcwh82a0ds/T5k0ZCOxYyI/AAAAAAAAAYg/zFIIxFijNfA/s1600-h/002%25255B4%25255D.png"&gt;&lt;img alt="002" border="0" height="402" src="http://lh3.ggpht.com/-16pV91nLeLE/T5k0aOoVhoI/AAAAAAAAAYo/Iwf6Pbyx9I8/002_thumb%25255B2%25255D.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="002" width="307" /&gt;&lt;/a&gt;&lt;/div&gt;
In fact we can see not only the amount of the columns but some more additional information. Notice that there is almost no noise between the first peak and the second one.&lt;br /&gt;
&lt;div align="center"&gt;
&lt;a href="http://lh6.ggpht.com/-Pp9zQ7n7DF8/T5k0bFLgk7I/AAAAAAAAAYw/vGOFEGCbvrs/s1600-h/003%25255B2%25255D.png"&gt;&lt;img alt="003" border="0" height="124" src="http://lh4.ggpht.com/-XIHgTgS1x8E/T5k0cKg-OiI/AAAAAAAAAY4/lVbhNK-tkc8/003_thumb.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="003" width="244" /&gt;&lt;/a&gt;&lt;/div&gt;
That happens because the first column doesn’t intersect with the second one.&lt;br /&gt;
&lt;div align="center"&gt;
&lt;a href="http://lh5.ggpht.com/-Kwei5Y8JKS0/T5k0dekewfI/AAAAAAAAAZA/6mwKntwcq3k/s1600-h/0031%25255B2%25255D.png"&gt;&lt;img alt="0031" border="0" height="232" src="http://lh5.ggpht.com/-f_t5hwA2VZQ/T5k0fjDBlfI/AAAAAAAAAZI/PfbSEIXphxA/0031_thumb.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="0031" width="244" /&gt;&lt;/a&gt;&lt;/div&gt;
However there is some noise distributed over the rest five columns. Moreover the noise between the second and the fifth column has almost the same level.&lt;br /&gt;
&lt;div align="center"&gt;
&amp;nbsp;&lt;a href="http://lh3.ggpht.com/-UzHVyF8zyyo/T5k0gUAAaXI/AAAAAAAAAZQ/nbxloexwGsU/s1600-h/004%25255B2%25255D.png"&gt;&lt;img alt="004" border="0" height="124" src="http://lh4.ggpht.com/-rBRAh8o-Tqs/T5k0hLWeu9I/AAAAAAAAAZY/W-0uAYkFUOM/004_thumb.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="004" width="244" /&gt;&lt;/a&gt;&lt;/div&gt;
This noise is caused by the text under the picture which is not divided into columns. The same can be observed from the noise between the fifth and sixth columns.&lt;br /&gt;
&lt;div align="center"&gt;
&lt;a href="http://lh4.ggpht.com/-Pr0w73x2_HY/T5k0jiV48II/AAAAAAAAAZg/6X56oG60eHU/s1600-h/005%25255B2%25255D.png"&gt;&lt;img alt="005" border="0" height="124" src="http://lh5.ggpht.com/-wbQxhYoNq5I/T5k0kZYu-tI/AAAAAAAAAZk/1cnJwcw3n9c/005_thumb.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="005" width="244" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div align="center"&gt;
&lt;a href="http://lh6.ggpht.com/-lDw_4M7Qkww/T5k0lQ4D8KI/AAAAAAAAAZw/k5UOohAWBrQ/s1600-h/0051%25255B2%25255D.png"&gt;&lt;img alt="0051" border="0" height="232" src="http://lh4.ggpht.com/-Wd-dhBmfS8Q/T5k0muK83WI/AAAAAAAAAZ4/8p9Hh2poOo0/0051_thumb.png?imgmax=800" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="0051" width="244" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Download this &lt;a href="http://download.tallcomponents.com/GlyphHistograms.zip"&gt;Visual Studio .NET project&lt;/a&gt; to construct histograms yourself.&lt;br /&gt;
&lt;br /&gt;
Author: Sergey Zavoloka&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/pfH7XInWJRo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/pfH7XInWJRo/searching-text-and-recognizing-columns.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-Ciq_AwD4-U0/T5k0V0T-v5I/AAAAAAAAAYI/J2qnhMl0mCM/s72-c/2%252520columns_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/05/searching-text-and-recognizing-columns.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-6016257995766544323</guid><pubDate>Wed, 25 Apr 2012 08:31:00 +0000</pubDate><atom:updated>2012-04-25T12:50:56.675+02:00</atom:updated><title>Rasterizing WinRT</title><description>Earlier we posted that creating WinRT editions should be painless.&lt;br&gt;&lt;br&gt; &lt;p&gt;Well, today we rewrite that “should”. Our earlier blog mostly talked about deployment, assuming that the WinRT graphical API would basically be similar to the non-Metro API. This assumption turned out to be incorrect. WinRT does not offer GDI+ (System.Drawing), nor does it offer WPF (Windows Presentation Foundation) in all its glory. It does appear to be remarkably similar to the SilverLight API, but there are some serious differences.  &lt;ul&gt; &lt;li&gt;Clipping: similar to Silverlight, all graphical elements have a &lt;em&gt;Clip&lt;/em&gt; property. In WinRT however this is no longer has the general &lt;em&gt;Geometry &lt;/em&gt;type, but it has been restricted to a &lt;em&gt;RectangleGeometry&lt;/em&gt;. There is also no &lt;em&gt;OpacityMask &lt;/em&gt;in WinRT. At this point it is not clear to us how we can achieve any form of non-rectangular clipping (which is ubiquitous in PDF documents).  &lt;li&gt;Images: similar to Silverlight, it is possible to use a &lt;em&gt;WritableBitmap&lt;/em&gt; to fill images with binary pixel data. In Silverlight, one can use &lt;em&gt;SetSource()&lt;/em&gt; to specify a stream of ARGB values (bytes). In WinRT however, one needs to assign an instance of &lt;em&gt;IRandomAccessStream&lt;/em&gt;. It is not clear to us yet how we can create such an instance for (for example) a stream of data. There appears to be no standard solution for using a &lt;em&gt;MemoryStream&lt;/em&gt; as an &lt;em&gt;IRandomAccessStream&lt;/em&gt;, which looks like a serious omission to us. We tried to create our own simple implementation based on a &lt;em&gt;MemoryStream&lt;/em&gt;, but alas, so far this just started throwing unclear exceptions (to be continued some other time…)&amp;nbsp;&amp;nbsp; &lt;li&gt;Radial Shadings: WinRT has &lt;em&gt;no&lt;/em&gt; Radial shadings&lt;!--EndFragment--&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;To illustrate this: we have been able to arrive at a first internal version of PDFRasterizer.NET for metro, using some stubs for various parts. We obtained the following result:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-BQ-PihbfTJE/T5fWg47HFfI/AAAAAAAAAXo/9URYmAubPcQ/s1600-h/metro-rast3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="metro-rast" border="0" alt="metro-rast" src="http://lh6.ggpht.com/-jWq4lYhVf0o/T5fWh5TjM9I/AAAAAAAAAXw/DH02WVpLIF8/metro-rast_thumb.png?imgmax=800" width="560" height="363"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;While Adobe Reader shows this file as:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Cz_ak8GW5eo/T5bNSd0zZSI/AAAAAAAAAXI/6N7_2ima_fY/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-PsjEQDxcMwE/T5bNTv0CqJI/AAAAAAAAAXQ/4xwW3etHtvA/image_thumb%25255B1%25255D.png?imgmax=800" width="342" height="379"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;We expect that we will be able to solve (or work around) the image loading problems if we look into this a bit further. And for now we assume that radial shading is just something that just did not make it into the preview release. The Metro Clipping issue is quite serious however, if it is not an accidental restriction. The same applies to the omission of the &lt;em&gt;OpacityMask&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;I should also mention that the depicted rendering differences are not &lt;em&gt;all&lt;/em&gt; related to the issues mentioned above. We simply did not have the time yet to implement some of the more complex shadings. This mostly applies to the bottom part of the page. This also means however, that it is not yet entirely certain that we will not encounter additional issues there.&lt;/p&gt; &lt;p&gt;Interestingly, Windows 8 comes with a metro-style PDF viewer. This shows this document as follows:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-prgDqbLFb2Y/T5bNVjwhvdI/AAAAAAAAAXY/q6w9G8-LE7s/s1600-h/metro-std%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="metro-std" border="0" alt="metro-std" src="http://lh6.ggpht.com/-pHKvhjOYHXE/T5bNWkGhlwI/AAAAAAAAAXg/JfIXqcAVpjA/metro-std_thumb%25255B2%25255D.png?imgmax=800" width="576" height="380"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This shows the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The radial shading at the bottom left is also missing in the built-in viewer. This seems to support our assumption that radial shading is just something that just did not make it into the preview release.  &lt;li&gt;This viewer does not suffer from the clipping restriction. This seems to suggest that it either uses some internal features that we do not have access to, or it uses an different platform altogether, possibly C++ and DirectX. The problem with DirectX however is that there is no C# binding for DirectX and even if there were it cannot be mixed with XAML for as far as we know. So at present this is no option for us.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;At this point, we feel that the preview release of WinRT is still a bit too limited to actually implement a full-blown viewer for it. We are driving the metro but some of the stations are missing.&lt;/p&gt; &lt;p&gt;&lt;br&gt;Author: Marco Kesseler&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/AiIQ0dIKcns" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/AiIQ0dIKcns/rasterizing-winrt.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh6.ggpht.com/-jWq4lYhVf0o/T5fWh5TjM9I/AAAAAAAAAXw/DH02WVpLIF8/s72-c/metro-rast_thumb.png?imgmax=800" height="72" width="72" /><thr:total>10</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/04/rasterizing-winrt.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-6732463397589666468</guid><pubDate>Mon, 19 Mar 2012 10:18:00 +0000</pubDate><atom:updated>2012-03-19T11:44:48.471+01:00</atom:updated><title>A Second Office in Russia – Part 1</title><description>A huge step for every business owner is to hire that first helping hand. Until that point you run your business as lean as possible: by yourself. Because of that first employee you need to deal with legal obligations, income taxes, salary negotiation, dividing tasks, etc. And not to forget, you suddenly are a bit of a boss.&lt;br&gt;&lt;br&gt;Something similar holds for a second office.&lt;br&gt; &lt;h2&gt;&lt;br&gt;&lt;/h2&gt; &lt;h2&gt;The first minute&lt;/h2&gt;Our second office started March 1st, 2012. Here is a Skype video screenshot of the first minute. I am in The Netherlands, Tegelen and my time is 3 AM in the night. My new colleagues are in Russia, Novosibirsk Academgorodok (6000 km away) and their time is 9 AM. How do you like my bed look?&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;table style="text-align: center; margin-left: auto; margin-right: auto" class="tr-caption-container" cellspacing="0" cellpadding="0" align="center"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td style="text-align: center"&gt;&lt;a style="margin-left: auto; margin-right: auto" href="http://1.bp.blogspot.com/-C6QFcm-fviE/T2RSspa2DTI/AAAAAAAAAWs/k8RlxkqAi1k/s1600/kickoff.png" imageanchor="1"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-C6QFcm-fviE/T2RSspa2DTI/AAAAAAAAAWs/k8RlxkqAi1k/s400/kickoff.png" width="400" height="395"&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td style="text-align: center" class="tr-caption"&gt;From left to right: Alexander, Konstantin, Alex and me&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br&gt; &lt;h2&gt;&lt;br&gt;&lt;/h2&gt; &lt;h2&gt;How it started&lt;/h2&gt;During summer, we have our lunch in the garden whenever possible. During one of those lunches in summer 2011, I was telling about my previous experiences 4 years ago with a remote team in Poland. I deliberately did not call it a second office because it never felt that way. Í was just hiring people from another company. The mission failed miserably. Mostly because I selected a company based on the promises of management and I trusted too much on their selection skills.&lt;br&gt;&lt;br&gt;Again we were in the position that the company needed more developers. I felt that we were not keeping up with support. Sergey started working for TallComponents early 2011 after he moved from Russia to The Netherlands. He suggested that a friend of him, might be able to help me bootstrap this idea.&lt;br&gt;&lt;br&gt;Alex and I met on Skype. I expressed that I wasn't looking for outsourcing work. Instead, I was looking for new colleagues. That appealed strongly. Alex came up with a team of three developers (including himself) that already knew each other intimately from college and did many development projects together. That sounded like a jump start.&lt;br&gt; &lt;h2&gt;&lt;br&gt;&lt;/h2&gt; &lt;h2&gt;&lt;span style="color: #222222"&gt;&lt;/span&gt;Pilot&lt;/h2&gt; &lt;p&gt;My girlfriend convinced me to do a pilot in The Netherlands. Fly over the guys and have them work on a project for a few weeks. This way, we would get to know each other both personally and professionally. I agreed with the candidate team that they would visit the Dutch office for two weeks. We set a goal: at the end of this period we should have a feature complete XPS to PDF converter with automated tests in place. The converter would be build on top of &lt;a href="http://www.tallcomponents.com/pdfkit4.aspx"&gt;PDFKit.NET 4.0&lt;/a&gt;. This way I would not yet have to expose any source code to the team.&lt;/p&gt; &lt;p&gt;But I had a second plan. A business case had emerged that required a Silverlight edition of our PDF render engine. I decided to change the goal and have them port our PDF render code to Silverlight. This plan had one drawback: I had to expose our source code. &lt;/p&gt; &lt;p&gt;The team visited our Dutch office. On Monday morning, they entered the office. Chilly atmosphere. Uncomfortable talks. It didn’t feel good. I quickly changed the goal of the pilot back to the XPS to PDF converter. An hour later I told a long time employee about my decision and he started working on getting our PDF render code ready for Silverlight. &lt;/p&gt; &lt;p&gt;Later on I learned that Russians and Western Europeans behave totally different in a first meeting. It was an interesting lesson. &lt;/p&gt; &lt;p&gt;They did an excellent job. At the end of the two week pilot we had a working XPS to PDF converter and automated tests were in place. The team expressed that they were looking forward to work at TallComponents. And I wanted to have them on board. The next goal was to have the Russian office up and running March 1st, 2012.&lt;/p&gt; &lt;h2&gt;&lt;br&gt;&lt;/h2&gt; &lt;h2&gt;Coming up&lt;/h2&gt;In Part 2, I will blog about my one week visit to Novosibirsk during which we prepared the office for the March 1st start. In a part 3, I want to share our collaboration challenges that come with a second office.&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/YbFpv6ytjLw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/YbFpv6ytjLw/second-office-in-russia-part-1.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-C6QFcm-fviE/T2RSspa2DTI/AAAAAAAAAWs/k8RlxkqAi1k/s72-c/kickoff.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/03/second-office-in-russia-part-1.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-188430840717148762</guid><pubDate>Thu, 16 Feb 2012 14:56:00 +0000</pubDate><atom:updated>2012-02-16T15:56:41.458+01:00</atom:updated><title>How to PEVerify Silverlight</title><description>&lt;p&gt;Ever ran PEVerify on a Silverlight assembly, and you got something like this?&lt;/p&gt;&lt;p&gt;&lt;hr&gt;[….many errors snipped…]&lt;/p&gt;&lt;p&gt;&lt;font style="" face="Courier New"&gt;&lt;strong&gt;[IL]: Error: [D:\SVN\Components\bin\PDFRasterizer.NET\SL4\STANDARD4\TallComponents.PDF.Rasterizer.dll : TallComponents.Images.ImageProperties::.ctor]&amp;nbsp; [HRESULT 0x80070002] - The system cannot find the file specified.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font style="" face="Courier New"&gt;&lt;strong&gt;[IL]: Error: [D:\SVN\Components\bin\PDFRasterizer.NET\SL4\STANDARD4\TallComponents.PDF.Rasterizer.dll : TallComponents.Images.ImageProperties::get_TransparentColor]&amp;nbsp; [HRESULT 0x80070002] - The system cannot find the file specified.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font style="" face="Courier New"&gt;&lt;strong&gt; [HRESULT 0x80070002] - The system cannot find the file specified.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font style="" face="Courier New"&gt;&lt;strong&gt;196 Error(s) Verifying TallComponents.PDF.Rasterizer.dll&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;hr&gt;&lt;/p&gt;&lt;p&gt;Look in Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0 (or whatever version you are using). Copy all assemblies to the same folder as your Silverlight assembly. Run PEVerify again, et voila:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;strong&gt; &lt;hr&gt;Microsoft (R) .NET Framework PE Verifier.&amp;nbsp; Version&amp;nbsp; 4.0.30319.1&lt;br /&gt;
Copyright (c) Microsoft Corporation.&amp;nbsp; All rights reserved.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;&lt;strong&gt;All Classes and Methods in TallComponents.PDF.Rasterizer.dll Verified.&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;hr&gt;Assuming of course that you use an up-to-date version of peverify and that your assembly in fact does not contain any issues that PEVerify checks for.&lt;/p&gt;&lt;p&gt;Author: Marco Kesseler&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/fskg4syEOsI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/fskg4syEOsI/how-to-peverify-silverlight.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/02/how-to-peverify-silverlight.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-2413992570431677788</guid><pubDate>Thu, 09 Feb 2012 13:16:00 +0000</pubDate><atom:updated>2012-02-09T14:16:22.414+01:00</atom:updated><title>Help, my images have white stripes</title><description>&lt;p&gt;In PDF, there are often images that actually consist of a collection of smaller ones, neatly put next to each other.&lt;/p&gt;&lt;p&gt;Rendering these images seems easy enough in GDI+: just call the proper “DrawImage” method and that’s it. But then you discover that there are ugly stripes between the images.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-ll6MHKlVj7Q/TzPA1ccdrpI/AAAAAAAAAUY/FxApo98_XBY/s1600-h/image3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-42JS8FRFJUw/TzPA2pxK28I/AAAAAAAAAUg/ZP4zTW6cltA/image_thumb1.png?imgmax=800" width="326" height="267"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;What happens is the following: when the first of these images gets drawn, its edges are interpolated with the background color around the image, which is white &lt;em&gt;at that point&lt;/em&gt;. This results in a smooth border that is almost completely white at the very edge. Then, when the neighbouring image gets drawn, its edges get interpolated again, this time with the lighter edge of the previous image.&lt;/p&gt;&lt;p&gt;All in all, the image edges get interpolated against a background color that actually should never have been visible in the first place.&lt;/p&gt;&lt;p&gt;A simple solution is to fool GDI+ and tell it that we do not intend to draw a single image, but that it is part of a tiling pattern where the images get flipped over both the X-axis and the Y-axis:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;using (System.Drawing.Imaging.ImageAttributes attrs = new System.Drawing.Imaging.ImageAttributes())&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;font face="Courier New"&gt;{&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; attrs.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;font face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; graphics.DrawImage(&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bitmap,&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rectangle,&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0, 0, width, height,&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Drawing.GraphicsUnit.Pixel, attrs);&lt;/font&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;font face="Courier New"&gt;}&lt;/font&gt;&lt;/p&gt;&lt;p&gt;The image will be clipped against the given rectangle, so we won’t actually &lt;em&gt;see&lt;/em&gt; any tiling happening, but GDI+ is now aware that the edges of the image are not drawn against a white background. In fact, it still interpolates de edges of each image, but it now does so against the edges of the neigbouring (but invisible) tile, which has the same colors (that is why we need flipping):&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-JtSrtDWKAEs/TzPA3kN-MYI/AAAAAAAAAUo/fm7XXjP4ykE/s1600-h/image7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-KuLYcJaqJr0/TzPA5DpKyII/AAAAAAAAAUw/UMyV_ofmJHM/image_thumb3.png?imgmax=800" width="330" height="329"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Arial"&gt;There are of course also drawbacks to this technique: if an image has a very sharp transition near its edge, one still sees the interpolation happening. See the “belly” of the “S” below.&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/-aWW1R1fSCuQ/TzPA564px8I/AAAAAAAAAU0/4kUaKHdb6tM/s1600-h/image22.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-mEF6d6XMO9M/TzPA6WoplCI/AAAAAAAAAVA/qOHvxgnWq7k/image_thumb12.png?imgmax=800" width="94" height="88"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;However, if we use some heuristics to avoid the tiling technique in certain cases we can largely avoid such issues:&lt;/p&gt;&lt;p align="center"&gt;&amp;nbsp;&lt;a href="http://lh6.ggpht.com/-BMwxDDVKlco/TzPA70tP-6I/AAAAAAAAAVI/05SBBaa_ODw/s1600-h/image28.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-M6GEFt7KaA8/TzPA8st-0AI/AAAAAAAAAVQ/vBBPZbG82-g/image_thumb16.png?imgmax=800" width="91" height="103"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;We must admit that we are probably not the only ones that thought of this. The following image is from Adobe Reader X. It appears that it does something similar – see the top edge –, although of course it is impossible to say whether it really uses the same technique.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/-4bS01_Ga8v0/TzPA9HlCzVI/AAAAAAAAAVU/MLTL1rlW_mE/s1600-h/image29.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/-vdDWvRo_Zso/TzPA9zZOepI/AAAAAAAAAVg/epGDRpqXYIc/image_thumb17.png?imgmax=800" width="381" height="240"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Author: &lt;a href="mailto:marco@tallcomponents.com"&gt;Marco Kesseler&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/sxajhxKF6Ik" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/sxajhxKF6Ik/help-my-images-have-white-stripes.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-42JS8FRFJUw/TzPA2pxK28I/AAAAAAAAAUg/ZP4zTW6cltA/s72-c/image_thumb1.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/02/help-my-images-have-white-stripes.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-9099821318891403681</guid><pubDate>Thu, 02 Feb 2012 11:42:00 +0000</pubDate><atom:updated>2012-02-02T12:42:26.590+01:00</atom:updated><title>Problem saving WPF as XPS.</title><description>&lt;p&gt;It turns out that XPS is sometimes trickier to generate than plain WPF elements.&lt;/p&gt;&lt;p&gt;We recently encountered a PDF file, that we were able to convert to a WPF FixedDocument instance, and view in a standard DocumentViewer:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-BsJ3wQ2OuQ4/Tyk9t8qAlEI/AAAAAAAAATY/c1O-JnhXhb4/s1600-h/image%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-8R1fzbNC2RA/Tyk9wUlklMI/AAAAAAAAATg/lSeM7yQzAp0/image_thumb%25255B1%25255D.png?imgmax=800" width="428" height="235"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;However, when we used “Save as XPS” from the DocumentViewer window and tried to view the resulting XPS file, we got the following:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-7SRHeCQiqd0/Tyk9w6h4qLI/AAAAAAAAATo/pbmgxNXoMMM/s1600-h/image29.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-SCU1Et3b7WI/Tyk9xrxGueI/AAAAAAAAATw/R8-FGKMH28g/image_thumb11.png?imgmax=800" width="415" height="307"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Closer inspection of the XPS file revealed that the page contained the following snippet for one of the text strings on the page:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/-SCqVOkegbYk/Tyk9yjvNoAI/AAAAAAAAAT0/owq1VYcKd0A/s1600-h/image41.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="Glyphs Indices -1" src="http://lh4.ggpht.com/-BCHMK96Svz0/Tyk9zSWxvQI/AAAAAAAAAUA/ySLB2I5liJM/image_thumb19.png?imgmax=800" width="717" height="87"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The “Indices” attribute suggests that it holds the indices of each glyph in a font, but it commonly specifies the exact placement each glyph. The snippet above does this too. It specifies the placement of the next glyph relative to the previous one.&lt;/p&gt;&lt;p&gt;During the computation of the location of one character, we arrived at a position that was slightly offset to the left compared to the previous one. And so we produced the offset –1. In PDF this is not necessarily an error. In principle, this technique may be used to place several glyphs on top of each other in order to produce a single “combined character”, such as characters with diacritical marks or ligatures. In practice however, negative offsets are often avoided.&lt;/p&gt;&lt;p&gt;This particular case was a bit unclear. It involved some invisible text that consisted of seemingly random codes. Consequently, we chose simply to ignore the negative offset:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-o4IwPgRUI7g/Tyk90Gy10JI/AAAAAAAAAUE/clDPZlafD74/s1600-h/image51.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="Glyphs Indices" src="http://lh5.ggpht.com/-c_xX--uGzHQ/Tyk9057wVvI/AAAAAAAAAUQ/1OLuzl-l5n4/image_thumb25.png?imgmax=800" width="741" height="90"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;And now all is well again. It remains to be seen however if we encounter cases where such negative offsets are more critical. The most interesting part is of course that having a valid WPF instance does not guarantee that the resulting XPS document is alright.&lt;/p&gt;&lt;p&gt;Author: &lt;a href="mailto:marco@tallcomponents.com"&gt;Marco Kesseler&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/QEbwXWhfiWo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/QEbwXWhfiWo/problem-saving-wpf-as-xps.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/-8R1fzbNC2RA/Tyk9wUlklMI/AAAAAAAAATg/lSeM7yQzAp0/s72-c/image_thumb%25255B1%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/02/problem-saving-wpf-as-xps.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-3570850241008995481</guid><pubDate>Mon, 23 Jan 2012 09:31:00 +0000</pubDate><atom:updated>2012-01-23T11:53:36.287+01:00</atom:updated><title>WinRT and C#/.NET Components</title><description>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/-KudECDmKGi4/Tx08ILjZsiI/AAAAAAAAARo/GVx8fG8ihao/s1600-h/Win8Platform%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: right; border-top: 0px; border-right: 0px; padding-top: 0px" title="Win8Platform" border="0" alt="Win8Platform" align="right" src="http://lh4.ggpht.com/-nyu7vmoiO7w/Tx08I13ny1I/AAAAAAAAARw/aX5CTZdcCN4/Win8Platform_thumb.png?imgmax=800" width="244" height="139"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Monday morning started with the following question in the sales inbox:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;“Do you plan to support Windows 8 Metro Style App’s using the WinRT API’s with a product like PDFRasterizer.NET? If so, when? We are in development now, so would you have a preview version that we could use during development?”&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This was the first request after Microsoft announced WinRT during their Build conference in Anaheim CA, September 2011. I googled around trying to quickly understand the implications of providing WinRT editions.Here are my first quick findings (in random order).&lt;/p&gt; &lt;h2&gt;#1: WinRT includes the .NET framework. &lt;/h2&gt; &lt;p&gt;So we do not have to port our C# code. Good thing! The included framework is .NET 4.5. To target this version we need Visual Studio .NET 2011. Caveat: VS 2011 only runs on Windows 8. &lt;/p&gt; &lt;h2&gt;#2: WinRT introduces a new file type: .winmd&lt;/h2&gt; &lt;p&gt;We can decide to either output a single .winmd including both API description and implementation. This is required to support non-managed languages such as JavaScript and C++. Or you can ship a pair of files: a DLL containing the implementation plus a .winmd containing the API description only. If you do this, only managed clients can use your component. Since it seems trivial to output a single .winmd (it is a project setting), I do not see a reason to restrict ourselves to managed clients only. &lt;/p&gt; &lt;h2&gt;#3: All public classes must be sealed&lt;/h2&gt; &lt;p&gt;We definitely don’t want this restriction to propagate to non-WinRT editions. We already have too much #if constructs cluttering our code so I prefer to post-process our normal assemblies to achieve this. We use &lt;a href="http://www.deepseaobfuscator.com/"&gt;DeepSea Obfuscator&lt;/a&gt; to obfuscate our assemblies. In fact we use it for much more such as changing accessiblity and injecting module assemblies, I called DeepSea’s CEO Ewout Prangsma (we happen to co-own this company) and asked whether DeepSea supports sealing classes in a compiled assembly. It does! In fact it already consumes .winmd files!&lt;/p&gt; &lt;p&gt;Looks like adding WinRT editions to our releases should be painless. In the next days we will do some experiments and build a small Metro app that renders PDF documents.&lt;/p&gt; &lt;p&gt;Author: Frank Rem&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/S9xsZvc66c4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/S9xsZvc66c4/winrt-and-cnet-components.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-nyu7vmoiO7w/Tx08I13ny1I/AAAAAAAAARw/aX5CTZdcCN4/s72-c/Win8Platform_thumb.png?imgmax=800" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/01/winrt-and-cnet-components.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-3150011628834912372</guid><pubDate>Wed, 04 Jan 2012 17:48:00 +0000</pubDate><atom:updated>2012-01-04T18:53:49.163+01:00</atom:updated><title>No one needs more than 6 MB of Silverlight</title><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;How small should Silverlight be?&lt;/p&gt; &lt;p&gt;I am not talking about market share, nor am I comparing it to HTML5. No: how small should it be compared to its big brother WPF?&lt;/p&gt; &lt;p&gt;If you start porting existing WPF code to Silverlight, you will soon discover that quite a bit is missing. MSDN does not help here. It does list some differences, but it does not say anything about the issues below.&lt;/p&gt; &lt;p&gt;First of all, Silverlight lacks method overloads. These are often easy to solve, but as we like to share our code as much as possible, we now have to add some comments warning against using the old overloads, as any non-suspecting programmer might easily break things again when working on non-Silverlight projects that share the same code. Luckily it is often possible to use extension methods to add the missing overloads.&lt;/p&gt; &lt;p&gt;Other easy fixes include the lack of collections like (the non-generic) ArrayList or HashTable.&lt;/p&gt; &lt;p&gt;Then there are missing parts that have an “existing” alternative. In WPF there are two ways in which graphics can be constructed. It is possible to “draw” in a constructive/declarative way by adding graphical elements as Children to other elements. But it is also possible to draw in a more imperative way using a DrawingContext. You will have to rewrite your code if you used the latter, because Silverlight only supports the former (yes, we used DrawingContext, because it resembles GDI+ more, which is were we came from...).&lt;/p&gt; &lt;p&gt;There are also missing parts that have a “new” alternative. There is no XmlNode. You will have to use the Linq variant XNode. And XElement, and XAttribute, and XDocument, and etc. So bascically all the old functionality is there, but you “just” need to use the new classes. If you have a lot of code, the best way is to recreate your own “Xml” classes and map all functionality onto the Linq “X” variants.&lt;/p&gt; &lt;p&gt;Cloning is also (largely?) missing. You will have to implement it if you need it. And you probably will, because sharing Graphical elements in a visual tree will lead to exceptions. It boggles the mind why someone decided to omit cloning &lt;em&gt;without&lt;/em&gt; tackling the sharing exceptions in the visual tree.&lt;/p&gt; &lt;p&gt;And then there is missing functionality for which there is &lt;em&gt;no&lt;/em&gt; alternative. At one point, we needed to take the intersection of two geometries in Silverlight, and we found no way to do it. Of course we encountered this &lt;em&gt;after&lt;/em&gt; doing all of the above. It never occurred to me that something like this would not exist in Silverlight. Some suggested using a geometry group, but these only provide unions, not intersections. It &lt;em&gt;almost&lt;/em&gt; proved to be a show-stopper. &lt;/p&gt; &lt;p&gt;But we were lucky: we only needed the intersection of two regions for &lt;em&gt;clipping&lt;/em&gt;. It turned out that one can put a canvas with a particular clipping geometry an use it inside another canvas with another clipping geometry. And if you then draw inside the inner canvas, all graphics get clipped against both, which is effectively the same as clipping against the intersection of both geometries.&lt;/p&gt; &lt;p&gt;I am now left wondering whether Microsoft actually &lt;em&gt;foresaw&lt;/em&gt; this use of nested canvases, and decided that geometry intersection was therefore not required, or whether this was just an &lt;em&gt;accidental&lt;/em&gt; omission.&lt;/p&gt; &lt;p&gt;What is it with Silverlight and being small? I suspect that many programmers write “glue” code in order to port existing code to Silverlight. This all adds up to the size of their own apps, which have to be downloaded over and over again. It seems far more sensible if Microsoft were to write this glue code once and put it in Silverlight itself. I mean: what does it matter if the Silverlight installer is 6 MB or 30?&lt;/p&gt; &lt;p&gt;I suspect that only programmers care. Praising the small size of Silverlight is like saying that 640 KB should be enough for anybody in a time that half the world is busy downloading movies over the internet.&lt;/p&gt; &lt;p&gt;Author: &lt;a href="mailto:marco@tallcomponents.com"&gt;Marco Kesseler&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/kYgUQmoGEr4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/kYgUQmoGEr4/no-one-needs-more-than-6-mb-of.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2012/01/no-one-needs-more-than-6-mb-of.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-2704926096343121175</guid><pubDate>Mon, 29 Aug 2011 09:20:00 +0000</pubDate><atom:updated>2011-08-29T11:43:53.175+02:00</atom:updated><title>What the Hack?</title><description>&lt;p&gt;A while ago, we got notified that PDFRasterizer.Net was hacked. Some guy – it probably is a guy – posted it at a Czech forum. I could not actually access the hacked software, as I did not have sufficient rights, but it was obvious. There were even requests for hacking some of our other libraries.&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-1q_68qE2JME/TltZxQTcKyI/AAAAAAAAAPc/K4Y-MVOCUGA/s1600-h/image15.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/-5RPVKkgzeIE/TltZx5ptfPI/AAAAAAAAAPg/HOAs4Z-1n00/image_thumb9.png?imgmax=800" width="545" height="173"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I created an account and posted a reply pointing out that this guy was a scoundrel. I included a link to our own website and I reported the post to the web site owner.&lt;/p&gt; &lt;p&gt;They did not like it:&lt;a href="http://lh5.ggpht.com/-6ufMUrWKub0/TltZ0bjwMpI/AAAAAAAAAPk/EYwqWYxIjas/s1600-h/image6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/-R3GL2n6Ncrc/TltZ0lQhXdI/AAAAAAAAAPo/2UTBlf3Xk4A/image_thumb4.png?imgmax=800" width="575" height="151"&gt;&lt;/a&gt;Darn.&lt;/p&gt; &lt;p&gt;Of course we can start legal actions against every site that does this. But that will cost a lot. No self-respecting company is going to shop on these forums for our software. And the boys that do look there are not going to buy anything from us period.&lt;/p&gt; &lt;p&gt;So we are telling ourselves that this is free publicity, and… some form of recognition. We must be doing something right if we get their interest.&lt;/p&gt; &lt;p&gt;Author: &lt;a href="mailto:marco@tallcomponents.com"&gt;Marco Kesseler&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/kvVrYRzwjDg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/kvVrYRzwjDg/what-hack.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-5RPVKkgzeIE/TltZx5ptfPI/AAAAAAAAAPg/HOAs4Z-1n00/s72-c/image_thumb9.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/08/what-hack.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-698705016972713887</guid><pubDate>Thu, 07 Jul 2011 14:10:00 +0000</pubDate><atom:updated>2011-07-07T16:10:46.915+02:00</atom:updated><title>Opacity masks in WPF – how can we use them imperatively?</title><description>&lt;p&gt;During the implementation of PDF soft masks in our WPF version of PDFRasterizer.NET we realized that there is little information about WPF opacity masks on the internet. The only information that exists is about applying masks declaratively (in XAML) but it is unclear how to use them imperatively.  &lt;p&gt;I assume that you are familiar with the concept of WPF opacity masks, otherwise you can read about it &lt;a href="http://msdn.microsoft.com/en-us/library/ms743320.aspx"&gt;here&lt;/a&gt;.  &lt;p&gt;There are two approaches how an opacity mask can be applied to an instance of the Visual class. The first approach is to assign an opacity mask to a drawing visual instance. This approach has several restrictions that reduce its flexibility. First of all, the mask is applied only when the Close() method of the DrawingContext is called. Hence, only one mask can be applied. And secondly, the mask is applied to whole the drawing, not to a particular part.  &lt;p&gt;The second approach is to use a pair of PushOpacityMask and Pop operations (let’s just call it Push/Pop below). These are performed on a drawing context instance. &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.media.drawingcontext.pushopacitymask.aspx"&gt;Msdn&lt;/a&gt; offers hardly any information on this. This is the only information we could find:  &lt;p&gt;&lt;i&gt;“The mask is applied to all subsequent drawing commands until it is removed by the Pop operation”&lt;/i&gt;  &lt;p&gt;&lt;i&gt;&lt;/i&gt; &lt;p&gt;Internet resources do not give any additional description of the Push/Pop approach either.  &lt;p&gt;Let’s try to understand how Push/Pop works. In order to do this we will perform several experiments. We need four pictures. The first is shading.  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-6Ir4aKuYyvA/ThW7haStD5I/AAAAAAAAAOM/3RgcRHOZtIY/s1600-h/image0012.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image001" border="0" alt="image001" src="http://lh5.ggpht.com/-CVTfpl236mE/ThW7iHMzdAI/AAAAAAAAAOQ/2RKl60Kdn-M/image001_thumb.png?imgmax=800" width="244" height="244"&gt;&lt;/a&gt;  &lt;p&gt;The inverted shading:  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-lKN07mF_ptk/ThW7ipmQqkI/AAAAAAAAAOU/ac1j0BtPrzs/s1600-h/image0032.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image003" border="0" alt="image003" src="http://lh5.ggpht.com/-_opmhWUVvjk/ThW7jDQ3TwI/AAAAAAAAAOY/TNnOkQdfnuU/image003_thumb.png?imgmax=800" width="244" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The next picture is a nice background:&lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-QKrTOmQfzbI/ThW7kGAk8LI/AAAAAAAAAOc/ulU3crwL6CE/s1600-h/clip_image0067.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://lh3.ggpht.com/-eSsHglnNEXA/ThW7kiPbvgI/AAAAAAAAAOg/td5uOgSYJwQ/clip_image006_thumb4.jpg?imgmax=800" width="244" height="175"&gt;&lt;/a&gt;  &lt;p&gt;And a red circle to draw on the foreground:  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-AYiSZox0Re4/ThW7lKA4rRI/AAAAAAAAAOk/trgYaPUqyFo/s1600-h/image0073.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image007" border="0" alt="image007" src="http://lh5.ggpht.com/-ucPZ9Qn_SpA/ThW7lXlSTEI/AAAAAAAAAOo/P7Et6oV06eA/image007_thumb1.png?imgmax=800" width="200" height="200"&gt;&lt;/a&gt;  &lt;p&gt;What I’m going to do is to draw the background with the opacity mask and the red circle on the foreground with the inverted opacity mask.&lt;pre&gt;
//create an opacity brush
ImageBrush opacityMask = new ImageBrush();
opacityMask.ImageSource = new BitmapImage(new Uri("mask.png"));

//create an inverted mask
ImageBrush invertedOpacityMask = new ImageBrush();
invertedOpacityMask.ImageSource = new BitmapImage(new Uri("invertedMask.png"));

//load an image from file
ImageSource clouds = new BitmapImage(new Uri("clouds.png"));
//load the red circle from file
ImageSource redCircle = new BitmapImage(new Uri("redCircle.png"));

DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext dc = drawingVisual.RenderOpen();

//push the opacity mask
dc.PushOpacityMask(opacityMask);

//draw the background
dc.DrawImage(clouds, new Rect(0, 0, clouds.Width, clowds.Height));
dc.Pop();

//push the inverted opacity mask
dc.PushOpacityMask(invertedOpacityMask);
//draw the red circle
dc.DrawImage(redCircle, new Rect((clouds.Width – redCircle.Width)/20, 0, redCircle.Width, redCircle.Height));
dc.Pop();
dc.Close();

&lt;/pre&gt;&lt;p&gt;The result:  &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-beie8HQG5_8/ThW7nf7XtQI/AAAAAAAAAOs/X3aWswDfMpw/s1600-h/image009%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image009" border="0" alt="image009" src="http://lh6.ggpht.com/-NGMvp9MXPOo/ThW7oPnUIsI/AAAAAAAAAOw/nXll_z1rSMw/image009_thumb%25255B1%25255D.png?imgmax=800" width="240" height="147"&gt;&lt;/a&gt;  &lt;p&gt;Looks nice, isn’t it? That’s what I wanted. Notice, that we should call Pop() before we draw the red circle, otherwise the first mask would be applied to the red circle as well.  &lt;p&gt;But it is not entirely clear for which area the mask is applied. Is it scaled to fit the whole image?  &lt;p&gt;To take a better look at the matter I’ll take a transparent background image and draw a red square on it with the inverted shading as an opacity mask.  &lt;p&gt;Here is the result:  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-WpQmHMlKano/ThW7orHPfyI/AAAAAAAAAO0/oSGnpdeNA0s/s1600-h/image0112.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image011" border="0" alt="image011" src="http://lh3.ggpht.com/-zLrwQhS6Cp4/ThW7pJW5ojI/AAAAAAAAAO4/fa78sw3vHWQ/image011_thumb.png?imgmax=800" width="244" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;If the opacity mask is scaled to fit the picture, the red square should be fully opaque as it is placed in the fully dark part of the shade. We can see it from the schema below. &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-O-AVB2tVBSo/ThW7p0oFRNI/AAAAAAAAAO8/EUPWdRkI62w/s1600-h/image013%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image013" border="0" alt="image013" src="http://lh5.ggpht.com/-bGSBiKRasxw/ThW7qRJyhjI/AAAAAAAAAPA/CiB-2f_gxyw/image013_thumb%25255B2%25255D.png?imgmax=800" width="244" height="184"&gt;&lt;/a&gt;  &lt;p&gt;Apparently the opacity mask was applied to the red square only. The schema in this case should looks like this:  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-S9ECHyrP7y8/ThW7quERWhI/AAAAAAAAAPE/i1AtxpKdOrI/s1600-h/image015%25255B5%25255D.png"&gt;&lt;img style="display: inline" title="image015" alt="image015" src="http://lh6.ggpht.com/-ZvzV_QjGAZ0/ThW7rr0KPeI/AAAAAAAAAPI/f8t8Z2hN1KY/image015_thumb%25255B3%25255D.png?imgmax=800" width="240" height="180"&gt;&lt;/a&gt; &lt;p&gt;It looks like the opacity mask is being scaled to fit object which are drawn within Push/Pop scope. We will verify this by drawing a number of objects. You can see the result below:  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-yNwxwusqtnI/ThW7tSdubnI/AAAAAAAAAPM/ghy_7fVRJrM/s1600-h/image017%25255B2%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image017" border="0" alt="image017" src="http://lh4.ggpht.com/-xu3XJJ4ddZ4/ThW7udMdlCI/AAAAAAAAAPQ/WSWCgAK-Gbs/image017_thumb.png?imgmax=800" width="244" height="244"&gt;&lt;/a&gt; &lt;p&gt;Our assumption is correct – the opacity mask is scaled to fit the area where the objects have been drawn. The schema below represents it.  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-WjrX07vQ--w/ThW7vD-VE3I/AAAAAAAAAPU/UAdQtUW5xEU/s1600-h/image019%25255B3%25255D.png"&gt;&lt;img style="display: inline" title="image019" alt="image019" src="http://lh4.ggpht.com/-dOK_TR48v-4/ThW7vVIBliI/AAAAAAAAAPY/8D2rRLKRBWA/image019_thumb%25255B1%25255D.png?imgmax=800" width="240" height="180"&gt;&lt;/a&gt; &lt;p&gt;Conclusion  &lt;p&gt;We have gained some insight how the WPF opacity mask can be used imperatively. We learned:  &lt;ol&gt; &lt;li&gt;If you want only one opacity mask to be applied to the whole Visual, you can assign an opacity mask to the Visual instance. &lt;/li&gt;&lt;/ol&gt; &lt;ol start="2"&gt; &lt;li&gt;If you want to apply more than one mask to the Visual, you should use a pair of PushOpacityMask and Pop operations on a drawing context instance. &lt;/li&gt;&lt;/ol&gt; &lt;ol start="3"&gt; &lt;li&gt;If you want to apply an opacity mask to a particular set of drawings on the Visual, you should draw the set within the scope of PushOpacityMask/Pop. Keep in mind though, that the mask will be scaled to fit the drawing area of the entire set of elements. &lt;/li&gt;&lt;/ol&gt; &lt;ol start="4"&gt; &lt;li&gt;You can also apply the opacity mask to each drawing individually and this will produce a different visual effect.&lt;/li&gt;&lt;/ol&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/1ikdnawFzwI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/1ikdnawFzwI/opacity-masks-in-wpf-how-can-we-use.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-CVTfpl236mE/ThW7iHMzdAI/AAAAAAAAAOQ/2RKl60Kdn-M/s72-c/image001_thumb.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/07/opacity-masks-in-wpf-how-can-we-use.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-1806772226442472843</guid><pubDate>Thu, 30 Jun 2011 13:32:00 +0000</pubDate><atom:updated>2011-06-30T15:34:39.108+02:00</atom:updated><title>Raising the Bar</title><description>&lt;p&gt;I wanted to have a QR barcode on a PDF form, and I wanted it to get dynamically updated with the value of another form field. Sounds reasonable I think. Does not sound hard either. Let’s have a look at some trial and error in Adobe Acrobat.  &lt;p&gt;First step: I happily started Acrobat X and chose “Add Barcode Field”. It greeted me with the following message:  &lt;p&gt;&amp;nbsp; &lt;a href="http://lh5.ggpht.com/-iIO6RrHDwTM/Tgx6qB8wt3I/AAAAAAAAAMM/nNHDOY-sdY4/s1600-h/image001%25255B12%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image001" border="0" alt="image001" src="http://lh5.ggpht.com/-Vw3Kv8lPaaY/Tgx6qjg6daI/AAAAAAAAAMQ/VP5iy811VVs/image001_thumb%25255B8%25255D.png?imgmax=800" width="509" height="225"&gt;&lt;/a&gt; &lt;p&gt;I just ignored this. I am not doing any paper forms processing, am I? I am just adding a barcode to an electronic form. So, I added the Barcode field, set its “Symbology” to “QR Code” and pointed to the field “Text2” for its value.  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-NbDQTFAyZYU/Tgx6rEwqufI/AAAAAAAAAMU/gTAwIqTaGdE/s1600-h/image003%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image003" border="0" alt="image003" src="http://lh5.ggpht.com/-zkKR2cCU--0/Tgx6rabnQEI/AAAAAAAAAMY/60YgpwgrnE0/image003_thumb%25255B3%25255D.png?imgmax=800" width="482" height="191"&gt;&lt;/a&gt; &lt;p&gt;And sure enough, in Acrobat, when I type a value in the field named “Text2”, the barcode gets updated:  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-2RJhVZTQiS8/Tgx6r4gXMEI/AAAAAAAAAMc/LQTU-g1ppZ4/s1600-h/image005%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image005" border="0" alt="image005" src="http://lh4.ggpht.com/-guc1oJaZK24/Tgx6sb-S4FI/AAAAAAAAAMg/oDMZuAipgbg/image005_thumb%25255B3%25255D.png?imgmax=800" width="359" height="107"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;I was quite pleased, assuming that things would be the same in Reader. This is just another field isn’t it? But then I tried it, and…  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-OayeodEs0w8/Tgx6sxF0HuI/AAAAAAAAAMk/TTARFYmVjqs/s1600-h/image007%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image007" border="0" alt="image007" src="http://lh6.ggpht.com/-Qa34FY4sofo/Tgx6tYvALJI/AAAAAAAAAMo/5fr3d778ibo/image007_thumb%25255B2%25255D.png?imgmax=800" width="443" height="148"&gt;&lt;/a&gt; &lt;p&gt;Googling suggested that the document actually needs to be reader-enabled. So I went back to Acrobat X and chose Save As -&amp;gt; Reader Extended PDF -&amp;gt; Enable Additional Features. Again, we get a dialog box: &lt;/p&gt; &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-_kDB6q9251s/Tgx6ty0wlKI/AAAAAAAAAMs/_uqy71_YOD8/s1600-h/image009%25255B6%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image009" border="0" alt="image009" src="http://lh6.ggpht.com/-rjdFtEiJf2g/Tgx6u46O6EI/AAAAAAAAAMw/Zl0Q2CA4zho/image009_thumb%25255B4%25255D.png?imgmax=800" width="527" height="385"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Hmmm, it does not say anything about Barcodes. And indeed: after enabling Reader still does not update the barcodes. What now?  &lt;p&gt;Maybe it was not such a good idea to ignore the Barcoded Paper Forms Solution message after all. I opened Acrobat help, and entered “barcode paper forms solution”. The first hit on the “Community Help” page, was “Adobe LiveCycle ES2 * Using paper forms barcodes”. This lead to some general story about using paper forms barcodes. No prices, no product info, and certainly no howto. Well, I found a nice picture…  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-3HLsXGAIoes/Tgx6vXSToBI/AAAAAAAAAM0/j15PG4xkmVM/s1600-h/image011%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image011" border="0" alt="image011" src="http://lh5.ggpht.com/-YT1bYK9l1dQ/Tgx6wXR7xqI/AAAAAAAAAM4/ih0882_7F4s/image011_thumb%25255B2%25255D.png?imgmax=800" width="558" height="353"&gt;&lt;/a&gt; &lt;p&gt;And, at the end, there is the note “To make use of the paper forms barcode, your organization must have implemented LiveCycle Barcoded Forms”. Of course no link, just yet another term.  &lt;p&gt;At this point I felt very reluctant to start searching again. Apparently all this was related to LiceCycle Designer. Notice that the article says AdobeLiveCycle Designer &lt;i&gt;ES2&lt;/i&gt;. I have that as part of Acrobat Pro, so I started it up, opened the PDF and let it convert the document. Then it said this.  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-y-w2hPq-Qtg/Tgx6w28Cl8I/AAAAAAAAAM8/v-ET-9tDwFg/s1600-h/image013%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image013" border="0" alt="image013" src="http://lh4.ggpht.com/-_hPjuBaDpBo/Tgx6xiI1kaI/AAAAAAAAANA/MLZ8vF4i2M8/image013_thumb%25255B3%25255D.png?imgmax=800" width="513" height="171"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;Fair enough, even though Acrobat apparently had no problems with this. So, I dragged the Barcode field a bit bigger:  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-EKNsUCIxlck/Tgx6yNNQ0wI/AAAAAAAAANE/TfdtFuAiT7A/s1600-h/image015%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image015" border="0" alt="image015" src="http://lh4.ggpht.com/-5yhs3tX94x0/Tgx6yupl6SI/AAAAAAAAANI/oXi7fRSC6Q4/image015_thumb%25255B2%25255D.png?imgmax=800" width="478" height="147"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;My Script? What script? I enabled the script editor and saw that there was some javascript associated with the “calculate” event. Well, commented-out code actually:  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-1baylRPYOF8/Tgx6zMo0juI/AAAAAAAAANM/vLqunuIEQ3w/s1600-h/image017%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image017" border="0" alt="image017" src="http://lh3.ggpht.com/-F1jSa5Pcjag/Tgx6zzaXFVI/AAAAAAAAANQ/OBXHW2XpWAY/image017_thumb%25255B2%25255D.png?imgmax=800" width="496" height="366"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;Right, so now I am supposed to rewrite this into some FormCalc expression? I think not!  &lt;p&gt;Back to square one. We create an empty form in LiveCycle designer, and we choose &lt;i&gt;Insert – Barcodes – QRCode&lt;/i&gt; from the menu:  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-vErcTJZD0B8/Tgx60Hi3pAI/AAAAAAAAANU/nI2TctPSWcE/s1600-h/image019%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image019" border="0" alt="image019" src="http://lh5.ggpht.com/-3B9KPzluvDk/Tgx60itaegI/AAAAAAAAANY/Ya3VyLNzaL4/image019_thumb%25255B2%25255D.png?imgmax=800" width="425" height="212"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;And as an award, we now have a &lt;em&gt;read-only&lt;/em&gt; QR code on our form. There is nothing much we can do with that, except assigning some fixed value to it.  &lt;p&gt;Luckily the dialog box mentioned a “Paper Forms Barcode”. So we look in the menu again. Yes, there they are: &lt;i&gt;Insert – Barcodes – Paper Forms Barcodes&lt;/i&gt;. Again a tip (isn’t this great?)  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-jzCfHfnlBuU/Tgx61K-mS0I/AAAAAAAAANc/ikl0EhHFHbs/s1600-h/image021%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image021" border="0" alt="image021" src="http://lh6.ggpht.com/-jrr_MbGvdbw/Tgx61-TeSxI/AAAAAAAAANg/srUOq10JoVc/image021_thumb%25255B2%25255D.png?imgmax=800" width="441" height="327"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;Of course I am going to ignore the talk about separate licenses. we get:  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-6ib6dnnsuiw/Tgx62n3szDI/AAAAAAAAANk/e9QB0gUhrmg/s1600-h/image023%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image023" border="0" alt="image023" src="http://lh6.ggpht.com/-xEN51u8qRZ8/Tgx63aB89KI/AAAAAAAAANo/RJT01Te8u60/image023_thumb%25255B2%25255D.png?imgmax=800" width="412" height="167"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;I create a new text box, as well as a new collection, and I add the text box to it. I leave this as an exercise to the reader… You will probably get warnings about exceeding the barcode capacity. Just specify a maximum numbers of characters for the text field.  &lt;p&gt;And again, this is not going to work out-of-the-box for Adobe Reader. At least the effect is consistent:  &lt;p&gt;&amp;nbsp;&lt;a href="http://lh3.ggpht.com/-YwRm1O1vWWI/Tgx63-rD8HI/AAAAAAAAANs/nA7Ooz4GANY/s1600-h/image025%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image025" border="0" alt="image025" src="http://lh5.ggpht.com/-PBA5M5cN0MY/Tgx64I_QD6I/AAAAAAAAANw/6M3efNW1R_M/image025_thumb%25255B3%25255D.png?imgmax=800" width="241" height="199"&gt;&lt;/a&gt; &lt;p&gt;In LiveCycle designer, we choose &lt;i&gt;File – Distribute Form..&lt;/i&gt;. We choose “Manually collect responses in my email inbox”.  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-T9yPv-jvxME/Tgx644aLYnI/AAAAAAAAAN0/SMtAwGba_X4/s1600-h/image027%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image027" border="0" alt="image027" src="http://lh3.ggpht.com/-434RomJ-kKk/Tgx65aCp4TI/AAAAAAAAAN4/4WHS9LJbbzo/image027_thumb%25255B2%25255D.png?imgmax=800" width="401" height="199"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;On the next screen, we choose the second option (save a local copy). Then we specify an email address, and finish the wizard. We now have a “distributed” variant of our form. It should have been enabled, I think.  &lt;p&gt;And then….  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-JJOvezabWy8/Tgx65rxKzPI/AAAAAAAAAN8/MfG8Soycvhc/s1600-h/image029%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="image029" border="0" alt="image029" src="http://lh6.ggpht.com/-Y5Y5Tio8HzM/Tgx66GfdpQI/AAAAAAAAAOA/x2htRuPY72I/image029_thumb%25255B2%25255D.png?imgmax=800" width="279" height="227"&gt;&lt;/a&gt;&amp;nbsp; &lt;p&gt;I now read somewhere on the web that I actually need LiveCycle &lt;i&gt;RE&lt;/i&gt; (reader extensions) to enable dynamic barcodes in reader! I give up. Sigh. Why is it that Adobe treats barcodes so much different from other form fields? And why does this picture above even mention LiveCycle &lt;i&gt;ES2&lt;/i&gt;?&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/nTzP4gJB79o" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/nTzP4gJB79o/raising-bar.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/-Vw3Kv8lPaaY/Tgx6qjg6daI/AAAAAAAAAMQ/VP5iy811VVs/s72-c/image001_thumb%25255B8%25255D.png?imgmax=800" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/06/raising-bar.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-4003258332529664783</guid><pubDate>Mon, 20 Jun 2011 10:33:00 +0000</pubDate><atom:updated>2011-06-20T12:52:52.192+02:00</atom:updated><title>BitmapEncoder.Save puzzling behavior</title><description>&lt;p&gt;In our effort to release editions of our software that have no reference to the System.Drawing assembly, we are porting GDI+ code to WPF. While doing this, we encounter some puzzling behavior from System.Windows.Media.Imaging.BitmapEncoder.Save.&lt;/p&gt;
&lt;p&gt;We call BitmapEncoder.Save and pass it our own implementation of System.IO.Stream as follows:&lt;/p&gt;
&lt;pre&gt;using System.Windows.Media.Imaging;

BitmapFrame frame = BitmapFrame.Create(bitmapSource);
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(frame);
encoder.Save( myStream );&lt;/pre&gt;
&lt;p&gt;The object myStream is a derived stream which implements some overloads available in System.IO.Stream. We would expect that the Save method calls the Stream.Write method only and does not call Stream.Read. Our initial implementation of Stream.CanSeek and Stream.CanRead returns false and Stream.Read throws NotSupportedException as specified in the &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.stream.read.aspx"&gt;MSDN documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To our surprise, it turned out that the framework calls the Read method even though CanRead returns false!&lt;/p&gt;
&lt;p&gt;After some experimentation, we discovered that when CanSeek returns true, the framework does not call Read. But, even more surprisingly it never calls Seek.&lt;/p&gt;
&lt;p&gt;To summarize:&lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="2" width="302"&gt;
&lt;tbody&gt;
&lt;tr&gt;
   &lt;td valign="top" width="146"&gt;CanSeek&lt;/td&gt;
   &lt;td valign="top" width="72"&gt;false&lt;/td&gt;
   &lt;td valign="top" width="82"&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
   &lt;td valign="top" width="146"&gt;CanRead&lt;/td&gt;
   &lt;td valign="top" width="72"&gt;false&lt;/td&gt;
   &lt;td valign="top" width="82"&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
   &lt;td valign="top" width="146"&gt;CanWrite&lt;/td&gt;
   &lt;td valign="top" width="72"&gt;true&lt;/td&gt;
   &lt;td valign="top" width="82"&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
   &lt;td valign="top" width="146"&gt;Save calls Seek&lt;/td&gt;
   &lt;td valign="top" width="72"&gt;No&lt;/td&gt;
   &lt;td valign="top" width="82"&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
   &lt;td valign="top" width="146"&gt;Save calls Read&lt;/td&gt;
   &lt;td valign="top" width="72"&gt;Yes&lt;/td&gt;
   &lt;td valign="top" width="82"&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In other words, making the stream seekable, causes the framework to suddenly not call Read anymore, even though Seek is never called. This totally puzzles us.&lt;/p&gt;
&lt;p&gt;Any insightful comments are welcome!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/6R45FF59nDU" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/6R45FF59nDU/bitmapencodersave-puzzling-behavior.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/06/bitmapencodersave-puzzling-behavior.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-8010904647276794980</guid><pubDate>Mon, 06 Jun 2011 12:26:00 +0000</pubDate><atom:updated>2011-06-07T09:25:12.827+02:00</atom:updated><title>Architecture of an HTML Consumer</title><description>&lt;p&gt;
In this post I will roughly outline the architecture of our HTML to PDF converter. I believe it applies largely to any HTML consumer.&lt;/p&gt;
&lt;h2&gt;
STEP 1: Tidy&lt;/h2&gt;
&lt;p&gt;
The first step is to tidy the HTML. Most HTML documents are not well formed. Meaning that they are not XML documents. By first converting the HTML document into an equivalent XML document, we create the required conditions for the subsequent transformations. Typical tidy transformations include the following:&lt;/p&gt;
&lt;table border="0" cellspacing="0" cellpadding="2" width="557"&gt;&lt;tbody&gt;
&lt;tr&gt;       &lt;td valign="top" width="246"&gt;Before&lt;/td&gt;        &lt;td valign="top" width="309"&gt;After&lt;/td&gt;     &lt;/tr&gt;
&lt;tr&gt;       &lt;td valign="top" width="246"&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;heading
&amp;lt;h2&amp;gt;subheading&amp;lt;/h3&amp;gt;&lt;/pre&gt;
&lt;/td&gt; &lt;td valign="top" width="309"&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;heading&amp;lt;/h1&amp;gt;
&amp;lt;h2&amp;gt;subheading&amp;lt;/h2&amp;gt;&lt;/pre&gt;
&lt;/td&gt;     &lt;/tr&gt;
&lt;tr&gt;        &lt;td valign="top" width="246"&gt;Before&lt;/td&gt;        &lt;td valign="top" width="309"&gt;After&lt;/td&gt;      &lt;/tr&gt;
&lt;tr&gt;        &lt;td valign="top" width="246"&gt;
&lt;pre&gt;&amp;lt;i&amp;gt;&amp;lt;h1&amp;gt;heading&amp;lt;/h1&amp;gt;&amp;lt;/i&amp;gt;
&amp;lt;p&amp;gt;new paragraph &amp;lt;b&amp;gt;bold text
&amp;lt;p&amp;gt;some more bold text&lt;/pre&gt;
&lt;/td&gt;          &lt;td valign="top" width="309"&gt;
&lt;pre&gt;&amp;lt;h1&amp;gt;&amp;lt;i&amp;gt;heading&amp;lt;/i&amp;gt;&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;new paragraph &amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;some more bold text&amp;lt;/b&amp;gt;&lt;/pre&gt;
&lt;/td&gt;     &lt;/tr&gt;
&lt;tr&gt;       &lt;td valign="top" width="246"&gt;Before&lt;/td&gt; &lt;td valign="top" width="309"&gt;After&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign="top" width="246"&gt;
&lt;pre&gt;&amp;lt;body&amp;gt;
&amp;lt;li&amp;gt;1st list item
&amp;lt;li&amp;gt;2nd list item&lt;/pre&gt;
&lt;/td&gt; &lt;td valign="top" width="309"&gt;
&lt;pre&gt;&amp;lt;body&amp;gt;
&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;1st list item&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;2nd list item&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/pre&gt;
&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;
STEP 2: Execute JavaScript&lt;/h2&gt;
&lt;p&gt;
This step is far from trivial because it involves executing JavaScript. So one actually needs to build a JavaScript interpreter (or use an existing one). When we started working on our HTML converter, we already had our own JavaScript interpreter. But it was conditioned for JavaScript code that one typically finds in PDF documents. This type of JavaScript tends to be far less complex than the JavaScript in current HTML documents. We rarely receive a bug report related to JavaScript embedded in PDF documents. But when we started using the same interpreter with real-life HTML documents, it turned out to be flawed and having many deficiencies. Especially supporting the &lt;a href="http://en.wikipedia.org/wiki/JQuery" target="_blank"&gt;jQuery library&lt;/a&gt; turned out to be an enormous task. jQuery makes extensive use of more advanced JavaScript features such as prototypes and closures.&lt;/p&gt;
&lt;p&gt;
Here is a typical conversion that takes place when executing JavaScript:&lt;/p&gt;
&lt;table border="0" cellspacing="0" cellpadding="2" width="551"&gt;&lt;tbody&gt;
&lt;tr&gt; &lt;td valign="top" width="288"&gt;Before&lt;/td&gt;  &lt;td valign="top" width="261"&gt;After&lt;/td&gt; &lt;/tr&gt;
&lt;tr&gt; &lt;td valign="top" width="288"&gt;
&lt;p&gt;
&amp;lt;html&amp;gt;&lt;/br&gt;
&amp;#160;&amp;#160;&amp;lt;head&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;function load() {&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var x = document.getElementById(&amp;quot;foo&amp;quot;)&lt;br/&gt;
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; x.innerHTML = &amp;quot;Hello TallComponents!&amp;quot;;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;/script&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;/head&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;body onload=&amp;quot;load()&amp;quot;&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;h1 id=&amp;quot;foo&amp;quot;&amp;gt;Hello World!&amp;lt;/h1&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;/body&amp;gt;&lt;br/&gt; 
&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;/td&gt;  &lt;td valign="top" width="261"&gt;
&lt;p&gt;
&amp;lt;html&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;lt;body&amp;gt;&lt;br/&gt; 
&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;lt;h1&amp;gt;Hello TallComponents!&amp;lt;/h1&amp;gt;&lt;br/&gt;
&amp;#160;&amp;#160;&amp;lt;/body&amp;gt;&lt;br/&gt; 
&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;/td&gt; &lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;
&amp;#160;&lt;/h2&gt;
&lt;h2&gt;
STEP 3: Resolving CSS&lt;/h2&gt;
&lt;p&gt;
Cascading style sheets are used to separate content from presentation. CSS is resolved after JavaScript has been executed because JavaScript may also manipulate CSS. CSS can be specified in three ways:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;External stylesheet. These are specified using the LINK element as follows: 
&lt;pre&gt;&amp;lt;HEAD&amp;gt;
&amp;lt;LINK href=&amp;quot;special.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot;&amp;gt;
&amp;lt;/HEAD&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Inline stylesheet. These are speficied using the STYLE element as follows: 
&lt;pre&gt;&amp;lt;HEAD&amp;gt;
&amp;lt;STYLE type=&amp;quot;text/css&amp;quot;&amp;gt;
H1 {border-width: 1; border: solid; text-align: center}
&amp;lt;/STYLE&amp;gt;
&amp;lt;/HEAD&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Inline style. Here is a typical example: 
&lt;pre&gt;&amp;lt;P style=&amp;quot;font-size: 12pt; color: fuchsia&amp;quot;&amp;gt;
Aren't style sheets wonderful?
&amp;lt;/P&amp;gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
The CSS resolver transforms the HTML document such that it only has inline styles while being equivalent to the original document.&lt;/p&gt;
&lt;h2&gt;
STEP 4: LAYOUT&lt;/h2&gt;
&lt;p&gt;
Now that the HTML document has been normalized with respect to syntax and CSS and initialization JavaScript code has been executed and removed, all visual elements have to be placed and formatted. This is referred to as the layout step.&lt;/p&gt;
&lt;p&gt;
Although we convert to PDF, our layout module has been designed such that by implementing a specific interface we may just as well convert to SVG or GDI+.&lt;/p&gt;
&lt;h2&gt;
Remark&lt;/h2&gt;
&lt;p&gt;
While the above four steps have been presented as sequential steps, in reality they are performed more or less in parallel for performance reasons.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/nrPrU55tjdI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/nrPrU55tjdI/architecture-of-html-consumer.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/06/architecture-of-html-consumer.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-6457889383749250680</guid><pubDate>Mon, 30 May 2011 13:50:00 +0000</pubDate><atom:updated>2011-05-30T15:51:18.648+02:00</atom:updated><title>Two wrongs don’t make a right. Two negatives do make a positive</title><description>&lt;p&gt;We encountered a PDF document from a customer where we failed to geometrically sort the glyphs correctly. Glyphs appearing lower on the page were returned earlier in the sort order by the text extractor. &lt;/p&gt;  &lt;p&gt;It turned out that not only the font size, but also the horizontal scaling and finally the CTM (current transformation matrix) scaled the text negatively in both direction two times. The net result is positive of course. Our software should have handled all these scales using a generic algorithm but we dropped one: we took the absolute value of the horizontal scale (Tz operator).&lt;/p&gt;  &lt;p&gt;Here is a screenshot from our internal PDF nitpicker PDFSpy:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-HWQ4pSwEXvg/TeOgqi57_kI/AAAAAAAAALw/hT3ayrENq-U/s1600-h/clipped%25255B7%25255D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clipped" border="0" alt="clipped" src="http://lh4.ggpht.com/-2_AEvaoy3s8/TeOgrgOCLHI/AAAAAAAAAL0/05MoX8pojzw/clipped_thumb%25255B3%25255D.png?imgmax=800" width="584" height="347" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Operation 2 sets the vertical scale to –1. Operation 9 sets the font size to –5 (this is basically a negative scale in the horizontal and a negative scale in the vertical direction). Operation 11 sets the horizontal scale to –1 (the operand of the Tz operator must be divided by 100). When we take all this into account the scale in both directions is positive.&lt;/p&gt;  &lt;p&gt;We fixed this in &lt;a href="http://www.tallcomponents.com/pdfkit3-versions.aspx" target="_blank"&gt;maintenance update 3.0.63.0 of PDFKit.NET 3.0&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/jDbpWLPg95k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/jDbpWLPg95k/two-wrongs-dont-make-right-two.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-2_AEvaoy3s8/TeOgrgOCLHI/AAAAAAAAAL0/05MoX8pojzw/s72-c/clipped_thumb%25255B3%25255D.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/05/two-wrongs-dont-make-right-two.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-7697911774865540371</guid><pubDate>Thu, 26 May 2011 10:12:00 +0000</pubDate><atom:updated>2011-05-26T12:26:25.296+02:00</atom:updated><title>Testing our HTML to PDF Converter</title><description>&lt;p&gt;Among other tests, we use the &lt;a href="http://test.csswg.org/suites/css2.1/20110323/" target="_blank"&gt;W3C CSS 2.1 test suite&lt;/a&gt; to assure the quality of our HTML to PDF converter WebToPDF.NET. &lt;/p&gt;&lt;h2&gt;W3C Test Suite&lt;/h2&gt;&lt;p&gt;The test suite is published as a set of documents (.xht files) without a folder structure. The first thing we did was organize these files into folders that correspond to the different chapters of the CSS 2.1 specification. We wrote a little tool that generates this folder structure based on the chapter information that is stored in the metadata of each test document. This structure makes testing easier. E.g. if we change some code related to chapter 5, we first run these tests and once these are fine, we run the rest.&lt;/p&gt;&lt;h2&gt;Converting all HTML documents to PDF&lt;/h2&gt;&lt;p&gt;We use an internal command line tool that enumerates all the test documents and converts each .xht to PDF. If an exception occurs, we flag this test as ERROR. If no exception occurs, the PDF is stored in a temporary output folder. We then compare this PDF with a reference PDF document (this is what we expect the PDF to look like). This reference PDF document was created the first time that a converted PDF was manually approved. If a reference does not exist yet, the test is flagged as NO-REF. If the reference exists but the output differs, then the test is flagged as FAILED. Otherwise, it is flagged as &lt;font color="#008000"&gt;&lt;strong&gt;PASSED&lt;/strong&gt;&lt;/font&gt;. Obviously, the ultimate goal is to have all tests flagged as &lt;font color="#008000"&gt;&lt;strong&gt;PASSED&lt;/strong&gt;&lt;/font&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_xFqIw0kj-i8/TczwbD1qQ7I/AAAAAAAAAKQ/ynfKgxENztw/s1600-h/run7.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Running the conversion" border="0" alt="Running the conversion" src="http://lh5.ggpht.com/_xFqIw0kj-i8/Tczwb4Hx6HI/AAAAAAAAAKU/0MM5wtpIFqw/run_thumb5.png?imgmax=800" width="604" height="545" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The first time we ran the tests, each test was flagged either as ERROR (an exception occurred) or as NO-REF (because no output was approved yet). We first fixed our code so that no exceptions were thrown.&lt;/p&gt;&lt;h2&gt;Inspecting the Test Results&lt;/h2&gt;&lt;p&gt;Next, we have to visually inspect each output document and decide whether the output is correct or not. For this we compare the output with how a ‘trusted’ browser renders the HTML. Because this involves inspecting A LOT of output documents we wrote a tool that makes our life a bit easier. This tool evolved during the testing phase in order to maximize productivity. Here is how it looks:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_xFqIw0kj-i8/TczwdfuagtI/AAAAAAAAAKY/tAhqzA6RMzw/s1600-h/tool11.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Our tool for inspecting the output" border="0" alt="Our tool for inspecting the output" src="http://lh3.ggpht.com/_xFqIw0kj-i8/Tczwd6Rz4jI/AAAAAAAAAKc/PATQiyDF5G4/tool_thumb7.png?imgmax=800" width="604" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Without explaining every detail of this tool, let me go over the most-used features. What you see in the above picture is how our converter renders attribute-003.xht (in Chapter 5 of the W3C test suite) to PDF. This test is self-explaining. Obviously, each line has the color that it should have.&lt;/p&gt;&lt;p&gt;The button F9 lanuches a browser (we can select from all major browsers) so we can compare our output with that of a major browser such as Chrome. F11 (Next) jumps to the next test. F12 (Make Reference) copies the output to the reference folder, basically approving the output. &lt;/p&gt;&lt;h2&gt;Reporting&lt;/h2&gt;&lt;p&gt;Per chapter we generate a test report that gives a quick overview of the results as follows:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_xFqIw0kj-i8/TczwfULwCmI/AAAAAAAAAKg/AYIBPz9lqDg/s1600-h/chapter%5B6%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Test results for a single chapter" border="0" alt="Test results for a single chapter" src="http://lh5.ggpht.com/_xFqIw0kj-i8/TczwgJKwMhI/AAAAAAAAAKk/RSPjnQCCDgk/chapter_thumb%5B2%5D.png?imgmax=800" width="604" height="484" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;For the complete test set we generate a test report like this one:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_xFqIw0kj-i8/TczwhHajrRI/AAAAAAAAAKo/3ppbKL4leoE/s1600-h/summary%5B3%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Test results for all chapters" border="0" alt="Test results for all chapters" src="http://lh3.ggpht.com/_xFqIw0kj-i8/TczwhlZwIwI/AAAAAAAAAKs/2C1WgdCytrc/summary_thumb%5B1%5D.png?imgmax=800" width="604" height="444" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;As always, comments are welcome!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/tFnToE1CHmY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/tFnToE1CHmY/testing-our-html-to-pdf-converter.html</link><author>noreply@blogger.com (TallComponents)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_xFqIw0kj-i8/Tczwb4Hx6HI/AAAAAAAAAKU/0MM5wtpIFqw/s72-c/run_thumb5.png?imgmax=800" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/05/testing-our-html-to-pdf-converter.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-807055817343774432.post-6878615723725085621</guid><pubDate>Tue, 24 May 2011 10:26:00 +0000</pubDate><atom:updated>2011-05-24T12:48:43.244+02:00</atom:updated><title>If you can build an XBox, you can build a Blender!</title><description>&lt;p&gt;Our &lt;a href="http://www.tallcomponents.com/pdfrasterizer3.aspx" target="_blank"&gt;PDF rasterizer engine&lt;/a&gt; uses GDI+ for rendering. In this way rendering to a printer is no different than rendering to the screen, and we do not have to bother with low level concepts like resolutions. In any case, we really do not like the idea of sending bitmaps to our high resolution color printer. It is 2011 you know.&lt;/p&gt;  &lt;p&gt;Along the way however, we discovered that GDI+ does not quite cut it. It has all sorts of quirks and limitations, and it lacks some features that PDF has. So, we spent some of our time inventing GDI+ workarounds.&lt;/p&gt;  &lt;p&gt;One area that has been particularly painful is the complete lack of blend modes in GDI+. Up to a point we have been able to approximate the blend modes using normal transparency. This works surprisingly well for many files. There are however some effects that no form of ordinary transparency will &lt;em&gt;ever&lt;/em&gt; be able to approximate.&lt;/p&gt;  &lt;p&gt;In GDI+, the only real solution for this appears to be to render both the foreground and the background as a bitmap and do the blending ourselves, pixel for pixel. So why have we not done this already? The problem is not so much the blending operations. These are trivial. The problem is: keeping (printing) quality without generating huge bitmaps that slow down printing to a crawl. So here we are: we have PCL6 and PostScript 3, and the only way to get these pages on our high resolution color printer is basically by avoiding these high level printer languages entirely…. Pfff.&lt;/p&gt;  &lt;p&gt;So, we started telling ourselves: GDI+ is old. Microsoft is bound to come up with an improved, modern successor. We decided to wait a bit, hoping to avoid complaints. And then WPF arrived at the end of 2006. Hurray!&lt;/p&gt;  &lt;p&gt;Wait… no Blend modes yet, despite a product called Expression Blend. We waited a bit more.&lt;/p&gt;  &lt;p&gt;I have been told that blend modes are difficult to implement in WPF because of the retained graphical system that WPF employs. I find that hard to believe. If that were true WPF would basically be broken. And supporting blend modes is no more difficult than supporting transparency. The pixels just need to be combined with their backdrop in a slightly different manner. WPF has plenty support for ordinary transparency. As I see it, this would be a tiny technical step for Microsoft.&lt;/p&gt;  &lt;p&gt;In the meantime, Microsoft has started telling us not to rely on GDI+ anymore for ASP.NET services and it is ‘gently’ pushing us towards WPF. See &lt;a href="http://msdn.microsoft.com/en-us/library/system.drawing.aspx" target="_blank"&gt;http://msdn.microsoft.com/en-us/library/system.drawing.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;It is now halfway 2011 and WPF still has no Blend Mode support. How is this system (and XPS) ever going to be a serious competitor of PDF in terms of high-end graphical rendering? I understand that 3D rendering is also important, but seriously Microsoft: the last time I looked at your gaming platform – albeit increasingly popular – it was not more profitable than your office division.&lt;/p&gt;  &lt;p&gt;So come on Microsoft, if you can make an XBox, you can also build a Blender!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/thepdf/~4/5cBTWSq3gM0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/thepdf/~3/5cBTWSq3gM0/if-you-can-build-xbox-you-can-build.html</link><author>noreply@blogger.com (TallComponents)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.tallcomponents.com/2011/05/if-you-can-build-xbox-you-can-build.html</feedburner:origLink></item></channel></rss>
