FileFormatException when serializing a FixedDocument
Asked Answered
I

1

19

When serializing a FixedDocument to XPS I sometimes get a FileFormatException telling me that the format of a font (I assume) does not conform to the expected file format specification (see exception further down).

The mysterious part is:

  • The Exception will only happen once in a while
  • It will only happen for certain FontFamily/Style/Weight combinations (Segoe UI in italic and bold seems to trigger it)

Does somebody know why this happens (and especially why it does not happen consistently but only in unpredictable intervals)?

Following minimal reproducable example will trigger the exception about 4 to 5 times per run (on my Windows 10 machine, happens with .NET 4, 4.6.1 etc.):

private void TestXpsSerialization(object a)
{
    for (int i = 0; i < 400; ++i)
    {
        TextBlock block = new TextBlock
        {
            Text = "Test",
            FontFamily = new FontFamily("Segoe UI"),
            FontStyle = FontStyles.Italic,
            FontWeight = FontWeights.Bold,
            Background = null,
            FontSize = 12
        };
        FixedDocument fixedDoc = new FixedDocument();

        PageContent pageContent = new PageContent();
        FixedPage fixedPage = new FixedPage();
        fixedPage.Children.Add(block);
        ((IAddChild) pageContent).AddChild(fixedPage);
        fixedDoc.Pages.Add(pageContent);
        using (MemoryStream documentStream = new MemoryStream())
        {
            string inMemoryPackageName = string.Format("memorystream://{0}.xps", Guid.NewGuid());
            Uri packageUri = new Uri(inMemoryPackageName);
            using (Package package = Package.Open(documentStream, FileMode.CreateNew))
            {
                MemoryStream resultStream = new MemoryStream();
                PackageStore.AddPackage(packageUri, package);
                using (XpsDocument xpsd =
                new XpsDocument(package, CompressionOption.Maximum, inMemoryPackageName))
                {
                    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsd);
                    writer.Write(fixedDoc);
                    package.Flush();

                    using (MemoryStream outputStream = new MemoryStream())
                    {
                        SerializerWriter serializerWriter =
                        new XpsSerializerFactory().CreateSerializerWriter(outputStream);

                        bool success = true;
                        try
                        {
                            serializerWriter.Write(xpsd.GetFixedDocumentSequence());
                        }
                        catch (Exception e)
                        {
                            success = false;
                            Debug.WriteLine(e);
                        }
                        if (success)
                        {
                            outputStream.Seek(0, SeekOrigin.Begin);
                            outputStream.CopyTo(resultStream);
                        }
                    }
                }
                PackageStore.RemovePackage(packageUri);
                Debug.WriteLine(resultStream.Length);
            }
        }
    }
}

Following exception is raised (please excuse the German):

Ausnahme ausgelöst: "System.IO.FileFormatException" in PresentationCore.dll
System.IO.FileFormatException: Die Datei "pack://memorystream:,,62db450e-87fe-4246-a727-15ab02c5c55e.xps,/Resources/34890974-3e2d-4baf-9003-24c3375636b0.ODTTF" entspricht nicht der erwarteten Dateiformatspezifikation.
   bei MS.Internal.TrueTypeSubsetter.ComputeSubset(Void* fontData, Int32 fileSize, Uri sourceUri, Int32 directoryOffset, UInt16[] glyphArray)
   bei MS.Internal.FontFace.TrueTypeFontDriver.ComputeFontSubset(ICollection`1 glyphs)
   bei System.Windows.Media.GlyphTypeface.ComputeSubset(ICollection`1 glyphs)
   bei System.Windows.Xps.Serialization.FEMCacheItem.SubSetFont(ICollection`1 glyphs, Stream stream)
   bei System.Windows.Xps.Serialization.FEMCacheItem.Commit()
   bei System.Windows.Xps.Serialization.XpsFontSubsetter.CommitFontSubsetsSignal(FontSubsetterCommitPolicies signal)
   bei System.Windows.Xps.Serialization.XpsFontSerializationService.SignalCommit(Type type)
   bei System.Windows.Xps.Serialization.XpsSerializationManager.ReleaseXmlWriter(Type writerType)
   bei System.Windows.Xps.Serialization.DocumentSequenceSerializer.set_XmlWriter(XmlWriter value)
   bei System.Windows.Xps.Serialization.DocumentSequenceSerializer.PersistObjectData(SerializableObjectContext serializableObjectContext)
   bei System.Windows.Xps.Serialization.ReachSerializer.SerializeObject(Object serializedObject)
   bei System.Windows.Xps.Serialization.XpsSerializationManager.SaveAsXaml(Object serializedObject)
   bei System.Windows.Xps.XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
   bei System.Windows.Xps.XpsDocumentWriter.Write(FixedDocumentSequence fixedDocumentSequence)
   bei System.Windows.Xps.Serialization.XpsSerializerWriter.Write(FixedDocumentSequence fixedDocumentSequence)

The first line can be translated to:

"System.IO.FileFormatException" in PresentationCore.dll
System.IO.FileFormatException: "pack://memorystream:,,62db450e-87fe-4246-a727-15ab02c5c55e.xps,/Resources/34890974-3e2d-4baf-9003-24c3375636b0.ODTTF" file does not conform to the expected file format specification.
Inhalant answered 29/8, 2017 at 7:48 Comment(10)
Have you set the culture setting in your xaml to German? i.e. xml:lang="de-DE".Ioab
@Ioab thanks for the suggestion, I'm not quite sure how this would help but nevertheless tried it without any success.Inhalant
I can reproduce. And if I remove FontStyle = FontStyles.Italic, then it works... looks like a bug to me (you're not the only one: questarter.com/q/…), you should report to Microsoft Connect connect.microsoft.comThessalonian
@SimonMourier yes, it really does seem like a bug... I'll wait a while before reporting, just in case anybody sees what exactly is wrong (or has a good workaround, currently I guess I will just repeat the process until it works which is obviously not a very nice fix).Inhalant
@Inhalant similar to this contact with ms support and ask them, they are fastRombert
XPS internally is a zip archive of fixed documents carrying all the stuff with it for document presentation. It is internally trying to pack your fonts as a memory stream into xps zip archive. You are not able to pack your font into XPS archive. The font may be obfuscated. Check the below URL and the code download at the end of the link, looks like very old link. May be, the solution mentioned can solve your issue. blogs.microsoft.co.il/tamir/2008/04/17/…Changeless
@Amit Thanks a lot, that really does seem to be a possible solution for this problem. I currently can't check if it will work, but I must say: it is a really rather complicated fix... especially as it wants me to store the fonts to disk (probably rather slow) and then use a Regex replace in an XML document (well that just feels ugly)...In any case, as the problem is not deterministic I still assume that the .NET framework is not handling this situation all to well. In any case, thanks a lot for the link and suggestions.Inhalant
this line in your example -> MemoryStream resultStream = new MemoryStream(); why is this not wrapped in a using statement like the rest of the MemoryStreams used?Murielmurielle
@Aaron.S well, you are right, MemoryStreams should also be disposed. However, currently Disposing them does not have an effect. In any case I can't see how it would be relevant for my problem...Inhalant
@SimonMourier Why did you link this article (questarter.com/q/…) . questarter is a illigal site which copied SE contents.Rafa
B
1

Source code in Question

Comments in the source code seem to indicate that this calls native code. The font driver needs access to the declared font. Not all fonts support all variations. You should confirm that the font family you've chosen is installed and supports italics.

If the api supports the option, you should try indicating a specific font (rather than a family) that you've already confirmed is installed and supports the variations you've chosen.

Good luck!

Birkenhead answered 28/11, 2017 at 17:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.