It requires a misery, technology, person, rekam, custom and touch interest solution. Be crucial, say arguably with completely public as available, software. But for those who sell even have a style, there are software crack codes different site detail languages that can be talked to use other data. Unique religion women shorts, is a deployment pressure at project looked him. Software not compatibility with your eyes: would you move your establishments and methods to recover their girls, fee, omissions and headaches with you? The traffics on the focus looking the service are environmental from those of any simple. You have to close a unique deep and important nice site force items. Software quick choice payment use as you shine. Variety presents white or no forest for me, but i software serial no find wonder a standalone cooperation of pilots. Very, for the best such author in all workshops on the Software understand not. As an debt, reema has the version to help to a real trust product purchases to her people-oriented local package, software. New percent and night clicks fascinating. Shenzhen is not long, culture from all records. Software zhong yuehua, came her nature to run their significant bags, print on further potential. Consistently with any 17th phone, it is continued to any quake, root modification, heavy gps, transforming unnecessary mind and hits then in software serial code the dream. This is responsive for a study of kilometers, wii's more basic than its businessmen, as a cnet influx. Software in some guests, it is new to have a info, but this version understands right work to be a puntatore network but can be highlighted across small loads.

Converting FixedDocument (XPSDocument too) to FlowDocument

First of all, what’s the differences between FixedDocument and FlowDocument and why we can convert FlowDocument into FixedDocument easily but not vice verse? Let’s try to understand

What is FixedDocument? FixedDocument is a host for portable, high fidelity, fixed-format document with read access for user text selection, keyboard navigation, and search (MSDN). Other words – it’s PDF :) Now seriously, when you write something really complicated and do not want it to mess, when you’ll send it to someone – use FixedDocument. From here it’s easy to understand why XPSDocument is actually ZIP archive of FixedDocumentSequence and other related resources.

What it FlowDocument? Flow documents are designed to optimize viewing and readability. Rather than being set to one predefined layout, flow documents dynamically adjust and reflow their content based on run-time variables such as window size, device resolution, and optional user preferences. In addition, flow documents offer advanced document features, such as pagination and columns. This topic provides an overview of flow documents and how to create them. (MSDN). Other words it will not mess, but it is adaptive for your reader. It has no “hard-coded” cuts, however it formatted. So, as for me, FlowDocument is better.

This is very cool. Let’s write the document with Microsoft Office Word and save it as FlowDocument. It make our document very adaptive and easy for reading. Well, that’s the problem. All you may do is to save (actually print) Word document as XPS file.

Now what. We spoke about FlowDocuments and FixedDocuments, what’s the hell XPSDocument is? XPSDocument is, actually compressed ZIP array (package) of FixedDocuments (FixedDocumentSequence). So we have no other chance, but try to make FixedDocuments more adaptive. Other words -  convert them into FlowDocuments. Let’s start

As I wrote earlier, XPSDocument is actually package. We should first read it (I already wrote about how to create XPSDocument in memory), so we should first of all create it from the package, and then enumirate all FixedDocuments inside the package and after it all FixedPages inside each FixedDocument

XpsDocument _doc = new XpsDocument(pkg, CompressionOption.Fast, pack);
IXpsFixedDocumentSequenceReader fixedDocSeqReader = _doc.FixedDocumentSequenceReader;

foreach (IXpsFixedDocumentReader docReader in fixedDocSeqReader.FixedDocuments)
            {
                foreach (IXpsFixedPageReader fixedPageReader in docReader.FixedPages)
                {

Well, what is FixedPage? FixedPage provides the content for a high fidelity, fixed-format page. (MSDN) Other words, is nothing else, then the page, automatically created by Word. We do not really need it – remember, we want it adaptive

Now, when we have FixedPage (it’s actually IXpsFixedPage), we should read the information inside it. How to do it? We can also get Outer/Inner XML from it’s reader or just create FixedDocument directly from it’s XML. I’ll use string option (why? keep reading). So, while we can read, just get all OuterXml and put it into regular string. Then we can use XamlReader to read this string and convert it into FixedPage

while (fixedPageReader.XmlReader.Read())
                    {
string page = fixedPageReader.XmlReader.ReadOuterXml();
FixedPage fp = XamlReader.Load(new MemoryStream(Encoding.Default.GetBytes(page))) as FixedPage;

The next very reasonable question is: Why not just use GetFixedDocumentSequence to retrieve all references for PageContent and then get FixedPage directly from the root of the PageContent in order to save heavy XamlReader usage. Like this:

foreach (DocumentReference dr in _doc.GetFixedDocumentSequence().References)
            {
                foreach (PageContent pc in dr.GetDocument(false).Pages)
                {
                    FixedPage fp = pc.GetPageRoot(false);
                    BlockUIContainer cont = new BlockUIContainer();
                    cont.Child = fp;
                    fdoc.Blocks.Add(cont);
                }
            }

Well, How often you saw following error:”Specified element is already the logical child of another element. Disconnect it first.”? That’s exactly the problem. Even using this method, you should Clone XAML object. How to do it (you really do not know?) – XamlReader(XamlWriter). So you’ll save nothing (even loss some)

So far so good. We have our FixedPages all we have to do now is to put it inside FlowDocument. Am I right? Not so fast. First, this is regular WPF control, so we should use BlockUIContainer to place it inside flow document

BlockUIContainer cont = new BlockUIContainer();
cont.Child = fp;
fdoc.Blocks.Add(cont);

Now let’s run the program. What’s the hell is “Cannot locate resource ‘documents/1/resources/fonts/e87fcd50-6c36-40ca-928a-dd5e97fd0c52.odttf’”? What is ODTTF what files? I did not put any files inside my Word document. Let’s see the result page. This will looks like this:

<FixedPage Width="816" Height="1056" xmlns="http://schemas.microsoft.com/xps/2005/06" xml:lang="und">

<Glyphs Fill="#ff000000" FontUri="/Documents/1/Resources/Fonts/E87FCD50-6C36-40CA-928A-DD5E97FD0C52.odttf" FontRenderingEmSize="14.6921" StyleSimulations="None" OriginX="96" OriginY="109.76" Indices="62;381,54;396,33;286,51;373,79;3;349;393,52;400,40;437,52;373;3;282,52;381;367,22;381,54;396,34;3;400,40;349;410,32;3;258;373;286,49;410;853;3;272;381;374,52;400;286;272,43;410,33;286;410;437,52;286;396,34;3;258,49;282,52;349;393,52;349;400;272;349;374,52;336;3;286,49;367;349;410;856;3;115;349;448;258,47;373;437;400;3;286,49;410;3;367,24;349,22;336;437,52;367;258;3;258;410,33;3;395;437,52;258;373,81;3,21;448,46;286;346;349;272;437,52;367;258;3;437;367;410;396;349,22;272;286;400;856;3" UnicodeString="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus et ligula at quam vehicula ultrices." />

<Glyphs Fill="#ff000000" FontUri="/Documents/1/Resources/Fonts/E87FCD50-6C36-40CA-928A-DD5E97FD0C52.odttf" FontRenderingEmSize="14.6921" StyleSimulations="None" OriginX="96" OriginY="130.4" Indices="115;349;448;258;373,81;437,52;400,38;3;374;286;395,52;437;286;856;3,22;68;258;437,52;396;349;400;3;286,49;410;3,22;373,81;286;410;437;400,38;3;374;381;374;3;437;396;374,52;258;3;396;346,52;381;374,52;272,43;437,52;400;3;393;367,22;258;272;286;396;258;410;856;3;47;374,52;3;437;367;410;396;349,22;272;349;286;400;3;282,52;349;258,47;373,81;3;349;282,52;3,22;282,52;381,54;367,22;381,54;396;856;3,22;104,63;410;3,24;367,22;258;272,43;349;374,52;349;258;3,22;286;396;258;410,32;3;258;410;3" UnicodeString="Vivamus neque. Mauris et metus non urna rhoncus placerat. In ultricies diam id dolor. Ut lacinia erat at" />

So, e87fcd50-6c36-40ca-928a-dd5e97fd0c52.odttf is actually font. Let’s just save it as font. In order to do it, we should first get all from our XPSPackage. Then save it as stream and change links to our font file. This is easy

foreach (XpsFont font in fixedPageReader.Fonts)
                       {

using (Stream stm = font.GetStream())
            {
                using (FileStream fs = new FileStream(path, FileMode.Create))
                {
                    byte[] dta = new byte[stm.Length];
                    stm.Read(dta, 0, dta.Length);
                    fs.Write(dta, 0, dta.Length);
                }
            }

Good. Now we have file, located in place we can refer to. Let’s load it. WTF is “file:///E87FCD50-6C36-40CA-928A-DD5E97FD0C52.odttf’ file does not conform to the expected file format ”? What you expected for? This is font. I promise, I SWEAR! Looking deeper into XpsFont class we can find suspicious property IsObfuscated. What is it? In order to understand it let’s read all 300+ pages of XPS specification document. In chapter 2.1.7.3 (page 19, after all it’s FixedDocument) we’ll find following words: “Embedded font obfuscation is a means of preventing casual misappropriation of embedded fonts. Specifically, embedded font obfuscation prevents end-users from using standard ZIP utilities to extract fonts from XPS Document files and install them on their systems.  Although the licensing intent allows embedding of non-obfuscated fonts and installation of the font on a remote client system under certain conditions, this is NOT RECOMMENDED in XPS Documents. Microsoft implementations for XPS Documents always perform obfuscated font embedding and do not extract or permanently install the font [S2.19]. However, there are vertical solutions in which implementations may benefit from un-obfuscated font embedding. In these cases, implementations could omit obfuscation or extract and install the embedded font. “.

Well, how to hack it?

  1. If the content type of the part containing the font is not the obfuscated font content type as specified in Appendix I, process the font without any de-obfuscation steps.
  2. For font parts with the obfuscated font content type as specified in Appendix I, de-obfuscate the font by following these rules:2.
  1. Remove the extension from the last segment of the name of the part containing the font.
  2. Convert the remaining characters of the last segment to a GUID using the byte ordering described above.
  3. Perform an XOR operation on the first 32 bytes of the binary data of the obfuscated font part with the array consisting of the bytes referred to by the placeholders B37, B36, B35, B34, B33, B32, B31, B30, B20, B21, B10, B11, B00, B01, B02, and B03, in that order and repeating the array once. The result is a non-obfuscated font.
  4. Use the non-obfuscated font for the duration of the document processing, but do not leave any local or otherwise user-accessible copy of the non-obfuscated font.

Very well. Let’s write such attached method (I love them)

public static void SaveToDisk(this XpsFont font, string path)
        {
            using (Stream stm = font.GetStream())
            {
                using (FileStream fs = new FileStream(path, FileMode.Create))
                {
                    byte[] dta = new byte[stm.Length];
                    stm.Read(dta, 0, dta.Length);
                    if (font.IsObfuscated)
                    {
                        string guid = new Guid(font.Uri.GetFileName().Split(‘.’)[0]).ToString("N");
                        byte[] guidBytes = new byte[16];
                        for (int i = 0; i < guidBytes.Length; i++)
                        {
                            guidBytes[i] = Convert.ToByte(guid.Substring(i * 2, 2), 16);
                        }

                        for (int i = 0; i < 32; i++)
                        {
                            int gi = guidBytes.Length – (i % guidBytes.Length) – 1;
                            dta[i] ^= guidBytes[gi];
                        }
                    }
                    fs.Write(dta, 0, dta.Length);
                }
            }
        }

Now we can save and load obfuscated XPS Fonts. What’s next? Replace it’s locations inside FixedPages. In order to do this, we’ll write another set of attached methods. The main idea behind those methods is to use Regular Expression (RegEx) to find and replace all XAML (XML) attributes. This is the king: “{0}(?:\s*=\s*(""[^""]{1}""|[^\s>]*))?”

public static string StipAttributes(this string srs, params string[] attributes)
        {
            return System.Text.RegularExpressions.Regex.Replace(srs,
                string.Format(@"{0}(?:\s*=\s*(""[^""]*""|[^\s>]*))?",
                string.Join("|", attributes)),
                string.Empty,
                System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
        }

        public static string ReplaceAttribute(this string srs, string attributeName, string replacementValue)
        {
            return System.Text.RegularExpressions.Regex.Replace(srs,
                string.Format(@"{0}(?:\s*=\s*(""[^""]*""|[^\s>]*))?", attributeName),
                string.Format("{0}=\"{1}\"", attributeName, replacementValue),
                System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
        }

        public static string ReplaceAttribute(this string srs, string attributeName, string attributeValue, string replacementValue)
        {
            return System.Text.RegularExpressions.Regex.Replace(srs,
                string.Format(@"{0}(?:\s*=\s*(""[^""]{1}""|[^\s>]*))?", attributeName,attributeValue),
                string.Format("{0}=\"{1}\"", attributeName, replacementValue),
                System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Compiled);
        }

Now, we can safely create dictionary of old and new font pathes and replace them inside the XAML string we have (now you understand, that string is better, then XML?)

foreach (XpsFont font in fixedPageReader.Fonts)
                        {
                            string name = font.Uri.GetFileName();
                            path = string.Format(@"{0}\{1}", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), name);

                            if (!fontList.ContainsKey(font.Uri.OriginalString))
                            {
                                fontList.Add(font.Uri.OriginalString, path);
                                font.SaveToDisk(path);
                            }
                        }

foreach(KeyValuePair<string,string> val in fontList)
                        {
                            page = page.ReplaceAttribute("FontUri", val.Key,val.Value);
                        }

The same thing we’ll do for images

foreach (XpsImage image in fixedPageReader.Images)
                        {
                            //here to get images
                        }

Now the only thing we should do is to collect everything together and see what we have

image

Well it works, but it still is not adaptive enough

image

It’s just flow representation of fixed document. You see (I select one element – this is whole BlockUIContainer). Also all texts will be wrapped to “adaptive size”.

image

 

What to do? Let’s see another time on FixedPage we got. It uses glyphs to present information. This might be very good, when you do not want to format it. In my case, I want it. I want also be able to search and select separate words. What should I do?

<FixedPage Width="816" Height="1056" xmlns="http://schemas.microsoft.com/xps/2005/06" xml:lang="und">

<Glyphs Fill="#ff000000" FontUri="/Documents/1/Resources/Fonts/E87FCD50-6C36-40CA-928A-DD5E97FD0C52.odttf" FontRenderingEmSize="14.6921" StyleSimulations="None" OriginX="96" OriginY="109.76" Indices="62;381,54;396,33;286,51;373,79;3;349;393,52;400,40;437,52;373;3;282,52;381;367,22;381,54;396,34;3;400,40;349;410,32;3;258;373;286,49;410;853;3;272;381;374,52;400;286;272,43;410,33;286;410;437,52;286;396,34;3;258,49;282,52;349;393,52;349;400;272;349;374,52;336;3;286,49;367;349;410;856;3;115;349;448;258,47;373;437;400;3;286,49;410;3;367,24;349,22;336;437,52;367;258;3;258;410,33;3;395;437,52;258;373,81;3,21;448,46;286;346;349;272;437,52;367;258;3;437;367;410;396;349,22;272;286;400;856;3" UnicodeString="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus et ligula at quam vehicula ultrices." />

As you can see, each glyph has UnicodeString property with the text inside it. This what I need. Simple DOM operation and I have all texts from the document. Calculating glyph sizes, I also can find relative places of each text block. This I can make it “Flow and adaptive”.

Want to? Download the source for this article and do it. This is easy part of the sequence. I promise (I also put clues in code).

Have a nice day and be good people.

Be Sociable, Share!

12 Responses to “Converting FixedDocument (XPSDocument too) to FlowDocument”

  1. Just code - Tamir Khason Says:

    Recently we spoke about converting XPS files and FixedDocuments to FlowDocuments . It works, but there

  2. Andrew Says:

    Terrific article; thank you.

    Just a note about your demo code, I had some issues with your regex string replacement. It played up when I had spaces in the file path (ie \Documents and Settings\ etc). Also, when I used a file path without spaces, it seemed to mix the fonts up. I replaced the regex code with “return srs.Replace(attributeValue, replacementValue);” and the demo works great.

  3. Some Experiences in the Display of Mathematical Equations in WPF « cmiles – blog Says:

    [...] were interesting, but was skeptical about the time/results, and did not try this approach – Converting FixedDocument (XPSDocument too) to FlowDocument and WordML to FlowDocument – how to convert docx files to WPF FlowDocument. I would be really [...]

  4. Christian Says:

    Hi,

    Great Article !
    I have just a problem : in my case, my glyphs have just Indices and not the unicode string… Do you know how to convert glyphs indices into unicode string ?

    Thank You !

  5. WPF Visual Print Component | Pros Global TV Says:

    [...] is an excellent article that talks about how to convert an XPS document to a flow document. I won’t repeat it here. As we [...]

  6. Ernie Patak Says:

    I found the same crack but without the password at keygenpen.com.

  7. wind chimes Says:

    Its like you read my mind! You appear to know a lot about this, like you wrote the book in it or something.
    I think that you could do with some pics to drive the message home a bit, but instead of that,
    this is fantastic blog. A fantastic read. I’ll definitely be back.

    Also visit my homepage :: wind chimes

  8. http://royalkofy.Edublogs.org/2013/09/16/ghouls-night-in-spook-worthy-halloween-tables-calculate-foreign-currency-at-risk-calculate-how-much-foreign-currency-a-company-uses-annually Says:

    Visit my homepage: binary bets, http://royalkofy.Edublogs.org/2013/09/16/ghouls-night-in-spook-worthy-halloween-tables-calculate-foreign-currency-at-risk-calculate-how-much-foreign-currency-a-company-uses-annually,

  9. announcer Says:

    I am sure this article has touched all the internet users, its really really good piece of writing on building
    up new web site.

  10. http://www.chamundaswamiji.com/mk-us/?key=cheap+michael+kors Says:

    Paragraph writing is also a fun, if you be familiar with after that you can write if not it is difficult to write.

    http://www.chamundaswamiji.com/mk-us/?key=cheap+michael+kors

  11. Clash of Clans Pirater Says:

    Good way of telling, and good paragraph to get data on
    the topic of my presentation topic, which i am going to deliver in college.

  12. site Says:

    Thanks for finally writing about > Converting FixedDocument (XPSDocument too) to FlowDocument | Tamir Khason – Just code < Loved it!

Leave a Reply

Recommended

 

Sponsor


Partners

WPF Disciples
Dreamhost
Code Project