Draw Graphics in an XPS OM

This page describes how to draw graphics in an XPS OM.

To draw vector-based graphics in a page, instantiate an IXpsOMPath interface, populate it with the desired content, and add it to the page's or canvas' list of visual objects. An IXpsOMPath interface contains such properties of a vector-based shape as the outline, fill color, line style, and line color. The path's shape is specified by an IXpsOMGeometry interface, which contains a collection of IXpsOMGeometryFigure interfaces and, optionally, an IXpsOMMatrixTransform interface. You can use any interface that inherits from the IXpsOMBrush interface to fill the perimeter of the path and the interior of the shape that is described by the path.

Before using the following code examples in your program, read the disclaimer in Common XPS Document Programming Tasks.

Code Example

The following code example creates a simple path that describes a rectangle that is filled with a single color.

Create the stroke and the fill brushes

The first section of the code example creates the IXpsOMSolidColorBrush that will be used to fill the path object.

    HRESULT               hr = S_OK;

    XPS_COLOR             xpsColor;
    IXpsOMSolidColorBrush *xpsFillBrush = NULL;
    IXpsOMSolidColorBrush *xpsStrokeBrush = NULL;

    // Set the fill brush color to RED.
    xpsColor.colorType = XPS_COLOR_TYPE_SRGB;
    xpsColor.value.sRGB.alpha = 0xFF;
    xpsColor.value.sRGB.red = 0xFF;
    xpsColor.value.sRGB.green = 0x00;
    xpsColor.value.sRGB.blue = 0x00;

    // Use the object factory to create the brush.
    hr = xpsFactory->CreateSolidColorBrush( 
        &xpsColor,
        NULL,          // color profile resource
        &xpsFillBrush);
    // The color profile resource parameter is NULL because
    //  this color type does not use a color profile resource.

    // Set the stroke brush color to BLACK.
    xpsColor.colorType = XPS_COLOR_TYPE_SRGB;
    xpsColor.value.sRGB.alpha = 0xFF;
    xpsColor.value.sRGB.red = 0x00;
    xpsColor.value.sRGB.green = 0x00;
    xpsColor.value.sRGB.blue = 0x00;

    // Use the object factory to create the brush.
    hr = xpsFactory->CreateSolidColorBrush( 
            &xpsColor,
            NULL, // This color type does not use a color profile resource.
            &xpsStrokeBrush);

    // The brushes are released below after they have been used.

Define the shape

The second section of the code example creates the IXpsOMGeometry interface. It then creates the IXpsOMGeometryFigure interface that specifies the figure's shape, and adds the figure to the IXpsOMGeometry interface. The example creates a rectangle that is specified by rect. Segments must be defined for only three of the four sides of the rectangle. The perimeter of the shape, the rectangle in this case, starts from the start point and extends as defined by the segments of the geometry figure. Setting the IsClosed property to TRUE indicates that the rectangle is closed by adding one additional segment that connects the end of the last segment to the start point.

    // rect is initialized outside of the sample and 
    //  contains the coordinates of the rectangular geometry to create.
    XPS_RECT                            rect = {0,0,100,100};       

    HRESULT                             hr = S_OK;
    IXpsOMGeometryFigure                *rectFigure;
    IXpsOMGeometry                      *imageRectGeometry;
    IXpsOMGeometryFigureCollection      *geomFigureCollection;

    // Define the start point and create an empty figure.
    XPS_POINT                           startPoint = {rect.x, rect.y};
    hr = xpsFactory->CreateGeometryFigure( &startPoint, &rectFigure );
    // Define the segments of the geometry figure.
    //  First, define the type of each segment.
    XPS_SEGMENT_TYPE segmentTypes[3] = {
        XPS_SEGMENT_TYPE_LINE,  // each segment is a straight line
        XPS_SEGMENT_TYPE_LINE, 
        XPS_SEGMENT_TYPE_LINE
    };

    // Define the x and y coordinates of each corner of the figure
    //  the start point has already been defined so only the 
    //  remaining three corners need to be defined.
    FLOAT segmentData[6] = {
        rect.x,                (rect.y + rect.height),
        (rect.x + rect.width), (rect.y + rect.height), 
        (rect.x + rect.width), rect.y 
    };

    // Describe if the segments are stroked (that is if the segment lines
    //  should be drawn as a line).
    BOOL segmentStrokes[3] = {
        TRUE, TRUE, TRUE // Yes, draw each of the segment lines.
    };

    // Add the segment data to the figure.
    hr = rectFigure->SetSegments(
                        3, 
                        6, 
                        segmentTypes, 
                        segmentData, 
                        segmentStrokes);

    // Set the closed and filled properties of the figure.
    hr = rectFigure->SetIsClosed( TRUE );
    hr = rectFigure->SetIsFilled( TRUE );
 
    // Create the geometry object.
    hr = xpsFactory->CreateGeometry( &imageRectGeometry );
    
    // Get a pointer to the figure collection interface of the geometry...
    hr = imageRectGeometry->GetFigures( &geomFigureCollection );

    // ...and then add the figure created above to this geometry.
    hr = geomFigureCollection->Append( rectFigure );
    // If not needed for anything else, release the rectangle figure.
    rectFigure->Release();

    // when done adding figures, release the figure collection. 
    geomFigureCollection->Release();

    //  When done with the geometry object, release the object.
    // imageRectGeometry->Release();
    //  In this case, imageRectGeometry is used in the next sample
    //  so the geometry object is not released, yet.
    

Create the path and add it to the visual collection

The final section of this code example creates and configures the path object, then adds it to the page's list of visual objects.

    HRESULT                    hr = S_OK;
    // The page interface pointer is initialized outside of this sample.
    IXpsOMPath                *rectPath = NULL;
    IXpsOMVisualCollection    *pageVisuals = NULL;

    // Create the new path object.
    hr = xpsFactory->CreatePath( &rectPath );

    // Add the geometry to the path.
    //  imageRectGeometry is initialized outside of this example.
    hr = rectPath->SetGeometryLocal( imageRectGeometry );

    // Set the short description of the path to provide
    //  a textual description of the object for accessibility.
    hr = rectPath->SetAccessibilityShortDescription( L"Red Rectangle" );
    
    // Set the fill and stroke brushes to use the brushes 
    //  created in the first section.
    hr = rectPath->SetFillBrushLocal( xpsFillBrush );
    hr = rectPath->SetStrokeBrushLocal( xpsStrokeBrush);

    // Get the visual collection of this page and add this path to it.
    hr = xpsPage->GetVisuals( &pageVisuals );
    hr = pageVisuals->Append( rectPath );
    // If not needed for anything else, release the rectangle path.
    rectPath->Release();
    
    // When done with the visual collection, release it.
    pageVisuals->Release();

    // When finished with the brushes, release the interface pointers.
    if (NULL != xpsFillBrush) xpsFillBrush->Release();
    if (NULL != xpsStrokeBrush) xpsStrokeBrush->Release();

    // When done with the geometry interface, release it.
    imageRectGeometry->Release();

    // When done with the path interface, release it.
    rectPath->Release();

Best Practices

Add a textual description of the shape that is specified by the IXpsOMPath interface. For the benefit of visually impaired users, use the SetAccessibilityShortDescription and SetAccessibilityLongDescription methods to provide textual content for accessibility support features, such as screen readers.

Additional Information

The code example on this page uses an IXpsOMSolidColorBrush interface as the fill brush and stroke brush for the path. In addition to the IXpsOMSolidColorBrush interface, you can use an IXpsOMGradientBrush, IXpsOMImageBrush, or IXpsOMVisualBrush interface.

The stroke is the line that can be drawn around the perimeter of the figure. The XML Paper Specification supports many different stroke line styles. To specify the stroke line style, set the stroke properties with the following methods of the IXpsOMPath interface:

Next Steps

Navigate the XPS OM

Write Text to an XPS OM

Place Images in an XPS OM

Write an XPS OM to an XPS Document

Print an XPS OM

Used in This Page

IOpcPartUri

IXpsOMGeometry

IXpsOMGeometryFigure

IXpsOMGeometryFigureCollection

IXpsOMObjectFactory

IXpsOMPage

IXpsOMPath

IXpsOMSolidColorBrush

IXpsOMVisualCollection

For More Information

Initialize an XPS OM

XPS Document API Reference

XML Paper Specification