I did a test in C# with XPS OM interfaces, by adding a gradient, a text and an image, like in MS MFCXPSSample
It seems to work fine, but it is complicated (and I reduced the interfaces declarations by replacing some by IntPtr)
// References:
// https://learn.microsoft.com/en-us/windows/win32/printdocs/create-a-blank-xps-om
// VCSamples\VC2010Samples\MFC\XPS\MFCXPSSample
Guid CLSID_XpsOMObjectFactory = new Guid("E974D26D-3D9B-4D47-88CC-3872F2DC3585");
Type XpsOMObjectFactoryType = Type.GetTypeFromCLSID(CLSID_XpsOMObjectFactory, true);
IXpsOMObjectFactory pXpsFactory = (IXpsOMObjectFactory)Activator.CreateInstance(XpsOMObjectFactoryType);
if (pXpsFactory != null)
{
IXpsOMPackage pXpsPackage = null;
HRESULT hr = pXpsFactory.CreatePackage(out pXpsPackage);
if (hr == HRESULT.S_OK)
{
IXpsOMDocumentSequence pXpsFDS = null;
IntPtr opcPartUri = IntPtr.Zero;
// Create the URI for the fixed document sequence part and then create the fixed document sequence
hr = pXpsFactory.CreatePartUri("/pfixedDocumentCollectionequence.fdseq", out opcPartUri);
hr = pXpsFactory.CreateDocumentSequence(opcPartUri, out pXpsFDS);
if (opcPartUri != IntPtr.Zero)
Marshal.Release(opcPartUri);
IXpsOMDocument pXpsFD = null;
// Create the URI for the document part and then create the document.
hr = pXpsFactory.CreatePartUri("/Documents/1/FixedDocument.fdoc", out opcPartUri);
hr = pXpsFactory.CreateDocument(opcPartUri, out pXpsFD);
if (opcPartUri != IntPtr.Zero)
Marshal.Release(opcPartUri);
// Create a blank page
// Size of the screen for the test
int nWidth = Screen.PrimaryScreen.Bounds.Width;
int nHeight = Screen.PrimaryScreen.Bounds.Height;
//XPS_SIZE pageSize = new XPS_SIZE { width = 800, height = 600 };
XPS_SIZE pageSize = new XPS_SIZE { width = nWidth, height = nHeight };
float nFactorWidth = 2;
float nFactorHeight = 2;
IXpsOMPage pXpsPage = null;
hr = pXpsFactory.CreatePartUri("/Documents/1/Pages/1.fpage", out opcPartUri);
hr = pXpsFactory.CreatePage(ref pageSize, "en-US", opcPartUri, out pXpsPage);
if (opcPartUri != IntPtr.Zero)
Marshal.Release(opcPartUri);
// Create a page reference for the page.
IXpsOMPageReference pXpsPageRef = null;
hr = pXpsFactory.CreatePageReference(pageSize, out pXpsPageRef);
// Add the fixed document sequence to the package.
hr = pXpsPackage.SetDocumentSequence(pXpsFDS);
// Get the document collection of the fixed document sequence and then add the document to the collection.
IXpsOMDocumentCollection pFixedDocumentCollection = null;
hr = pXpsFDS.GetDocuments(out pFixedDocumentCollection);
hr = pFixedDocumentCollection.Append(pXpsFD);
// Get the page reference collection from the document and add the page reference and blank page.
IXpsOMPageReferenceCollection pXpsPageRefCollection = null;
hr = pXpsFD.GetPageReferences(out pXpsPageRefCollection);
hr = pXpsPageRefCollection.Append(pXpsPageRef);
hr = pXpsPageRef.SetPage(pXpsPage);
// Gradient
{
XPS_COLOR xpsColorTopbar = new XPS_COLOR();
XPS_POINT startPoint = new XPS_POINT();
XPS_POINT endPoint = new XPS_POINT();
IXpsOMGradientStop pXpsGradientStop1;
IXpsOMGradientStop pXpsGradientStop2;
//SetXPSColorToARGB(ref xpsColorTopbar, ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(255, 0xE4, 0x3B, 0x2F)), 255);
SetXPSColorToARGB(ref xpsColorTopbar, ColorTranslator.ToWin32(System.Drawing.Color.Blue), 192);
hr = pXpsFactory.CreateGradientStop(ref xpsColorTopbar, IntPtr.Zero, 0.0f, out pXpsGradientStop1);
//SetXPSColorToARGB(ref xpsColorTopbar, ColorTranslator.ToWin32(System.Drawing.Color.FromArgb(255, 0xEF, 0x79, 0x2F)), 255);
SetXPSColorToARGB(ref xpsColorTopbar, ColorTranslator.ToWin32(System.Drawing.Color.Red), 192);
hr = pXpsFactory.CreateGradientStop(ref xpsColorTopbar, IntPtr.Zero, 1.0f, out pXpsGradientStop2);
startPoint.x = 375.75f;
startPoint.y = 18.0f;
endPoint.x = 375.75f;
endPoint.y = 134.6f;
IXpsOMLinearGradientBrush pTopbarBrush;
hr = pXpsFactory.CreateLinearGradientBrush(pXpsGradientStop1, pXpsGradientStop2, ref startPoint, ref endPoint, out pTopbarBrush);
startPoint.x = 20.5f;
startPoint.y = 18.0f;
XPS_SEGMENT_TYPE[] topbarSegmentTypes = new XPS_SEGMENT_TYPE[3]
{
XPS_SEGMENT_TYPE.XPS_SEGMENT_TYPE_LINE,
XPS_SEGMENT_TYPE.XPS_SEGMENT_TYPE_BEZIER,
XPS_SEGMENT_TYPE.XPS_SEGMENT_TYPE_LINE
};
float[] topbarSegmentData = new float[10]
{
20.5f, 134.6f,
322.76f, 102.91f, 476.79f, 105.27f, 594.0f, 116.63f,
594.0f, 18.0f
};
bool[] topbarSegmentStrokes = new bool[3]
{
false, false, false
};
IXpsOMGeometry pXpsGeometry = null;
IXpsOMGeometryFigure pXpsFigure = null;
IXpsOMGeometryFigureCollection pXpsFigureCollection = null;
hr = pXpsFactory.CreateGeometryFigure(ref startPoint, out pXpsFigure);
pXpsFigure.SetIsClosed(true);
pXpsFigure.SetIsFilled(true);
hr = pXpsFigure.SetSegments(3, 10, topbarSegmentTypes, topbarSegmentData, topbarSegmentStrokes);
hr = pXpsFactory.CreateGeometry(out pXpsGeometry);
hr = pXpsGeometry.GetFigures(out pXpsFigureCollection);
hr = pXpsFigureCollection.Append(pXpsFigure);
// Create the topbar
IXpsOMPath pPathTopbar;
hr = pXpsFactory.CreatePath(out pPathTopbar);
hr = pPathTopbar.SetFillBrushLocal(pTopbarBrush);
hr = pPathTopbar.SetGeometryLocal(pXpsGeometry);
IXpsOMVisualCollection pPageVisuals;
hr = pXpsPage.GetVisuals(out pPageVisuals);
hr = pPageVisuals.Append(pPathTopbar);
if (pXpsGeometry != null)
Marshal.ReleaseComObject(pXpsGeometry);
if (pXpsFigure != null)
Marshal.ReleaseComObject(pXpsFigure);
if (pXpsFigureCollection != null)
Marshal.ReleaseComObject(pXpsFigureCollection);
if (pPathTopbar != null)
Marshal.ReleaseComObject(pPathTopbar);
if (pPageVisuals != null)
Marshal.ReleaseComObject(pPageVisuals);
}
// Image
{
string sTempPath = System.IO.Path.GetTempPath();
sTempPath = String.Concat(sTempPath, "Little_Girl.jpg");
using (var wc = new System.Net.WebClient())
{
//wc.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv: 52.0) Gecko/20100101 Firefox/52.0 SeaMonkey/2.49.4");
//wc.DownloadFileAsync(new Uri("https://image.ibb.co/buLv2e/Little_Girl3.jpg"), sTempPath);
wc.DownloadFile(new Uri("https://image.ibb.co/buLv2e/Little_Girl3.jpg"), sTempPath);
}
string sImageFileName = sTempPath;
//string sImageFileName = "E:\\Flowers.jpg";
//string sImageFileName = "E:\\Rose.jpg";
//string sImageFileName = "E:\\Rose_small.png";
//string sImageFileName = "E:\\Schtroumpfette.jpg";
//string sImageFileName = "E:\\Little_Girl3.jpg";
Bitmap bitmap = new Bitmap(sImageFileName);
IStream imageStream = null;
IntPtr imagePartUri = IntPtr.Zero;
IntPtr pImageResource = IntPtr.Zero;
hr = pXpsFactory.CreateReadOnlyStreamOnFile(sImageFileName, out imageStream);
string sImagePartName = "/Resources/Images/1.jpg";
hr = pXpsFactory.CreatePartUri(sImagePartName, out imagePartUri);
hr = pXpsFactory.CreateImageResource(
imageStream,
XPS_IMAGE_TYPE.XPS_IMAGE_TYPE_JPEG,
// XPS_IMAGE_TYPE.XPS_IMAGE_TYPE_PNG,
imagePartUri,
out pImageResource);
if (imagePartUri != IntPtr.Zero)
Marshal.Release(imagePartUri);
if (imageStream != null)
Marshal.ReleaseComObject(imageStream);
float nX = 100, nY = 150;
IntPtr pImageBrushPtr = IntPtr.Zero;
XPS_RECT xpsViewbox = new XPS_RECT { x = 0.0f, y = 0.0f, width = bitmap.Width * nFactorWidth, height = bitmap.Height * nFactorHeight };
XPS_RECT xpsViewport = new XPS_RECT { x = nX, y = nY, width = bitmap.Width * nFactorWidth, height = bitmap.Height * nFactorHeight };
XPS_POINT startPoint = new XPS_POINT { x = nX, y = nY };
// Create the image brush
hr = pXpsFactory.CreateImageBrush(pImageResource, ref xpsViewbox, ref xpsViewport, out pImageBrushPtr);
XPS_SEGMENT_TYPE[] segmentTypes = new XPS_SEGMENT_TYPE[3]
{
XPS_SEGMENT_TYPE.XPS_SEGMENT_TYPE_LINE,
XPS_SEGMENT_TYPE.XPS_SEGMENT_TYPE_LINE,
XPS_SEGMENT_TYPE. XPS_SEGMENT_TYPE_LINE
};
float[] segmentData = new float[6]
{
nX + bitmap.Width * nFactorWidth, nY,
nX + bitmap.Width * nFactorWidth, nY + bitmap.Height * nFactorHeight,
nX, nY + bitmap.Height * nFactorHeight
};
bool[] segmentStrokes = new bool[3]
{
false, false, false
};
IXpsOMGeometry pXpsGeometry = null;
IXpsOMGeometryFigure pXpsFigure = null;
IXpsOMGeometryFigureCollection pXpsFigureCollection = null;
hr = pXpsFactory.CreateGeometryFigure(startPoint, out pXpsFigure);
pXpsFigure.SetIsClosed(true);
pXpsFigure.SetIsFilled(true);
pXpsFigure.SetSegments(3, 6, segmentTypes, segmentData, segmentStrokes);
hr = pXpsFactory.CreateGeometry(out pXpsGeometry);
hr = pXpsGeometry.GetFigures(out pXpsFigureCollection);
hr = pXpsFigureCollection.Append(pXpsFigure);
// Create and add the image
IXpsOMPath pImagePath;
hr = pXpsFactory.CreatePath(out pImagePath);
IXpsOMBrush pImageBrush = Marshal.GetObjectForIUnknown(pImageBrushPtr) as IXpsOMBrush;
hr = pImagePath.SetFillBrushLocal(pImageBrush);
hr = pImagePath.SetGeometryLocal(pXpsGeometry);
IXpsOMVisualCollection pPageVisuals;
hr = pXpsPage.GetVisuals(out pPageVisuals);
hr = pPageVisuals.Append(pImagePath);
if (pXpsGeometry != null)
Marshal.ReleaseComObject(pXpsGeometry);
if (pXpsFigure != null)
Marshal.ReleaseComObject(pXpsFigure);
if (pXpsFigureCollection != null)
Marshal.ReleaseComObject(pXpsFigureCollection);
if (pImageResource != IntPtr.Zero)
Marshal.Release(pImageResource);
if (pImageBrush != null)
Marshal.ReleaseComObject(pImageBrush);
if (pPageVisuals != null)
Marshal.ReleaseComObject(pPageVisuals);
}
// Text
{
string sText = "This is a XPS text";
Guid FOLDERID_Fonts = new Guid("FD228CB7-AE11-4AE3-864C-16F3910AB8FE");
IntPtr pString = IntPtr.Zero;
hr = SHGetKnownFolderPath(FOLDERID_Fonts, 0, IntPtr.Zero, out pString);
string sFontFileName = Marshal.PtrToStringUni(pString);
//sFontFileName = String.Concat(sFontFileName, "\\Arial.ttf");
sFontFileName = String.Concat(sFontFileName, "\\Times.ttf");
// Create font stream.
IStream fontStream = null;
hr = pXpsFactory.CreateReadOnlyStreamOnFile(sFontFileName, out fontStream);
// Create new obfuscated part name for this resource using a GUID.
Guid fontNameGuid;
hr = CoCreateGuid(out fontNameGuid);
StringBuilder sbGuidString = new StringBuilder(50);
StringFromGUID2(ref fontNameGuid, sbGuidString, sbGuidString.Capacity);
// Create a URI string for this font resource that will place the font part in the /Resources/Fonts folder of the package.
string sUriString = "/Resources/Fonts/";
// Create the part name using the GUID string as the name and ".odttf" as the extension GUID string start and ends with
// curly braces so they are removed.
// uriString = "/Resources/Fonts/676FC6CF-A245-4BCC-B2DA-0B75C5317651.odttf"
sbGuidString.Remove(0, 1);
sbGuidString.Remove(sbGuidString.Length - 1, 1);
sUriString = String.Concat(sUriString, sbGuidString.ToString(), ".odttf");
// Create the font URI interface.
IntPtr fontUri = IntPtr.Zero;
IntPtr fontResource = IntPtr.Zero;
hr = pXpsFactory.CreatePartUri(sUriString, out fontUri);
// Create the font resource.
hr = pXpsFactory.CreateFontResource(fontStream, XPS_FONT_EMBEDDING.XPS_FONT_EMBEDDING_OBFUSCATED, fontUri, false, out fontResource);
if (fontUri != IntPtr.Zero)
Marshal.Release(fontUri);
if (fontStream != null)
Marshal.ReleaseComObject(fontStream);
XPS_COLOR xpsColorText = new XPS_COLOR();
SetXPSColorToARGB(ref xpsColorText, ColorTranslator.ToWin32(System.Drawing.Color.Yellow), 255);
AppendSimpleText(pXpsFactory, fontResource, 35.00f, xpsColorText, 170.0f, 75.0f, sText, pXpsPage);
if (fontResource != IntPtr.Zero)
Marshal.Release(fontResource);
}
// Create the XPS file
string sFileName = "E:\\test_create_xps.xps";
try
{
hr = pXpsPackage.WriteToFile(sFileName, IntPtr.Zero, FILE_ATTRIBUTE_NORMAL, false);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Could not write file : " + sFileName + "\r\n" + ex.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (pXpsFDS != null)
Marshal.ReleaseComObject(pXpsFDS);
if (pXpsFD != null)
Marshal.ReleaseComObject(pXpsFD);
if (pXpsPage != null)
Marshal.ReleaseComObject(pXpsPage);
if (pXpsPageRef != null)
Marshal.ReleaseComObject(pXpsPageRef);
if (pFixedDocumentCollection != null)
Marshal.ReleaseComObject(pFixedDocumentCollection);
if (pXpsPageRefCollection != null)
Marshal.ReleaseComObject(pXpsPageRefCollection);
Marshal.ReleaseComObject(pXpsPackage);
}
Marshal.ReleaseComObject(pXpsFactory);
}
Declarations : XPS OM