Name

    NV_path_rendering

Name Strings

    GL_NV_path_rendering

Contact

    Mark Kilgard, NVIDIA (mjk 'at' nvidia.com)

Contributors

    Roger Allen, NVIDIA
    Jeff Bolz, NVIDIA
    Chris Dalton, NVIDIA
    Pierre-Loup Griffais, NVIDIA
    Chris Hebert, Samsung
    Scott Nations, NVIDIA
    David Chait, NVIDIA
    Daniel Koch, NVIDIA
    Bas Schouten, Mozilla
    Sandeep Shinde, NVIDIA

Status

    Released in NVIDIA Driver Release 275.33 (June 2011).

    Substantially optimized in NVIDIA Driver Release 301.42 (May 2012).

    Further optimized in NVIDIA Driver Release 314.xx (February 2013).

    Version 1.3 functionality shipping in NVIDIA Driver Release 337.88
    and on (May, 27 2014).

Version

    Last Modified Date:  September 9, 2014
    Version:             35

Number

    OpenGL Extension #410
    OpenGL ES Extension #199

Dependencies

    This extension is written against the OpenGL 3.2 Specification with
    Compatibility Profile but can apply to OpenGL 1.1 and up.

    When used with a Core profile or OpenGL ES context, certain
    functionality is unavailable (see "Dependencies on Core Profile and
    OpenGL ES" section).

    This extension depends on ARB_program_interface_query.

    EXT_direct_state_access commands are used in specifying portions
    of this extension but EXT_direct_state_access is not required to
    implement this extension as long as the functionality implemented
    is equivalent to the EXT_direct_state_access commands.

    EXT_separate_shader_objects is recommended.

    ARB_program_interface_query is recommended.

Overview

    Conventional OpenGL supports rendering images (pixel rectangles and
    bitmaps) and simple geometric primitives (points, lines, polygons).

    This extension adds a new rendering paradigm, known as path rendering,
    for rendering filled and stroked paths.  Path rendering is not novel
    but rather a standard part of most resolution-independent 2D rendering
    systems such as Flash, PDF, Silverlight, SVG, Java 2D, Office
    drawings, TrueType fonts, PostScript and its fonts, Quartz 2D, XML
    Paper Specification (XPS), and OpenVG.  What is novel is the ability
    to mix path rendering with arbitrary OpenGL 3D rendering and imaging.

    With this extension, path rendering becomes a first-class rendering
    mode within the OpenGL graphics system that can be arbitrarily mixed
    with existing OpenGL rendering and can take advantage of OpenGL's
    existing mechanisms for texturing, programmability, and per-fragment
    operations.

    Unlike geometric primitive rendering, paths are specified on a 2D
    (non-projective) plane rather than in 3D (projective) space.
    Even though the path is defined in a 2D plane, every path can
    be transformed into 3D clip space allowing for 3D view frustum &
    user-defined clipping, depth offset, and depth testing in the same
    manner as geometric primitive rendering.

    Both geometric primitive rendering and path rendering support
    rasterization of edges defined by line segments; however, path
    rendering also allows path segments to be specified by Bezier (cubic
    or quadratic) curves or partial elliptical arcs.  This allows path
    rendering to define truly curved primitive boundaries unlike the
    straight edges of line and polygon primitives.  Whereas geometric
    primitive rendering requires convex polygons for well-defined
    rendering results, path rendering allows (and encourages!) concave
    and curved outlines to be specified.  These paths are even allowed
    to self-intersect.

    When filling closed paths, the winding of paths (counterclockwise
    or clockwise) determines whether pixels are inside or outside of
    the path.

    Paths can also be stroked whereby, conceptually, a fixed-width "brush"
    is pulled along the path such that the brush remains orthogonal to
    the gradient of each path segment.  Samples within the sweep of this
    brush are considered inside the stroke of the path.

    This extension supports path rendering through a sequence of three
    operations:

        1.  Path specification is the process of creating and updating
            a path object consisting of a set of path commands and a
            corresponding set of 2D vertices.

            Path commands can be specified explicitly from path command
            and coordinate data, parsed from a string based on standard
            grammars for representing paths, or specified by a particular
            glyph of standard font representations.  Also new paths can
            be specified by weighting one or more existing paths so long
            as all the weighted paths have consistent command sequences.

            Each path object contains zero or more subpaths specified
            by a sequence of line segments, partial elliptical arcs,
            and (cubic or quadratic) Bezier curve segments.  Each path
            may contain multiple subpaths that can be closed (forming
            a contour) or open.

        2.  Path stenciling is the process of updating the stencil buffer
            based on a path's coverage transformed into window space.

            Path stenciling can determine either the filled or stroked
            coverage of a path.

            The details of path stenciling are explained within the core
            of the specification.

            Stenciling a stroked path supports all the standard
            embellishments for path stroking such as end caps, join
            styles, miter limits, dashing, and dash caps.  These stroking
            properties specified are parameters of path objects.

        3.  Path covering is the process of emitting simple (convex &
            planar) geometry that (conservatively) "covers" the path's
            sample coverage in the stencil buffer.  During path covering,
            stencil testing can be configured to discard fragments not
            within the actual coverage of the path as determined by
            prior path stenciling.

            Path covering can cover either the filled or stroked coverage
            of a path.

            The details of path covering are explained within the core
            of the specification.

    To render a path object into the color buffer, an application specifies
    a path object and then uses a two-step rendering process.  First, the
    path object is stenciled whereby the path object's stroked or filled
    coverage is rasterized into the stencil buffer.  Second, the path object
    is covered whereby conservative bounding geometry for the path is
    transformed and rasterized with stencil testing configured to test against
    the coverage information written to the stencil buffer in the first step
    so that only fragments covered by the path are written during this second
    step.  Also during this second step written pixels typically have
    their stencil value reset (so there's no need for clearing the
    stencil buffer between rendering each path).

    Here is an example of specifying and then rendering a five-point
    star and a heart as a path using Scalable Vector Graphics (SVG)
    path description syntax:

        GLuint pathObj = 42;
        const char *svgPathString =
          // star
          "M100,180 L40,10 L190,120 L10,120 L160,10 z"
          // heart
          "M300 300 C 100 400,100 200,300 100,500 200,500 400,300 300Z";
        glPathStringNV(pathObj, GL_PATH_FORMAT_SVG_NV,
                       (GLsizei)strlen(svgPathString), svgPathString);

    Alternatively applications oriented around the PostScript imaging
    model can use the PostScript user path syntax instead:

        const char *psPathString =
          // star
          "100 180 moveto"
          " 40 10 lineto 190 120 lineto 10 120 lineto 160 10 lineto closepath"
          // heart
          " 300 300 moveto"
          " 100 400 100 200 300 100 curveto"
          " 500 200 500 400 300 300 curveto closepath";
        glPathStringNV(pathObj, GL_PATH_FORMAT_PS_NV,
                       (GLsizei)strlen(psPathString), psPathString);

    The PostScript path syntax also supports compact and precise binary
    encoding and includes PostScript-style circular arcs.

    Or the path's command and coordinates can be specified explicitly:

        static const GLubyte pathCommands[10] =
          { GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV,
            GL_LINE_TO_NV, GL_CLOSE_PATH_NV,
            'M', 'C', 'C', 'Z' };  // character aliases
        static const GLshort pathCoords[12][2] =
          { {100, 180}, {40, 10}, {190, 120}, {10, 120}, {160, 10},
            {300,300}, {100,400}, {100,200}, {300,100},
            {500,200}, {500,400}, {300,300} };
        glPathCommandsNV(pathObj, 10, pathCommands, 24, GL_SHORT, pathCoords);

    Before rendering to a window with a stencil buffer, clear the stencil
    buffer to zero and the color buffer to black:

        glClearStencil(0);
        glClearColor(0,0,0,0);
        glStencilMask(~0);
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    Use an orthographic path-to-clip-space transform to map the
    [0..500]x[0..400] range of the star's path coordinates to the [-1..1]
    clip space cube:

        glMatrixLoadIdentityEXT(GL_PROJECTION);
        glMatrixLoadIdentityEXT(GL_MODELVIEW);
        glMatrixOrthoEXT(GL_MODELVIEW, 0, 500, 0, 400, -1, 1);

    Stencil the path:

        glStencilFillPathNV(pathObj, GL_COUNT_UP_NV, 0x1F);

    The 0x1F mask means the counting uses modulo-32 arithmetic. In
    principle the star's path is simple enough (having a maximum winding
    number of 2) that modulo-4 arithmetic would be sufficient so the mask
    could be 0x3.  Or a mask of all 1's (~0) could be used to count with
    all available stencil bits.

    Now that the coverage of the star and the heart have been rasterized
    into the stencil buffer, cover the path with a non-zero fill style
    (indicated by the GL_NOTEQUAL stencil function with a zero reference
    value):

        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_NOTEQUAL, 0, 0x1F);
        glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
        glColor3f(1,1,0); // yellow
        glCoverFillPathNV(pathObj, GL_BOUNDING_BOX_NV);

    The result is a yellow star (with a filled center) to the left of
    a yellow heart.

    The GL_ZERO stencil operation ensures that any covered samples
    (meaning those with non-zero stencil values) are zero'ed when
    the path cover is rasterized. This allows subsequent paths to be
    rendered without clearing the stencil buffer again.

    A similar two-step rendering process can draw a white outline
    over the star and heart.

    Before rendering, configure the path object with desirable path
    parameters for stroking.  Specify a wider 6.5-unit stroke and
    the round join style:

        glPathParameteriNV(pathObj, GL_PATH_JOIN_STYLE_NV, GL_ROUND_NV);
        glPathParameterfNV(pathObj, GL_PATH_STROKE_WIDTH_NV, 6.5);

     Now stencil the path's stroked coverage into the stencil buffer,
     setting the stencil to 0x1 for all stencil samples within the
     transformed path.

        glStencilStrokePathNV(pathObj, 0x1, ~0);

     Cover the path's stroked coverage (with a hull this time instead
     of a bounding box; the choice doesn't really matter here) while
     stencil testing that writes white to the color buffer and again
     zero the stencil buffer.

        glColor3f(1,1,1); // white
        glCoverStrokePathNV(pathObj, GL_CONVEX_HULL_NV);

     In this example, constant color shading is used but the application
     can specify their own arbitrary shading and/or blending operations,
     whether with Cg compiled to fragment program assembly, GLSL, or
     fixed-function fragment processing.

     More complex path rendering is possible such as clipping one path to
     another arbitrary path.  This is because stencil testing (as well
     as depth testing, depth bound test, clip planes, and scissoring)
     can restrict path stenciling.

     Now let's render the word "OpenGL" atop the star and heart.

     First create a sequence of path objects for the glyphs for the
     characters in "OpenGL":

        GLuint glyphBase = glGenPathsNV(6);
        const unsigned char *word = "OpenGL";
        const GLsizei wordLen = (GLsizei)strlen(word);
        const GLfloat emScale = 2048;  // match TrueType convention
        GLuint templatePathObject = ~0;  // Non-existent path object
        glPathGlyphsNV(glyphBase,
                       GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV,
                       wordLen, GL_UNSIGNED_BYTE, word,
                       GL_SKIP_MISSING_GLYPH_NV, ~0, emScale);
        glPathGlyphsNV(glyphBase,
                       GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV,
                       wordLen, GL_UNSIGNED_BYTE, word,
                       GL_SKIP_MISSING_GLYPH_NV, ~0, emScale);
        glPathGlyphsNV(glyphBase,
                       GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV,
                       wordLen, GL_UNSIGNED_BYTE, word,
                       GL_USE_MISSING_GLYPH_NV, ~0, emScale);

    Glyphs are loaded for three different fonts in priority order:
    Helvetica first, then Arial, and if neither of those loads, use the
    standard sans-serif font.  If a prior glPathGlyphsNV is successful
    and specifies the path object range, the subsequent glPathGlyphsNV
    commands silently avoid re-specifying the already existent path
    objects.

    Now query the (kerned) separations for the word "OpenGL" and build
    a set of horizontal translations advancing each successive glyph by
    its kerning distance with the following glyph.

        GLfloat xtranslate[6+1];  // wordLen+1
        glGetPathSpacingNV(GL_ACCUM_ADJACENT_PAIRS_NV,
                           wordLen+1, GL_UNSIGNED_BYTE,
                           "\000\001\002\003\004\005\005",  // repeat last letter twice
                           glyphBase,
                           1.0f, 1.0f,
                           GL_TRANSLATE_X_NV,
                           xtranslate);

    Next determine the font-wide vertical minimum and maximum for the
    font face by querying the per-font metrics of any one of the glyphs
    from the font face.

        GLfloat yMinMax[2];
        glGetPathMetricRangeNV(GL_FONT_Y_MIN_BOUNDS_BIT_NV|GL_FONT_Y_MAX_BOUNDS_BIT_NV,
                               glyphBase, /*count*/1,
                               2*sizeof(GLfloat),
                               yMinMax);

    Use an orthographic path-to-clip-space transform to map the
    word's bounds to the [-1..1] clip space cube:

        glMatrixLoadIdentityEXT(GL_PROJECTION);
        glMatrixOrthoEXT(GL_MODELVIEW,
                         0, xtranslate[6], yMinMax[0], yMinMax[1],
                         -1, 1);

    Stencil the filled paths of the sequence of glyphs for "OpenGL",
    each transformed by the appropriate 2D translations for spacing.

        glStencilFillPathInstancedNV(6, GL_UNSIGNED_BYTE,
                                     "\000\001\002\003\004\005",
                                     glyphBase,
                                     GL_PATH_FILL_MODE_NV, 0xFF,
                                     GL_TRANSLATE_X_NV, xtranslate);

     Cover the bounding box union of the glyphs with 50% gray.

        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
        glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
        glColor3f(0.5,0.5,0.5); // 50% gray
        glCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE,
                                   "\000\001\002\003\004\005",
                                   glyphBase,
                                   GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
                                   GL_TRANSLATE_X_NV, xtranslate);

    Voila, the word "OpenGL" in gray is now stenciled into the framebuffer.

    Instead of solid 50% gray, the cover operation can apply a linear
    gradient that changes from green (RGB=0,1,0) at the top of the word
    "OpenGL" to blue (RGB=0,0,1) at the bottom of "OpenGL":

        GLfloat rgbGen[3][3] = {
          0, 0, 0,  // red   = constant zero
          0, 1, 0,  // green = varies with y from bottom (0) to top (1)
          0, -1, 1  // blue  = varies with y from bottom (1) to top (0)
        };
        glPathColorGenNV(GL_PRIMARY_COLOR, GL_PATH_OBJECT_BOUNDING_BOX_NV,
                         GL_RGB, &rgbGen[0][0]);

    Instead of loading just the glyphs for the characters in "OpenGL",
    the entire character set could be loaded.  This allows the characters
    of the string to be mapped (offset by the glyphBase) to path object names.
    A range of glyphs can be loaded like this:

        const int numChars = 256;  // ISO/IEC 8859-1 8-bit character range
        GLuint glyphBase = glGenPathsNV(numChars);
        glPathGlyphRangeNV(glyphBase,
                           GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV,
                           0, numChars,
                           GL_SKIP_MISSING_GLYPH_NV, ~0, emScale);
        glPathGlyphRangeNV(glyphBase,
                           GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV,
                           0, numChars,
                           GL_SKIP_MISSING_GLYPH_NV, ~0, emScale);
        glPathGlyphRangeNV(glyphBase,
                           GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV,
                           0, numChars,
                           GL_USE_MISSING_GLYPH_NV, ~0, emScale);

    Given a range of glyphs loaded as path objects, (kerned) spacing
    information can now be queried for the string:

        glGetPathSpacingNV(GL_ACCUM_ADJACENT_PAIRS_NV,
                           7, GL_UNSIGNED_BYTE, "OpenGLL", // repeat L to get final spacing
                           glyphBase,
                           1.0f, 1.0f,
                           GL_TRANSLATE_X_NV,
                           kerning);

    Using the range of glyphs, stenciling and covering the instanced
    paths for "OpenGL" can be done this way:

        glStencilFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL",
                                     glyphBase,
                                     GL_PATH_FILL_MODE_NV, 0xFF,
                                     GL_TRANSLATE_X_NV, xtranslate);

        glCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL",
                                   glyphBase,
                                   GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV,
                                   GL_TRANSLATE_X_NV, xtranslate);

    The "stencil" and "cover" steps can be combined in a single command:

        glStencilThenCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL",
                                              glyphBase,
                                              GL_PATH_FILL_MODE_NV, 0xFF,
                                              GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV
                                              GL_TRANSLATE_X_NV, xtranslate);

    XXX add path clipping example to demonstrate glPathStencilFuncNV.

New Procedures and Functions

    PATH SPECIFICATION COMMANDS

        EXPLICIT PATH DATA

        void PathCommandsNV(uint path,
                            sizei numCommands, const ubyte *commands,
                            sizei numCoords, enum coordType,
                            const void *coords);
        void PathCoordsNV(uint path,
                          sizei numCoords, enum coordType,
                          const void *coords);

        void PathSubCommandsNV(uint path,
                               sizei commandStart, sizei commandsToDelete,
                               sizei numCommands, const ubyte *commands,
                               sizei numCoords, enum coordType,
                               const void *coords);
        void PathSubCoordsNV(uint path,
                             sizei coordStart,
                             sizei numCoords, enum coordType,
                             const void *coords);

        STRING PATH DESCRIPTION

        void PathStringNV(uint path, enum format,
                          sizei length, const void *pathString);

        PATHS FROM FONT GLYPHS BY UNICODE CHARACTER POINT

        void PathGlyphsNV(uint firstPathName,
                          enum fontTarget,
                          const void *fontName,
                          bitfield fontStyle,
                          sizei numGlyphs, enum type,
                          const void *charcodes,
                          enum handleMissingGlyphs,
                          uint pathParameterTemplate,
                          float emScale);
        void PathGlyphRangeNV(uint firstPathName,
                              enum fontTarget,
                              const void *fontName,
                              bitfield fontStyle,
                              uint firstGlyph,
                              sizei numGlyphs,
                              enum handleMissingGlyphs,
                              uint pathParameterTemplate,
                              float emScale);

        PATHS FROM FONT GLYPHS BY PER-FONT GLYPH INDEX

        enum PathGlyphIndexArrayNV(uint firstPathName,
                                   enum fontTarget,
                                   const void *fontName,
                                   bitfield fontStyle,
                                   uint firstGlyphIndex,
                                   sizei numGlyphs,
                                   uint pathParameterTemplate,
                                   float emScale);
        enum PathMemoryGlyphIndexArrayNV(uint firstPathName,
                                         enum fontTarget,
                                         sizeiptr fontSize,
                                         const void *fontData,
                                         sizei faceIndex,
                                         uint firstGlyphIndex,
                                         sizei numGlyphs,
                                         uint pathParameterTemplate,
                                         float emScale);
        enum PathGlyphIndexRangeNV(enum fontTarget,
                                   const void *fontName,
                                   bitfield fontStyle,
                                   uint pathParameterTemplate,
                                   float emScale,
                                   uint baseAndCount[2]);

        PATH SPECIFICATION WITH EXISTING PATHS

        void WeightPathsNV(uint resultPath,
                           sizei numPaths,
                           const uint paths[], const float weights[]);
        void CopyPathNV(uint resultPath, uint srcPath);
        void InterpolatePathsNV(uint resultPath,
                                uint pathA, uint pathB,
                                float weight);
        void TransformPathNV(uint resultPath,
                             uint srcPath,
                             enum transformType,
                             const float *transformValues);

    PATH PARAMETER SPECIFICATION COMMANDS

        void PathParameterivNV(uint path, enum pname, const int *value);
        void PathParameteriNV(uint path, enum pname, int value);
        void PathParameterfvNV(uint path, enum pname, const float *value);
        void PathParameterfNV(uint path, enum pname, float value);

        void PathDashArrayNV(uint path,
                             sizei dashCount, const float *dashArray);

    PATH NAME MANAGEMENT

        uint GenPathsNV(sizei range);
        void DeletePathsNV(uint path, sizei range);
        boolean IsPathNV(uint path);

    PATH STENCILING

        void PathStencilFuncNV(enum func, int ref, uint mask);
        void PathStencilDepthOffsetNV(float factor, float units);

        void StencilFillPathNV(uint path,
                               enum fillMode, uint mask);

        void StencilStrokePathNV(uint path,
                                 int reference, uint mask);

        void StencilFillPathInstancedNV(sizei numPaths,
                                        enum pathNameType, const void *paths,
                                        uint pathBase,
                                        enum fillMode, uint mask,
                                        enum transformType,
                                        const float *transformValues);

        void StencilStrokePathInstancedNV(sizei numPaths,
                                          enum pathNameType, const void *paths,
                                          uint pathBase,
                                          int reference, uint mask,
                                          enum transformType,
                                          const float *transformValues);

    PATH COVERING

        void PathCoverDepthFuncNV(enum zfunc);

        void PathColorGenNV(enum color,
                            enum genMode,
                            enum colorFormat, const float *coeffs);
        void PathTexGenNV(enum texCoordSet,
                          enum genMode,
                          int components, const float *coeffs);
        void PathFogGenNV(enum genMode);

        void CoverFillPathNV(uint path, enum coverMode);

        void CoverStrokePathNV(uint path, enum coverMode);

        void CoverFillPathInstancedNV(sizei numPaths,
                                      enum pathNameType, const void *paths,
                                      uint pathBase,
                                      enum coverMode,
                                      enum transformType,
                                      const float *transformValues);

        void CoverStrokePathInstancedNV(sizei numPaths,
                                        enum pathNameType, const void *paths,
                                        uint pathBase,
                                        enum coverMode,
                                        enum transformType,
                                        const float *transformValues);

    PATH STENCILING THEN COVERING

        void StencilThenCoverFillPathNV(uint path, enum fillMode,
                                        uint mask, enum coverMode);
        void StencilThenCoverStrokePathNV(uint path, int reference,
                                          uint mask, enum coverMode);
        void StencilThenCoverFillPathInstancedNV(sizei numPaths,
                                                 enum pathNameType,
                                                 const void *paths,
                                                 uint pathBase,
                                                 enum fillMode, uint mask,
                                                 enum coverMode,
                                                 enum transformType,
                                                 const float *transformValues);
        void StencilThenCoverStrokePathInstancedNV(sizei numPaths,
                                                   enum pathNameType,
                                                   const void *paths,
                                                   uint pathBase,
                                                   int reference, uint mask,
                                                   enum coverMode,
                                                   enum transformType,
                                                   const float *transformValues);

    PATH COVERING OF GLSL FRAGMENT INPUTS

        void ProgramPathFragmentInputGenNV(uint program,
                                           int location,
                                           enum genMode,
                                           int components,
                                           const float *coeffs);

    PATH QUERIES

        void GetPathParameterivNV(uint path, enum pname, int *value);
        void GetPathParameterfvNV(uint path, enum pname, float *value);

        void GetPathCommandsNV(uint path, ubyte *commands);
        void GetPathCoordsNV(uint path, float *coords);
        void GetPathDashArrayNV(uint path, float *dashArray);

        void GetPathMetricsNV(bitfield metricQueryMask,
                              sizei numPaths,
                              enum pathNameType, const void *paths,
                              uint pathBase,
                              sizei stride,
                              float *metrics);
        void GetPathMetricRangeNV(bitfield metricQueryMask,
                                  uint firstPathName,
                                  sizei numPaths,
                                  sizei stride,
                                  float *metrics);

        void GetPathSpacingNV(enum pathListMode,
                              sizei numPaths,
                              enum pathNameType, const void *paths,
                              uint pathBase,
                              float advanceScale,
                              float kerningScale,
                              enum transformType,
                              float *returnedSpacing);

        void GetPathColorGenivNV(enum color, enum pname, int *value);
        void GetPathColorGenfvNV(enum color, enum pname, float *value);
        void GetPathTexGenivNV(enum texCoordSet, enum pname, int *value);
        void GetPathTexGenfvNV(enum texCoordSet, enum pname, float *value);

        boolean IsPointInFillPathNV(uint path,
                                    uint mask, float x, float y);
        boolean IsPointInStrokePathNV(uint path,
                                      float x, float y);

        float GetPathLengthNV(uint path,
                              sizei startSegment, sizei numSegments);

        boolean PointAlongPathNV(uint path,
                                 sizei startSegment, sizei numSegments,
                                 float distance,
                                 float *x, float *y,
                                 float *tangentX, float *tangentY);

    MATRIX SPECIFICATION

        void MatrixLoad3x2fNV(enum matrixMode, const float *m);
        void MatrixLoad3x3fNV(enum matrixMode, const float *m);
        void MatrixLoadTranspose3x3fNV(enum matrixMode, const float *m);

        void MatrixMult3x2fNV(enum matrixMode, const float *m);
        void MatrixMult3x3fNV(enum matrixMode, const float *m);
        void MatrixMultTranspose3x3fNV(enum matrixMode, const float *m);

    FLOATING-POINT PROGRAM RESOURCE QUERY

        void GetProgramResourcefvNV(uint program, enum programInterface,
                                    uint index, sizei propCount,
                                    const enum *props, sizei bufSize,
                                    sizei *length, float *params);

New Tokens

    Accepted in elements of the <commands> array parameter of
    PathCommandsNV and PathSubCommandsNV:

        CLOSE_PATH_NV                                   0x00
        MOVE_TO_NV                                      0x02
        RELATIVE_MOVE_TO_NV                             0x03
        LINE_TO_NV                                      0x04
        RELATIVE_LINE_TO_NV                             0x05
        HORIZONTAL_LINE_TO_NV                           0x06
        RELATIVE_HORIZONTAL_LINE_TO_NV                  0x07
        VERTICAL_LINE_TO_NV                             0x08
        RELATIVE_VERTICAL_LINE_TO_NV                    0x09
        QUADRATIC_CURVE_TO_NV                           0x0A
        RELATIVE_QUADRATIC_CURVE_TO_NV                  0x0B
        CUBIC_CURVE_TO_NV                               0x0C
        RELATIVE_CUBIC_CURVE_TO_NV                      0x0D
        SMOOTH_QUADRATIC_CURVE_TO_NV                    0x0E
        RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV           0x0F
        SMOOTH_CUBIC_CURVE_TO_NV                        0x10
        RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV               0x11
        SMALL_CCW_ARC_TO_NV                             0x12
        RELATIVE_SMALL_CCW_ARC_TO_NV                    0x13
        SMALL_CW_ARC_TO_NV                              0x14
        RELATIVE_SMALL_CW_ARC_TO_NV                     0x15
        LARGE_CCW_ARC_TO_NV                             0x16
        RELATIVE_LARGE_CCW_ARC_TO_NV                    0x17
        LARGE_CW_ARC_TO_NV                              0x18
        RELATIVE_LARGE_CW_ARC_TO_NV                     0x19
        CONIC_CURVE_TO_NV                               0x1A
        RELATIVE_CONIC_CURVE_TO_NV                      0x1B
        ROUNDED_RECT_NV                                 0xE8
        RELATIVE_ROUNDED_RECT_NV                        0xE9
        ROUNDED_RECT2_NV                                0xEA
        RELATIVE_ROUNDED_RECT2_NV                       0xEB
        ROUNDED_RECT4_NV                                0xEC
        RELATIVE_ROUNDED_RECT4_NV                       0xED
        ROUNDED_RECT8_NV                                0xEE
        RELATIVE_ROUNDED_RECT8_NV                       0xEF
        RESTART_PATH_NV                                 0xF0
        DUP_FIRST_CUBIC_CURVE_TO_NV                     0xF2
        DUP_LAST_CUBIC_CURVE_TO_NV                      0xF4
        RECT_NV                                         0xF6
        RELATIVE_RECT_NV                                0xF7
        CIRCULAR_CCW_ARC_TO_NV                          0xF8
        CIRCULAR_CW_ARC_TO_NV                           0xFA
        CIRCULAR_TANGENT_ARC_TO_NV                      0xFC
        ARC_TO_NV                                       0xFE
        RELATIVE_ARC_TO_NV                              0xFF

    Accepted by the <format> parameter of PathStringNV:

        PATH_FORMAT_SVG_NV                              0x9070
        PATH_FORMAT_PS_NV                               0x9071

    Accepted by the <fontTarget> parameter of PathGlyphsNV,
    PathGlyphRangeNV, and PathGlyphIndexRangeNV:

        STANDARD_FONT_NAME_NV                           0x9072
        SYSTEM_FONT_NAME_NV                             0x9073
        FILE_NAME_NV                                    0x9074

    Accepted by the <fontTarget> parameter of PathMemoryGlyphIndexArrayNV:

        STANDARD_FONT_FORMAT_NV                         0x936C

    Accepted by the <handleMissingGlyph> parameter of PathGlyphsNV and
    PathGlyphRangeNV:

        SKIP_MISSING_GLYPH_NV                           0x90A9
        USE_MISSING_GLYPH_NV                            0x90AA

    Returned by PathGlyphIndexRangeNV:

        FONT_GLYPHS_AVAILABLE_NV                        0x9368
        FONT_TARGET_UNAVAILABLE_NV                      0x9369
        FONT_UNAVAILABLE_NV                             0x936A
        FONT_UNINTELLIGIBLE_NV                          0x936B  // once was FONT_CORRUPT_NV
        INVALID_ENUM
        INVALID_VALUE
        OUT_OF_MEMORY

    Accepted by the <pname> parameter of PathParameterfNV,
    PathParameterfvNV, GetPathParameterfvNV, PathParameteriNV,
    PathParameterivNV, and GetPathParameterivNV:

        PATH_STROKE_WIDTH_NV                            0x9075
        PATH_INITIAL_END_CAP_NV                         0x9077
        PATH_TERMINAL_END_CAP_NV                        0x9078
        PATH_JOIN_STYLE_NV                              0x9079
        PATH_MITER_LIMIT_NV                             0x907A
        PATH_INITIAL_DASH_CAP_NV                        0x907C
        PATH_TERMINAL_DASH_CAP_NV                       0x907D
        PATH_DASH_OFFSET_NV                             0x907E
        PATH_CLIENT_LENGTH_NV                           0x907F
        PATH_DASH_OFFSET_RESET_NV                       0x90B4

        PATH_FILL_MODE_NV                               0x9080
        PATH_FILL_MASK_NV                               0x9081
        PATH_FILL_COVER_MODE_NV                         0x9082
        PATH_STROKE_COVER_MODE_NV                       0x9083
        PATH_STROKE_MASK_NV                             0x9084
        PATH_STROKE_BOUND_NV                            0x9086

    Accepted by the <pname> parameter of PathParameterfNV and
    PathParameterfvNV:

        PATH_END_CAPS_NV                                0x9076
        PATH_DASH_CAPS_NV                               0x907B

    Accepted by the <fillMode> parameter of StencilFillPathNV and
    StencilFillPathInstancedNV:

        INVERT
        COUNT_UP_NV                                     0x9088
        COUNT_DOWN_NV                                   0x9089
        PATH_FILL_MODE_NV                               see above

    Accepted by the <color> parameter of PathColorGenNV,
    GetPathColorGenivNV, and GetPathColorGenfvNV:

        PRIMARY_COLOR                                   0x8577  // from OpenGL 1.3
        PRIMARY_COLOR_NV                                0x852C  // from NV_register_combiners
        SECONDARY_COLOR_NV                              0x852D  // from NV_register_combiners

    Accepted by the <genMode> parameter of PathColorGenNV, PathTexGenNV,
    ProgramPathFragmentInputGenNV:

        NONE
        EYE_LINEAR
        OBJECT_LINEAR
        PATH_OBJECT_BOUNDING_BOX_NV                     0x908A
        CONSTANT

    Accepted by the <coverMode> parameter of CoverFillPathNV and
    CoverFillPathInstancedNV:

        CONVEX_HULL_NV                                  0x908B
        BOUNDING_BOX_NV                                 0x908D
        PATH_FILL_COVER_MODE_NV                         see above

    Accepted by the <coverMode> parameter of CoverStrokePathNV and
    CoverStrokePathInstancedNV:

        CONVEX_HULL_NV                                  see above
        BOUNDING_BOX_NV                                 see above
        PATH_STROKE_COVER_MODE_NV                       see above

    Accepted by the <transformType> parameter of
    StencilFillPathInstancedNV, StencilStrokePathInstancedNV,
    CoverFillPathInstancedNV, and CoverStrokePathInstancedNV:

        NONE
        TRANSLATE_X_NV                                  0x908E
        TRANSLATE_Y_NV                                  0x908F
        TRANSLATE_2D_NV                                 0x9090
        TRANSLATE_3D_NV                                 0x9091
        AFFINE_2D_NV                                    0x9092
        AFFINE_3D_NV                                    0x9094
        TRANSPOSE_AFFINE_2D_NV                          0x9096
        TRANSPOSE_AFFINE_3D_NV                          0x9098

    Accepted by the <transformType> parameter of TransformPathNV:

        NONE
        TRANSLATE_X_NV                                  see above
        TRANSLATE_Y_NV                                  see above
        TRANSLATE_2D_NV                                 see above
        TRANSLATE_3D_NV                                 see above
        AFFINE_2D_NV                                    see above
        AFFINE_3D_NV                                    see above
        TRANSPOSE_AFFINE_2D_NV                          see above
        TRANSPOSE_AFFINE_3D_NV                          see above

    Accepted by the <type> or <pathNameType> parameter of
    StencilFillPathInstancedNV, StencilStrokePathInstancedNV,
    CoverFillPathInstancedNV, CoverStrokePathInstancedNV,
    GetPathMetricsNV, and GetPathSpacingNV:

        UTF8_NV                                         0x909A
        UTF16_NV                                        0x909B

    Accepted by the <coverMode> parameter of CoverFillPathInstancedNV:

        CONVEX_HULL_NV                                  see above
        BOUNDING_BOX_NV                                 see above
        BOUNDING_BOX_OF_BOUNDING_BOXES_NV               0x909C
        PATH_FILL_COVER_MODE_NV                         see above

    Accepted by the <coverMode> parameter of CoverStrokePathInstancedNV:

        CONVEX_HULL_NV                                  see above
        BOUNDING_BOX_NV                                 see above
        BOUNDING_BOX_OF_BOUNDING_BOXES_NV               see above
        PATH_STROKE_COVER_MODE_NV                       see above

    Accepted by the <pname> parameter of GetPathParameterfvNV and
    GetPathParameterivNV:

        PATH_COMMAND_COUNT_NV                           0x909D
        PATH_COORD_COUNT_NV                             0x909E
        PATH_DASH_ARRAY_COUNT_NV                        0x909F

        PATH_COMPUTED_LENGTH_NV                         0x90A0

        PATH_OBJECT_BOUNDING_BOX_NV                     see above
        PATH_FILL_BOUNDING_BOX_NV                       0x90A1
        PATH_STROKE_BOUNDING_BOX_NV                     0x90A2

    Accepted by the <value> parameter of PathParameterfNV,
    PathParameterfvNV, PathParameteriNV, and PathParameterivNV
    when <pname> is one of PATH_END_CAPS_NV, PATH_INTIAL_END_CAP_NV,
    PATH_TERMINAL_END_CAP_NV, PATH_DASH_CAPS_NV, PATH_INITIAL_DASH_CAP_NV,
    and PATH_TERMINAL_DASH_CAP_NV:

        FLAT
        SQUARE_NV                                       0x90A3
        ROUND_NV                                        0x90A4
        TRIANGULAR_NV                                   0x90A5

    Accepted by the <value> parameter of PathParameterfNV,
    PathParameterfvNV, PathParameteriNV, and PathParameterivNV
    when <pname> is PATH_JOIN_STYLE_NV:

        NONE
        ROUND_NV                                        see above
        BEVEL_NV                                        0x90A6
        MITER_REVERT_NV                                 0x90A7
        MITER_TRUNCATE_NV                               0x90A8

    Accepted by the <value> parameter of PathParameterfNV,
    PathParameterfvNV, PathParameteriNV, and PathParameterivNV when
    <pname> is PATH_DASH_OFFSET_RESET_NV:

        MOVE_TO_RESETS_NV                               0x90B5
        MOVE_TO_CONTINUES_NV                            0x90B6

    Accepted by the <fontStyle> parameter of PathGlyphsNV,
    PathGlyphRangeNV, and PathGlyphIndexRangeNV:

        NONE
        BOLD_BIT_NV                                     0x01
        ITALIC_BIT_NV                                   0x02

    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
    GetInteger64v, GetFloatv, and GetDoublev:

        PATH_ERROR_POSITION_NV                          0x90AB

        PATH_FOG_GEN_MODE_NV                            0x90AC

        PATH_STENCIL_FUNC_NV                            0x90B7
        PATH_STENCIL_REF_NV                             0x90B8
        PATH_STENCIL_VALUE_MASK_NV                      0x90B9

        PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV             0x90BD
        PATH_STENCIL_DEPTH_OFFSET_UNITS_NV              0x90BE

        PATH_COVER_DEPTH_FUNC_NV                        0x90BF

    Accepted as a bit within the <metricQueryMask> parameter of
    GetPathMetricRangeNV or GetPathMetricsNV:

        // per-glyph metrics
        GLYPH_WIDTH_BIT_NV                              0x01
        GLYPH_HEIGHT_BIT_NV                             0x02
        GLYPH_HORIZONTAL_BEARING_X_BIT_NV               0x04
        GLYPH_HORIZONTAL_BEARING_Y_BIT_NV               0x08
        GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV         0x10
        GLYPH_VERTICAL_BEARING_X_BIT_NV                 0x20
        GLYPH_VERTICAL_BEARING_Y_BIT_NV                 0x40
        GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV           0x80
        GLYPH_HAS_KERNING_BIT_NV                        0x100

        // per-font face metrics
        FONT_X_MIN_BOUNDS_BIT_NV                        0x00010000
        FONT_Y_MIN_BOUNDS_BIT_NV                        0x00020000
        FONT_X_MAX_BOUNDS_BIT_NV                        0x00040000
        FONT_Y_MAX_BOUNDS_BIT_NV                        0x00080000
        FONT_UNITS_PER_EM_BIT_NV                        0x00100000
        FONT_ASCENDER_BIT_NV                            0x00200000
        FONT_DESCENDER_BIT_NV                           0x00400000
        FONT_HEIGHT_BIT_NV                              0x00800000
        FONT_MAX_ADVANCE_WIDTH_BIT_NV                   0x01000000
        FONT_MAX_ADVANCE_HEIGHT_BIT_NV                  0x02000000
        FONT_UNDERLINE_POSITION_BIT_NV                  0x04000000
        FONT_UNDERLINE_THICKNESS_BIT_NV                 0x08000000
        FONT_HAS_KERNING_BIT_NV                         0x10000000
        FONT_NUM_GLYPH_INDICES_BIT_NV                   0x20000000

    Accepted by the <pathListMode> parameter of GetPathSpacingNV:

        ACCUM_ADJACENT_PAIRS_NV                         0x90AD
        ADJACENT_PAIRS_NV                               0x90AE
        FIRST_TO_REST_NV                                0x90AF

    Accepted by the <pname> parameter of GetPathColorGenivNV,
    GetPathColorGenfvNV, GetPathTexGenivNV and GetPathTexGenfvNV:

        PATH_GEN_MODE_NV                                0x90B0
        PATH_GEN_COEFF_NV                               0x90B1

    Accepted by the <pname> parameter of GetPathColorGenivNV and
    GetPathColorGenfvNV:

        PATH_GEN_COLOR_FORMAT_NV                        0x90B2

    Accepted by the <pname> parameter of GetPathTexGenivNV and
    GetPathTexGenfvNV:

        PATH_GEN_COMPONENTS_NV                          0x90B3

    Accepted by the <programInterface> parameter of GetProgramInterfaceiv,
    GetProgramResourceIndex, GetProgramResourceName, GetProgramResourceiv,
    GetProgramResourcefvNV, and GetProgramResourceLocation:

        FRAGMENT_INPUT_NV                               0x936D

    Accepted in the <props> array of GetProgramResourceiv:

        PATH_GEN_MODE_NV                                see above
        PATH_GEN_COMPONENTS_NV                          see above

    Accepted in the <props> array of GetProgramResourcefvNV:

        PATH_GEN_COEFF_NV                               see above

Additions to Chapter 2 of the OpenGL 3.2 (unabridged) Specification
(OpenGL Operation)

    Add to the end of Section 2.12.1 (Matrices) with
    EXT_direct_state_access language applied...

    "The command

        void MatrixLoad3x2fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x2matrix[16] = {
            m[0], m[2], 0, m[4],
            m[1], m[3], 0, m[5],
            0,    0,    1, 0,
            0,    0,    0, 1
        };
        MatrixLoadTransposefEXT(matrixMode, equiv_3x2matrix);

    The command

        void MatrixLoad3x3fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x3matrix[16] = {
            m[0], m[3], 0, m[6],
            m[1], m[4], 0, m[7],
            0,    0,    1, 0,
            m[2], m[5], 0, m[8],
        };
        MatrixLoadTransposefEXT(matrixMode, equiv_3x3matrix);

    The command

        void MatrixLoadTranspose3x3fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x3matrix[16] = {
            m[0], m[1], 0, m[2],
            m[3], m[4], 0, m[5],
            0,    0,    1, 0,
            m[6], m[7], 0, m[8],
        };
        MatrixLoadTransposefEXT(matrixMode, equiv_3x3matrix);

    The command

        void MatrixMult3x2fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x2matrix[16] = {
            m[0], m[2], 0, m[4],
            m[1], m[3], 0, m[5],
            0,    0,    1, 0,
            0,    0,    0, 1
        };
        MatrixMultTransposefEXT(matrixMode, equiv_3x2matrix);

    The command

        void MatrixMult3x3fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x3matrix[16] = {
            m[0], m[3], 0, m[6],
            m[1], m[4], 0, m[7],
            0,    0,    1, 0,
            m[2], m[5], 0, m[8],
        };
        MatrixMultTransposefEXT(matrixMode, equiv_3x3matrix);

    The command

        void MatrixMultTranspose3x3fNV(enum matrixMode, const float *m);

    is equivalent to:

        const float equiv_3x3matrix[16] = {
            m[0], m[1], 0, m[2],
            m[3], m[4], 0, m[5],
            0,    0,    1, 0,
            m[6], m[7], 0, m[8],
        };
        MatrixMultTransposefEXT(matrixMode, equiv_3x3matrix);"

    Modify the ARB_program_interface_query language as follows...

    Add to the "query properties of the interfaces of a program object"
    paragraph, so the "supported values of <programInterface>" includes:

      * FRAGMENT_INPUT_NV corresponds to the set of active input variables
        used by the fragment shader stage of <program> (if a fragment
        stage exists).  (This may be different from PROGRAM_INPUT except
        when the first shader stage is the fragment stage when they will
        be identical.)

    Change this sentence about when locations are assigned to include
    FRAGMENT_INPUT_NV so it reads:

    "When a program is linked successfully, active variables in the
    UNIFORM, PROGRAM_INPUT, FRAGMENT_INPUT_NV, PROGRAM_OUTPUT interface,
    or in any of the subroutine uniform interfaces, are assigned one or
    more signed integer /locations/."

    Amend Table X.1 "GetProgramResourceiv properties and supported
    interfaces" to add FRAGMENT_INPUT_NV to all the properties that
    allow PROGRAM_INPUT.  Specifically:

      * NAME_LENGTH
      * TYPE
      * ARRAY_SIZE
      * REFERENCED_BY_*_SHADER
      * LOCATION
      * IS_PER_PATCH (will always be false for FRAGMENT_INPUT_NV)

    Further amend Table X.1 "GetProgramResourceiv properties with two
    more properties for fragment input path generation state:

      Property                     Supported Interfaces
      ---------------------------  ----------------------------------------
      PATH_GEN_MODE_NV             FRAGMENT_INPUT_NV
      PATH_GEN_COMPONENTS_NV       FRAGMENT_INPUT_NV

    Amend the discussion of GetProgramResourceiv properties, adding:

    "For the property PATH_GEN_MODE_NV, a single integer identifying
    the path generation mode of an active variable is written to
    <params>.  The integer returned is one of NONE, OBJECT_LINEAR,
    PATH_OBJECT_BOUNDING_BOX_NV, or EYE_LINEAR based on how
    ProgramPathFragmentInputGenNV last specified the program resource's
    path generation mode.  The initial state is NONE.

    For the property PATH_GEN_COMPONENTS_NV, a single integer identifying
    the number of generated path components an active variable is written
    to <params>.  The integer returned is between 0 and 4 based on how
    ProgramPathFragmentInputGenNV last specified the program resource's
    path generation number of components.  The initial state is 0."

    Amend the list of tokens supported for the <programInterface> parameter of
    GetProgramResourceLocation to include FRAGMENT_INPUT_NV so the relevant
    sentence reads:

    "For GetProgramResourceLocation, <programInterface> must be one
    of UNIFORM, PROGRAM_INPUT, FRAGMENT_INPUT_NV, PROGRAM_OUTPUT,
    VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_SUBROUTINE_UNIFORM,
    TESS_EVALUATION_SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_UNIFORM,
    FRAGMENT_SUBROUTINE_UNIFORM, or COMPUTE_SUBROUTINE_UNIFORM."

    After the discussion of GetProgramResourceiv, add:

    "The command

        void GetProgramResourcefvNV(uint program, enum programInterface,
                                    uint index, sizei propCount,
                                    const enum *props, sizei bufSize,
                                    sizei *length, float *params);

    operates in the same manner as GetProgramResourceiv expect the
    returned parameters values are floating-point and the only valid
    value of <programInterface> is FRAGMENT_INPUT_NV and the only valid value
    for the elements of the <props> array is PATH_GEN_COEFF_NV; otherwise
    INVALID_ENUM is generated.

    For the property PATH_GEN_COEFF_NV, sixteen floating-point values
    are written to <params> (limited to writing <bufSize> floating-point
    values)."

Additions to Chapter 3 of the OpenGL 3.2 (unabridged) Specification
(Rasterization)

    Append to the end of the "Shader Inputs" subsection of Section 3.12.2
    "Shader Execution":

    The command

        void ProgramPathFragmentInputGenNV(uint program,
                                           int location,
                                           enum genMode,
                                           int components,
                                           const float *coeffs);

    controls how a user-defined (non-built-in) fragment input of a
    GLSL program object is computed for fragment shading operations that
    occur as a result of CoverFillPathNV or CoverStrokePathNV.

    /program/ names a GLSL program object.  If /program/ has not been
    successfully linked, the error INVALID_OPERATION is generated.

    The given fragment input generation state is loaded into the fragment
    input variable location identified by /location/.  This location
    is a value returned either by GetProgramResourceLocation with a
    /programInterface/ of FRAGMENT_INPUT_NV and a given fragment shader
    input variable name or by GetProgramResourceiv with FRAGMENT_INPUT_NV
    for the /programInterface/ and LOCATION for the property for a given
    fragment input resource index.

    If the value of location is -1, the ProgramPathFragmentInputGenNV command
    will silently ignore the command, and the program's path fragment input
    generation state will not be changed.

    If any of the following conditions occur, an INVALID_OPERATION error
    is generated by the ProgramPathFragmentInputGenNV, and no state is changed:

        * if the size indicated in the /components/ of the
          ProgramPathFragmentInputGenNV command used does not match the
          size of the fragment input scalar or vector declared in the
          shader,

        * if the fragment input declared in the shader is not
          single-precision floating-point, or

        * if no fragment input variable with a location of /location/
          exists in the program object named by /program/ and location
          is not -1, or

        * if the fragment input declared in the shader is a built-in
          variables (i.e. prefixed by "gl_").

    When covering paths, fragment input variables are interpolated at
    each shaded fragment based on the corresponding fragment input
    generation state specified by ProgramPathFragmentInputGenNV for
    each respective fragment input.

    The /genMode/, /components/, and /coeffs/ parameters are used to
    generate the fragment input variable values identically as the
    PathTexGenNV command's corresponding parameters except it is a
    fragment input that is generated rather than a texture coordinate set
    (see the "TEXTURE COORDINATE SET GENERATION FOR PATH COVER COMMANDS"
    discussion in section 5.X.2.2 "Path Covering").  Because there is
    no associated texture coordinate set, the sc, tc, rc, and qc values
    when discussing PathTexGenNV are always zero when generating fragment
    input variables.

    When covering paths, if a fragment input variable has not had its
    path fragment input generation state successfully generated, it as
    if the values of this variable are always initialized to zero when
    the fragment shader is executing.

    Also when covering paths, GLSL fragment shaders support the following
    built-in fragment input variables:

        in vec4 gl_TexCoord[gl_MaxTextureCoords];
        in vec4 gl_Color
        in vec4 gl_FrontColor;
        in vec4 gl_BackColor;
        in vec4 gl_SecondaryColor;
        in vec4 gl_FrontSecondaryColor;
        in vec4 gl_BackSecondaryColor;
        in float gl_FogFragCoord;

    These respectively are initialized to the fragment input generated
    coordinates of PathTexGenNV, PathColorGenNV for GL_PRIMARY_COLOR_NV
    (front or back), PathColorGenNV for GL_SECONDARY_COLOR_NV (front or
    back), and glPathFogGenNV."

Additions to Chapter 4 of the OpenGL 3.2 (unabridged) Specification
(Per-Fragment Operations and the Frame Buffer)

    None

Additions to Chapter 5 of the OpenGL 3.2 (unabridged) Specification
(Special Functions)

 -- Insert section 5.X "Path Rendering" after 5.3 "Feedback"

    5.X Path Rendering

    5.X.1 Path Specification

    PATH COMMANDS

    Paths are specified as a sequence of path commands; each path command
    has an associated sequence of floating-point coordinates with the
    number of such coordinates depending on the specific path command.
    Coordinates are specified in a sequence independent from the path
    command sequence; coordinates from the coordinate sequence are matched
    up with (associated with) commands, in the order of the command,
    with coordinates extracted from the front of the coordinate sequence.

    Valid path commands are listed in table 5.pathCommands.  Each path
    command is listed with its associated token, description, character
    alias, count of associated coordinates.

    As an example of how path commands associated with path coordinates,
    if the command sequence was MOVE_TO_NV, LINE_TO_NV, CUBIC_CURVE_TO_NV,
    CLOSE_PATH_NV and the coordinates were 1, 2, 3, 4, 5, 6, 7, 8, 9,
    10, the MOVE_TO_NV command would be matched to coordinates 1 and 2,
    LINE_TO_NV would be matched to 3 and 4, CUBIC_CURVE_TO_NV would be
    matched to 5, 6, 7, 8, 9, 10, and CLOSE_PATH_NV would be matched to
    no coordinates.

    Path commands are processed in their sequence order to generate the
    path's outline.  The outline generation process maintains three 2D
    (x,y) state variables for each path processed: the start position
    (sp), the current position (cp), and the prior end point (pep);
    /sp/, /cp/ and /pep/ are initially (0,0) when a path starts being
    processed.

    Table 5.pathCommands: Path Commands

                                                       Character   Coordinate
    Token                       Description            alias       count
    ==========================  =====================  ==========  ==========
    MOVE_TO_NV                  Absolute move          'M'         2
                                current point
    RELATIVE_MOVE_TO_NV         Relative move          'm'         2
                                current point
    --------------------------  ---------------------  ----------  ----------
    CLOSE_PATH_NV               Close path             'Z' or 'z'  0
    RESTART_PATH_NV             Reset the path         -           0
    --------------------------  ---------------------  ----------  ----------
    LINE_TO_NV                  Absolute line          'L'         2
    RELATIVE_LINE_TO_NV         Relative line          'l'         2
    --------------------------  ---------------------  ----------  ----------
    HORIZONTAL_LINE_TO_NV       Absolute horizontal    'H'         1
                                line
    RELATIVE_HORIZONTAL-        Relative horizontal    'h'         1
      _LINE_TO_NV               line
    VERTICAL_LINE_TO_NV         Absolute vertical      'V'         1
                                line
    RELATIVE_VERTICAL-          Relative vertical      'v'         1
      _LINE_TO_NV               line
    --------------------------  ---------------------  ----------  ----------
    QUADRATIC_CURVE_TO_NV       Absolute quadratic     'Q'         4
                                Bezier segment
    RELATIVE-                   Relative quadratic     'q'         4
      _QUADRATIC_CURVE_TO_NV    Bezier segment
    --------------------------  ---------------------  ----------  ----------
    CUBIC_CURVE_TO_NV           Absolute cubic         'C'         6
                                Bezier segment
    RELATIVE_CUBIC_CURVE_TO_NV  Relative cubic         'c'         6
                                Bezier segment
    --------------------------  ---------------------  ----------  ----------
    SMOOTH-                     Absolute smooth        'T'         2
      _QUADRATIC_CURVE_TO_NV    quadratic Bezier
                                segment
    RELATIVE_SMOOTH-            Relative smooth        't'         2
      _QUADRATIC_CURVE_TO_NV    quadratic Bezier
                                segment
    --------------------------  ---------------------  ----------  ----------
    SMOOTH-                     Absolute smooth        'S'         4
      _CUBIC_CURVE_TO_NV        cubic Bezier segment
    RELATIVE_SMOOTH-            Relative smooth        's'         4
      _CUBIC_CURVE_TO_NV        cubic Bezier segment
    --------------------------  ---------------------  ----------  ----------
    SMALL_CCW_ARC_TO_NV         Absolute small-sweep   -           5
                                counterclockwise
                                partial elliptical
                                arc segment
    RELATIVE-                   Relative small-sweep   -           5
      _SMALL_CCW_ARC_TO_NV      counterclockwise
                                partial elliptical
                                arc segment
    SMALL_CW_ARC_TO_NV          Absolute small-sweep   -           5
                                clockwise partial
                                elliptical arc
                                segment
    RELATIVE-                   Relative small-sweep   -           5
      _SMALL_CW_ARC_TO_NV       clockwise partial
                                elliptical arc
                                segment
    LARGE_CCW_ARC_TO_NV         Absolute large-sweep   -           5
                                counterclockwise
                                partial elliptical
                                arc segment
    RELATIVE-                   Relative large-sweep   -           5
      _LARGE_CCW_ARC_TO_NV      counterclockwise
                                partial elliptical
                                arc segment
    LARGE_CW_ARC_TO_NV          Absolute large-sweep   -           5
                                clockwise partial
                                elliptical arc
                                segment
    RELATIVE-                   Relative large-sweep   -           5
      _LARGE_CW_ARC_TO_NV       clockwise partial
                                elliptical arc
                                segment
    --------------------------  ---------------------  ----------  ----------
    CONIC_CURVE_TO_NV           Absolute conic         'W'         5
                                (rational Bezier)
                                segment
    RELATIVE-                   Relative conic         'w'         5
      _CONIC_CURVE_TO_NV        (rational Bezier)
                                segment
    --------------------------  ---------------------  ----------  ----------
    ROUNDED_RECT_NV             Absolute rounded       -           5
                                rectangle with
                                uniform circular
                                corners (1 radius)
    RELATIVE_ROUNDED_RECT_NV    Relative rounded       -           5
                                rectangle with
                                uniform circular
                                corners (1 radius)
    ROUNDED_RECT2_NV            Absolute rounded       -           6
                                rectangle with
                                uniform elliptical
                                corners (2 x&y radii)
    RELATIVE_ROUNDED_RECT2_NV   Relative rounded       -           6
                                rectangle with
                                uniform elliptical
                                corners (2 x&y radii)
    ROUNDED_RECT4_NV            Absolute rounded       -           8
                                rectangle with
                                varying circular
                                corners (4 radii)
    RELATIVE_ROUNDED_RECT4_NV   Relative rounded       -           8
                                rectangle with
                                varying circular
                                corners (4 radii)
    ROUNDED_RECT8_NV            Absolute rounded       -           12
                                rectangle with
                                varying elliptical
                                corners (8 radii)
    RELATIVE_ROUNDED_RECT8_NV   Relative rounded       -           12
                                rectangle with
                                varying elliptical
                                corners (8 radii)
    --------------------------  ---------------------  ----------  ----------
    DUP_FIRST_-                 Absolute cubic Bezier  -           4
      CUBIC_CURVE_TO_NV         segment, duplicating
                                first control point
    DUP_LAST_CUBIC_CURVE_TO_NV  Absolute cubic Bezier  -           4
                                segment, duplicating
                                last control point
    RECT_NV                     Closed absolute        -           4
                                rectangle
    RELATIVE_RECT_NV            Closed relative        -           4
                                rectangle
    --------------------------  ---------------------  ----------  ----------
    CIRCULAR_CCW_ARC_TO_NV      Absolute               -           5
                                counterclockwise
                                circular arc segment
    CIRCULAR_CW_ARC_TO_NV       Absolute clockwise     -           5
                                circular arc segment
    CIRCULAR_TANGENT_ARC_TO_NV  Absolute circular      -           5
                                tangential
                                arc segment
    --------------------------  ---------------------  ----------  ----------
    ARC_TO_NV                   Absolute general       'A'         7
                                elliptical arc
    RELATIVE_ARC_TO_NV          Relative general       'a'         7
                                elliptical arc
    --------------------------  ---------------------  ----------  ----------

    Table 5.pathEquations provides for each path command, as relevant,
    the command's path segment parametric equation, equations for the
    updated current point (ncp) and equations for the updated prior
    end point (npep).  After each command in a path is processed in the
    sequence, the new current point, prior end point, and start point
    (if changed) update the current point, prior end point, and start
    point for the next path command to be processed in the sequence.  So:

       cp = ncp
       pep = npep

    Each path segment parametric equation is parameterized by a variable
    /t/ ranging from 0.0 to 1.0.  So the outline is traced by evaluating
    each path command's path segment parametric equation continuously
    as /t/ varies from 0.0 to 1.0.

    With the exception of the MOVE_TO_NV, RELATIVE_MOVE_TO_NV,
    RESTART_PATH_NV, RECT_NV, RELATIVE_RECT_NV, ROUNDED_RECT_NV,
    RELATIVE_ROUNDED_RECT_NV, ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV,
    ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV,
    RELATIVE_ROUNDED_RECT8_NV, CIRCULAR_CCW_ARC_TO_NV, and
    CIRCULAR_CW_ARC_TO_NV commands, the commands are specified such that
    C0 continuity of the outline is guaranteed at path command segment
    end-points.

    The MOVE_TO_NV, RELATIVE_MOVE_TO_NV, RESTART_PATH_NV, RECT_NV,
    RELATIVE_RECT_NV, ROUNDED_RECT_NV, RELATIVE_ROUNDED_RECT_NV,
    ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV,
    ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV,
    RELATIVE_ROUNDED_RECT8_NV, CIRCULAR_CCW_ARC_TO_NV, and
    CIRCULAR_CW_ARC_TO_NV commands update the start position (sp) to
    the value of these command's new current point (ncp).

    The MOVE_TO_NV, RELATIVE_MOVE_TO_NV, RECT_NV,
    RELATIVE_RECT_NV, ROUNDED_RECT_NV, RELATIVE_ROUNDED_RECT_NV,
    ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV,
    ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV,
    RELATIVE_ROUNDED_RECT8_NV, commands unconditionally change the start
    position (sp) to value of these command's new current point (ncp) so:

        sp = ncp

    The CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV commands
    conditionally change sp to the command's ncp but only the sp has not
    been specified by any prior command other than CLOSE_PATH_NV in the
    path's command sequence since the beginning of the path's command
    sequence or last RESTART_PATH_NV.  When these circular arc commands
    change the sp to the command's ncp, it implies the initial implicit
    line these commands generate from sp to ncp will be zero length.
    (This behavior is to match the semantics of PostScript.)

    Moving of the start position creates a discontinuity in the outline
    so starts a new subpath within the path.

    Table 5.pathEquations: Path Equations

                                Path segment                            new current         new prior end
    Token                       parametric equation                     point equation      point equation
    ==========================  ======================================  ==================  =======================
    MOVE_TO_NV                  -                                       ncp.x = c[0]        npep.x = c[0]
                                                                        ncp.y = c[1]        npep.y = c[1]
    RELATIVE_MOVE_TO_NV         -                                       ncp.x = cp.x+c[0]   npep.x = cp.x+c[0]
                                                                        ncp.y = cp.y+c[1]   npep.y = cp.y+c[1]
    --------------------------  --------------------------------------  ------------------  -----------------------
    CLOSE_PATH_NV               x = (1-t)*cp.x + t*sp.x                 ncp.x = sp.x        npep.x = sp.x
                                y = (1-t)*cp.y + t*sp.y                 ncp.y = sp.y        npep.y = sp.y
    RESTART_PATH_NV             -                                       ncp.x = 0           npep.x = 0
                                                                        ncp.y = 0           npep.y = 0
    --------------------------  --------------------------------------  ------------------  -----------------------
    LINE_TO_NV                  x = (1-t)*cp.x + t*c[0]                 ncp.x = c[0]        npep.x = c[0]
                                y = (1-t)*cp.y + t*c[1]                 ncp.y = c[1]        npep.y = c[1]
    RELATIVE_LINE_TO_NV         x = (1-t)*cp.x + t*(c[0]+cp.x)          ncp.x = cp.x+c[0]   npep.x = cp.x+c[0]
                                y = (1-t)*cp.y + t*(c[1]+cp.y)          ncp.y = cp.y+c[1]   npep.y = cp.y+c[1]
    --------------------------  --------------------------------------  ------------------  -----------------------
    HORIZONTAL_LINE_TO_NV       x = (1-t)*cp.x + t*sp.x                 ncp.x = c[0]        npep.x = c[0]
                                y = cp.y                                ncp.y = cp.y        npep.y = cp.y
    RELATIVE_HORIZONTAL-        x = (1-t)*cp.x + t*(c[0]+cp.x)          ncp.x = cp.x+c[0]   npep.x = cp.x+c[0]
      _LINE_TO_NV               y = cp.y                                ncp.y = cp.y        npep.y = cp.y
    VERTICAL_LINE_TO_NV         x = cp.x                                ncp.x = cp.x        npep.x = cp.x
                                y = (1-t)*cp.y + t*sp.y                 ncp.y = c[0]        npep.y = c[0]
    RELATIVE_VERTICAL-          x = cp.x                                ncp.x = cp.x        npep.x = cp.x
      _LINE_TO_NV               y = (1-t)*cp.y + t*(c[0]+cp.y)          ncp.y = cp.y+c[0]   npep.y = cp.y+c[0]
    --------------------------  --------------------------------------  ------------------  -----------------------
    QUADRATIC_CURVE_TO_NV       x = (1-t)^2*cp.x +                      ncp.x = c[2]        npep.x = c[0]
                                    2*(1-t)*t*c[0] +                    ncp.y = c[3]        npep.y = c[1]
                                    t^2*c[2]
                                y = (1-t)^2*cp.y +
                                    2*(1-t)*t*c[1] +
                                    t^2*c[3]
    RELATIVE-                   x = (1-t)^2*cp.x +                      ncp.x = cp.x+c[2]   npep.x = cp.x+c[0]
      _QUADRATIC_CURVE_TO_NV        2*(1-t)*t*(c[0]+cp.x) +             ncp.y = cp.x+c[3]   npep.y = cp.y+c[1]
                                    t^2*(c[2]+cp.x)
                                y = (1-t)^2*cp.y +
                                    2*(1-t)*t*(c[1]+cp.y) +
                                    t^2*(c[3]+cp.y)
    --------------------------  --------------------------------------  ------------------  -----------------------
    CUBIC_CURVE_TO_NV           x = (1-t)^3*cp.x +                      ncp.x = c[4]        npep.x = c[2]
                                    3*(1-t)^2*t*c[0] +                  ncp.y = c[5]        npep.y = c[3]
                                    3*(1-t)*t^2*c[2] +
                                    t^3*c[4]
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*c[1] +
                                    3*(1-t)*t^2*c[3] +
                                    t^3*c[5]
    RELATIVE_CUBIC_CURVE_TO_NV  x = (1-t)^3*cp.x +                      ncp.x = cp.x+c[4]   npep.x = cp.x+c[2]
                                    3*(1-t)^2*t*(c[0]+cp.x) +           ncp.y = cp.y+c[5]   npep.y = cp.y+c[3]
                                    3*(1-t)*t^2*(c[2]+cp.x) +
                                    t^3*(c[4]+cp.x)
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*(c[1]+cp.y) +
                                    3*(1-t)*t^2*(c[3]+cp.y) +
                                    t^3*(c[5]+cp.y)
    --------------------------  --------------------------------------  ------------------  -----------------------
    SMOOTH-                     x = (1-t)^2*cp.x +                      ncp.x = c[0]        npep.x = 2*cp.x-pep.x
      _QUADRATIC_CURVE_TO_NV        2*(1-t)*t*(2*cp.x-pep.x) +          ncp.y = c[1]        npep.y = 2*cp.y-pep.y
                                    t^2*c[0]
                                y = (1-t)^2*cp.y +
                                    2*(1-t)*t*(2*cp.y-pep.y) +
                                    t^2*c[1]
    RELATIVE_SMOOTH-            x = (1-t)^2*cp.x +                      ncp.x = cp.x+c[0]   npep.x = 2*cp.x-pep.x
      QUADRATIC_CURVE_TO_NV         2*(1-t)*t*(2*cp.x-pep.x) +          ncp.y = cp.y+c[1]   npep.y = 2*cp.y-pep.y
                                    t^2*(c[0]+cp.x)
                                y = (1-t)^2*cp.y +
                                    2*(1-t)*t*(2*cp.y-pep.y) +
                                    t^2*(c[1]+cp.y)

    SMOOTH-                     x = (1-t)^3*cp.x +                      ncp.x = c[2]        npep.x = c[0]
      _CUBIC_CURVE_TO_NV            3*(1-t)^2*t*(2*cp.x-pep.x) +        ncp.y = c[3]        npep.y = c[1]
                                    3*(1-t)*t^2*c[0] +
                                    t^3*c[2]
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*(2*cp.y-pep.y) +
                                    3*(1-t)*t^2*c[1] +
                                    t^3*c[3]
    RELATIVE_SMOOTH-            x = (1-t)^3*cp.x +                      ncp.x = cp.x+c[2]   npep.x = cp.x+c[0]
      _CUBIC_CURVE_TO_NV            3*(1-t)^2*t*(2*cp.x-pep.x) +        ncp.y = cp.y+c[3]   npep.y = cp.y+c[1]
                                    3*(1-t)*t^2*(c[0]+cp.x) +
                                    t^3*(c[2]+cp.x)
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*(2*cp.y-pep.y) +
                                    3*(1-t)*t^2*(c[1]+cp.y) +
                                    t^3*(c[3]+cp.y)
    --------------------------  --------------------------------------  ------------------  -----------------------
    SMALL_CCW_ARC_TO_NV         x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = c[3]
                                          theta1,dtheta,t)              ncp.y = c[4]        npep.y = c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    RELATIVE-                   x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = cp.x+c[3]
      _SMALL_CCW_ARC_TO_NV                theta1,dtheta,t)              ncp.y = c[4]        npep.y = cp.y+c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    SMALL_CW_ARC_TO_NV          x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = c[3]
                                          theta1,dtheta,t)              ncp.y = c[4]        npep.y = c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    RELATIVE-                   x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = cp.x+c[3]
      _SMALL_CW_ARC_TO_NV                 theta1,dtheta,t)              ncp.y = c[4]        npep.y = cp.y+c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    LARGE_CCW_ARC_TO_NV         x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = c[3]
                                          theta1,dtheta,t)              ncp.y = c[4]        npep.y = c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    RELATIVE-                   x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = cp.x+c[3]
      _LARGE_CCW_ARC_TO_NV                theta1,dtheta,t)              ncp.y = c[4]        npep.y = cp.y+c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    LARGE_CW_ARC_TO_NV          x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = c[3]
                                          theta1,dtheta,t)              ncp.y = c[4]        npep.y = c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    RELATIVE-                   x = arc_x(c,rv,rh,phi,                  ncp.x = c[3]        npep.x = cp.x+c[3]
      _SMALL_CW_ARC_TO_NV                 theta1,dtheta,t)              ncp.y = c[4]        npep.y = cp.y+c[4]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    --------------------------  --------------------------------------  ------------------  -----------------------
    CONIC_CURVE_TO_NV           WHEN c[4] > 0:                          ncp.x = c[2]        npep.x = c[0]
                                x = ( (1-t)^2*cp.x +                    ncp.y = c[3]        npep.y = c[1]
                                      2*(1-t)*t*c[0]*c[4] +
                                      t^2*c[2] ) /
                                    ( (1-t)^2 +
                                      2*(1-t)*t*c[4] +
                                      t^2*c[2] )
                                y = ( 1-t)^2*cp.y +
                                      2*(1-t)*t*c[1]*w +
                                      t^2*c[3] ) /
                                    ( (1-t)^2 +
                                      2*(1-t)*t*c[4] +
                                      t^2*c[2] ),
                                OTHERWISE:
                                x = (1-t)*cp.x + t*c[2]
                                y = (1-t)*cp.y + t*c[3]
    RELATIVE-                   WHEN c[4] > 0:                          ncp.x = cp.x+c[2]   npep.x = cp.x+c[0]
      _CONIC_CURVE_TO_NV        x = ( (1-t)^2*cp.x +                    ncp.y = cp.y+c[3]   npep.y = cp.y+c[1]
                                      2*(1-t)*t*(c[0]+cp.x)*c[4] +
                                      t^2*(c[2]+cp.x) ) /
                                    ( (1-t)^2 +
                                      2*(1-t)*t*c[4] +
                                      t^2*c[2] )
                                y = ( 1-t)^2*cp.y +
                                      2*(1-t)*t*c[1]*w +
                                      t^2*c[3] ) /
                                    ( (1-t)^2 +
                                      2*(1-t)*t*c[4] +
                                      t^2*c[2] ),
                                OTHERWISE:
                                x = (1-t)*cp.x + t*(c[2]+cp.x)
                                y = (1-t)*cp.y + t*(c[3]+cp.y)
    --------------------------  --------------------------------------  ------------------  -----------------------
    ROUNDED_RECT_NV             x = rrect(c[0], c[1], c[2], c[3],       ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[4], c[4], c[4], c[4],       ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[4], c[4], c[4], t).x
                                y = rrect(c[0], c[1], c[2], c[3],
                                          c[4], c[4], c[4], c[4],
                                          c[4], c[4], c[4], c[4], t).y
    RELATIVE_ROUNDED_RECT_NV    x = rrect(c[0]+cp.x, c[1]+cp.y,         ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[2], c[3],                   ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[4], c[4], c[4],
                                          c[4], c[4], c[4], c[4], t).x
                                y = rrect(c[0]+cp.x, c[1]+cp.y,
                                          c[2], c[3],
                                          c[4], c[4], c[4], c[4],
                                          c[4], c[4], c[4], c[4], t).y
    ROUNDED_RECT2_NV            x = rrect(c[0], c[1], c[2], c[3],       ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[4], c[5], c[4], c[5],       ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[5], c[4], c[5], t).x
                                y = rrect(c[0], c[1], c[2], c[3],
                                          c[4], c[5], c[4], c[5],
                                          c[4], c[5], c[4], c[5], t).y
    RELATIVE_ROUNDED_RECT2_NV   x = rrect(c[0]+cp.x, c[1]+cp.y,         ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[2], c[3],                   ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[5], c[4], c[5],
                                          c[4], c[5], c[4], c[5], t).x
                                y = rrect(c[0]+cp.x, c[1]+cp.y,
                                          c[2], c[3],
                                          c[4], c[5], c[4], c[5],
                                          c[4], c[5], c[4], c[5], t).y
    ROUNDED_RECT4_NV            x = rrect(c[0], c[1], c[2], c[3],       ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[4], c[4], c[5], c[5],       ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[6], c[6], c[7], c[7], t).x
                                y = rrect(c[0], c[1], c[2], c[3],
                                          c[4], c[4], c[5], c[5],
                                          c[6], c[6], c[7], c[7], t).y
    RELATIVE_ROUNDED_RECT4_NV   x = rrect(c[0]+cp.x, c[1]+cp.y,         ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[2], c[3],                   ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[4], c[5], c[5],
                                          c[6], c[6], c[7], c[7], t).x
                                y = rrect(c[0]+cp.x, c[1]+cp.y,
                                          c[2], c[3],
                                          c[4], c[4], c[5], c[5],
                                          c[6], c[6], c[7], c[7], t).y
    ROUNDED_RECT8_NV            x = rrect(c[0], c[1], c[2], c[3],       ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[4], c[5], c[6], c[7],       ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[8], c[9],
                                          c[10], c[11], t).x
                                y = rrect(c[0], c[1], c[2], c[3],
                                          c[4], c[5], c[6], c[7],
                                          c[8], c[9],
                                          c[10], c[11], t).y
    RELATIVE_ROUNDED_RECT8_NV   x = rrect(c[0]+cp.x, c[1]+cp.y,         ncp.x = C_ll.x      npep.x = C_ll.x
                                          c[2], c[3],                   ncp.y = C_ll.y      npep.y = C_ll.y
                                          c[4], c[5], c[6], c[7],
                                          c[8], c[9],
                                          c[10], c[11], t).x
                                y = rrect(c[0]+cp.x, c[1]+cp.y,
                                          c[2], c[3],
                                          c[4], c[5], c[6], c[7],
                                          c[8], c[9],
                                          c[10], c[11], t).y
    --------------------------  --------------------------------------  ------------------  -----------------------
    DUP_FIRST-                  x = (1-t)^3*cp.x +                      ncp.x = c[2]        npep.x = c[0]
      CUBIC_CURVE_TO_NV             3*(1-t)^2*t*cp.x +                  ncp.y = c[3]        npep.y = c[1]
                                    3*(1-t)*t^2*c[0] +
                                    t^3*c[2]
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*cp.y +
                                    3*(1-t)*t^2*c[1] +
                                    t^3*c[3]
    DUP_LAST_CUBIC_CURVE_TO_NV  x = (1-t)^3*cp.x +                      ncp.x = c[2]        npep.x = c[2]
                                    3*(1-t)^2*t*c[0] +                  ncp.y = c[3]        npep.y = c[3]
                                    3*(1-t)*t^2*c[2] +
                                    t^3*c[2]
                                y = (1-t)^3*cp.y +
                                    3*(1-t)^2*t*c[1] +
                                    3*(1-t)*t^2*c[3] +
                                    t^3*c[3]
    --------------------------  --------------------------------------  ------------------  -----------------------
    RECT_NV                         / (1-4*t)*c[0] +                    ncp.x = c[0]        npep.x = c[0]
                                    | 4*t*(c[0]+c[2]),         t<=0.25  ncp.y = c[1]        npep.y = c[1]
                                x = < c[0]+c[2],           0.25<t<=0.5
                                    | (1-4*t-2)*(c[0]+c[2]) +
                                    | (4*t-2)*c[0],       0.5 <t<=0.75
                                    \ c[0],                     0.75<t
                                    / c[1],                    t<=0.25
                                    | (1-4*t-1)*c[1] +
                                y = < (4*t-1)*(c[1]+c[3]), 0.25<t<=0.5
                                    | c[1]+c[3],          0.5 <t<=0.75
                                    | (1-4*t-3)*(c[1]+c[3]) +
                                    \ (4*t-3)*c[1],             0.75<t
    RELATIVE_RECT_NV                / (1-4*t)*(c[0]+cp.x) +             ncp.x = cp.x+c[0]   npep.x = cp.x+c[0]
                                    | 4*t*(c[0]+c[2]+cp.x),    t<=0.25  ncp.y = cp.y+c[1]   npep.y = cp.y+c[1]
                                x = < c[0]+c[2]+cp.x,      0.25<t<=0.5
                                    | (1-4*t-2)*(c[0]+c[2]+cp.x) +
                                    | (4*t-2)*(c[0]+cp.x), 0.5<t<=0.75
                                    \ c[0]+cp.x,                0.75<t
                                    / c[1]+cp.y,               t<=0.25
                                    | (1-4*t-1)*(c[1]+cp.y) +
                                y = < (4*t-1)*(c[1]+c[3]+cp.y),
                                    |                      0.25<t<=0.5
                                    | c[1]+c[3]+cp.y,      0.5<t<=0.75
                                    | (1-4*t-3)*(c[1]+c[3]+cp.y) +
                                    \ (4*t-3)*(c[1]+cp.y),      0.75<t
    --------------------------  --------------------------------------  ------------------  -----------------------
    CIRCULAR_CCW_ARC_TO_NV           / (1-2*t)*cp.x + 2*t*A.x,  t<=0.5  ncp.x = B.x         npep.x = B.x
                                x = {                                   ncp.y = B.y         npep.x = B.y
                                     \ arc_x(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1)      t>=0.5
                                     / (1-2*t)*cp.y + 2*t*A.y,  t<=0.5
                                y = {
                                     \ arc_y(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1),     t>=0.5
    CIRCULAR_CW_ARC_TO_NV            / (1-2*t)*cp.x + 2*t*A.x,  t<=0.5  ncp.x = B.x         npep.x = B.x
                                x = {                                   ncp.y = B.y         npep.x = B.y
                                     \ arc_x(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1)      t>=0.5
                                     / (1-2*t)*cp.y + 2*t*A.y,  t<=0.5
                                y = {
                                     \ arc_y(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1),     t>=0.5
    CIRCULAR_TANGENT_ARC_TO_NV       / (1-2*t)*cp.x + 2*t*C.x,  t<=0.5  ncp.x = D.x         npep.x = D.x
                                x = {                                   ncp.y = D.y         npep.x = D.y
                                     \ arc_x(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1),     t>=0.5
                                     / (1-2*t)*cp.y + 2*t*C.y,  t<=0.5
                                y = {
                                     \ arc_y(c,rv,rh,phi,theta1,
                                      \      dtheta,t*2-1),     t>=0.5
    --------------------------  --------------------------------------  ------------------  -----------------------
    ARC_TO_NV                   x = arc_x(c,rv,rh,phi,                  ncp.x = c[5]        npep.x = c[5]
                                          theta1,dtheta,t)              ncp.y = c[6]        npep.y = c[6]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    RELATIVE_ARC_TO_NV          x = arc_x(c,rv,rh,phi,                  ncp.x = cp.x+c[5]   npep.x = cp.x+c[5]
                                          theta1,dtheta,t)              ncp.y = cp.y+c[6]   npep.y = cp.y+c[6]
                                y = arc_y(c,rv,rh,phi,
                                          theta1,dtheta,t)
    --------------------------  --------------------------------------  ------------------  -----------------------

    In the equations in Table 5.pathEquations, c[i] is the /i/th (base
    zero) coordinate of the coordinate sequence for the command; /cp/
    is the 2D (x,y) current position from the prior command (for the
    first command of a path object, /cp/ is (0,0)); /sp/ is the 2D (x,y)
    start position for the current contour (for the first command of a
    path object, /sp/ is (0,0)); /pep/ is the 2D (x,y) prior end position
    from the prior end position (for the first command of a path object,
    /pep/ is (0,0)); and /ncp/ is the 2D (x,y) "new" current position
    that will become the current position for the subsequent command;
    /npep/ is the 2D (x,y) "new" prior end position for the subsequent
    command.  The values /c/, /theta1/, /dtheta/ are explained in the
    discussion of partial elliptical arc commands below.  The values
    of /rv/, /rh/, /phi/ come from Table 5.arcParameterSpecialization.
    The values of /A/, /B/, /C/, and /D/ are discussed in the context
    of Table 5.arcParameterSpecialization.  /C_ll/ is the lower-left
    end-point defined for Equation 5.roundedRectangleContour.

    If a value specified for a coordinate (however the coordinate is
    specified) or a value computed from these coordinates (as specified
    in the discussion that follows) exceeds the implementation's maximum
    representable value for a single-precision floating-point number,
    the rendering behavior (discussed in section 5.X.2) of the specified
    path and the value of said coordinate if queried (section 6.X.2)
    is undefined.  This is relevant because coordinates can be specified
    explicitly but also relatively (by RELATIVE_* path commands) or
    encoded in a string of otherwise arbitrary precision and range or
    computed by weighting.

    ROUNDED RECTANGLE COMMAND DETAILS

    In all the rounded-rectangle path commands, the parametric segment
    path equations in Table 5.pathEquations are expressed in terms of
    the function /rrect/ that returns an (x,y) position on the rounded
    rectangle when evaluated over the parametric range t=0..1.  /rrect/
    is a spline of alternating rational quadratic Bezier segments and
    linear segments that forms a closed contour.

    In addition to its parametric variable /t/, /rrect/ has 12
    parameters to which geometric properties can be ascribed when these
    values are positive.  (No restriction precludes these parameters
    to be non-positive; negative and zero values are allowed and
    supported.) (x,y) is the 2D location of the lower-left corner of the
    rectangle tightly bounding the rounded rectangle contour; /w/ and /h/
    are the respective width and height of the same bounding rectangle.
    /r_llx/, /r_lrx/, /r_urx/, and /r_ulx/ are the elliptical x-axis
    radii corresponding to the lower-left, lower-right, upper-right,
    and upper-left corners of the rounded rectangle; likewise /r_lly/,
    /r_lry/, /r_ury/, and /r_uly/ are the elliptical y-axis for the
    same corners.

    Equation 5.roundedRectangleContour

        rrect(x,y,             / (1-t_0)*C_ll + t_0*A_lr,                                   t=0/8..1/8
              w,h,             |
              r_llx,r_lly,     | (1-t_1)^2*A_lr + (1-t_1)*t_1*B_lr*sqrt(2) + t_1^2*C_lr)/
              r_lrx,r_lry,  =  < ((1-t_1)^2 + (1-t_1)*t_1*sqrt(2) + t_1^2),                 t=1/8..2/8
              r_urx,r_ury,     |
              r_ulx,r_uly,     | (1-t_2)*C_lr + t_2*A_ur,                                   t=2/8..3/8
              t)               |
                               | (1-t_3)^2*A_ur + (1-t_3)*t_3*B_ur*sqrt(2) + t_3^2*C_ur)/
                               | ((1-t_3)^2 + (1-t_3)*t_3*sqrt(2) + t_3^2),                 t=3/8..4/8
                               |
                               | (1-t_4)*C_ur + t_4*A_ul,                                   t=4/8..5/8
                               |
                               | (1-t_5)^2*A_ul + (1-t_5)*t_5*B_ul*sqrt(2) + t_5^2*C_ul)/
                               | ((1-t_5)^2 + (1-t_5)*t_5*sqrt(2) + t_5^2),                 t=5/8..6/8
                               |
                               | (1-t_6)*C_ul + t_6*A_ll,                                   t=6/8..7/8
                               |
                               | (1-t_7)^2*A_ll + (1-t_7)*t_7*B_ll*sqrt(2) + t_7^2*C_ll)/
                               \ ((1-t_7)^2 + (1-t_7)*t_7*sqrt(2) + t_7^2),                 t=7/8..1

    where

        t_i = 8*t - i

        A_ll = (x,y-r_lly), h<0
               (x,y+r_lly), otherwise
        B_ll = (x,y)
        C_ll = (x-r_llx,y), w<0
               (x+r_llx,y), otherwise

        A_lr = (x+w+r_lrx,y), w<0
               (x+w-r_lrx,y), otherwise
        B_lr = (x+w,y)
        C_lr = (x+w,y-r_lry), h<0
               (x+w,y+r_lry), otherwise

        A_ur = (x+w,y+h-r_ury*sign(h)), h<0
               (x+w,y+h-r_ury*sign(h)), otherwise
        B_ur = (x+w,y+h)
        C_ur = (x+w+r_urx,y+h), w<0
               (x+w-r_urx,y+h), otherwise

        A_ul = (x-r_ulx,y+h), w<0
               (x+r_ulx,y+h), otherwise
        B_ul = (x,y+h)
        C_ul = (x,y+h+r_uly), h<0
               (x,y+h-r_uly), otherwise

    Consider /t_i/ to be a subparmetric range within /t/ where /t_i/
    ranges over 0..1 for each spline segment of /rrect/.  The 2D control
    points /A_ll/ through /C_ul/ are shown in Figure 5.roundedRectangle,
    where /ll/, /lr/, /ur/, and /ul/ correspond to lower-left,
    lower-right, upper-right, and upper-left respectively.

    Figure 5.roundedRectangle:  Geometric interpretation of Equation
    5.roundedRectangleContour parameters.

                   _ r_ulx                       _ r_urx
                  / \                           / \
                 /   \C_ul                A_ur /   \
           B_ul .-----.-----------------------.-----. B_ur     \
               /|                                   |\         |
        r_uly < |                                   | > r_ury  |
               \|                                   |/         |
           A_ul .                                   . C_ur     |
                |                                   |          \
                |                                   |           > h
                |                                   |          /
                |                                   |          |
           A_ll .                                   . C_rl     |
               /|                                   |\         |
        r_lly < |                                   | > r_rly  |
               \|                                   |/         |
           B_ll .-----.-----------------------.-----. B_rl     /
         & (x,y) \   /C_ll                A_rl \   /
                  \_/                           \_/
                    r_llx                         r_rlx
                 \______________  __________________/
                                \/
                                 w

    Note that the ROUNDED_RECT*_NV commands degenerate to the RECT_NV
    command when all the radii are zero.

    PARTIAL ELLIPTICAL ARC COMMAND DETAILS

    In all the arc-based path commands, the parametric segment path
    equations in Table 5.pathEquations are expressed in terms of the
    functions /arc_x/ and /arc_y/.

    Equation 5.generalParametricArc

        arc_x(c,rv,rh,phi,theta1,dtheta,t) = cos(phi)*rh*cos(theta1+t*dtheta) -
                                             sin(phi)*rv*sin(theta1+t*dtheta) + c.x
        arc_y(c,rv,rh,phi,theta1,dtheta,t) = sin(phi)*rh*cos(theta1+t*dtheta) +
                                             cos(phi)*rv*sin(theta1+t*dtheta) + c.y

    This general form of a parametric partial elliptical arc computes
    (x,y) 2D positions on the arc as /t/ ranges from 0.0 to 1.0 inclusive.

    In addition to the varying /t/ parameter, these functions depend on
    a 2D (x,y) center position /c/, a horizontal ellipse radius /rh/,
    a vertical ellipse radius /rv/, a counterclockwise angle (in radians)
    of an ellipse with respect to the x-axis /phi/, /theta1/ is the angle
    (in radians) of the initial point on the partial arc, and /dtheta/
    is the difference between the angle (in radians) of the terminal
    point on the partial arc and /theta1/.  The larger of /rh/ and /rv/
    is the complete ellipse's major axis while the smaller of the two
    is the complete ellipse's minor axis.

    How these additional dependent parameters for /arc_x/ and /arc_y/
    are determined depends on the specific arc path command as
    detailed in Table 5.arcParameterSpecialization.  Before explaining
    how specific arc commands determine these dependent parameters,
    the following discussion develops a general scheme for converting
    general end-point representations of arcs to the partial elliptical
    arc segment representation of Equation 5.generalParametricArc.
    All the arc commands supported are specializations of this general
    end-point representation.  The general scheme is developed, specific
    arc commands are specified as special cases of the general end-point
    representation scheme for arcs.

    In general, consider seven scalar values (/x1/, /y1/, /x2/,
    /y2/, /phi/, /fA/, and /fS/) fully parameterizing a given partial
    elliptical arc:

        *   a 2D position (x1,y1) at the start of a partial elliptical
            arc segment

        *   a 2D position (x2,y2) at the end of a partial elliptical
            arc segment

        *   /phi/ is the angle (in radians) from the x-axis of the path
            space coordinate system to the x-axis of the axis-aligned ellipse

        *   /fA/ is a boolean (the "large arc" flag) that is true when
            the arc spans greater than 180 degrees; and otherwise false
            if the arc sweeps 180 degrees or less

        *   /fS/ is a boolean (the "sweep" flag) that is true when the
            arc sweeps in a counterclockwise direction in path space
            (so sweeps with increasing angles); and otherwise false
            when the arc sweeps in a clockwise direction (so sweeps with
            decreasing angles)

    Given this parameterization, the procedure below computes the /c/,
    /rv/, /rh/, /phi/, /theta1/, and /dtheta/ parameters to represent
    this same arc in the general parametric form of Equation
    5.generalParametricArc.

    Step 1:

       x1p =  cos(phi)*(x1-x2)/2 + sin(phi)*(y1-y2)/2
       y1p = -sin(phi)*(x1-x2)/2 + cos(phi)*(y1-y2)/2

    If /rh/, /rv/, and /phi/ are such that there is no solution
    (basically, the ellipse is not big enough to reach from (x1,y1)
    to (x2,y2), then the ellipse is scaled up uniformly until there
    is exactly one solution (until the ellipse is just big enough)
    in this manner:

       lambda = (x1p/rh)^2 + (y1p/rv)^2

               / rh,               lambda<=1
       rp.x = {
               \ rh*sqrt(lambda),  lambda>1

               / rv,               lambda<=1
       rp.y = {
               \ rv*sqrt(lambda),  lambda>1

    Step 2:

       cp.x = fsgn*sqrt((rp.x^2*rp.y^2 - rp.x^2*y1p^2 - rp.y^2*x1p^2) /
                        (rp.x^2*y1p^2 + rp.y^2*x1p^2)
                       ) * rp.x*y1p/rp.y
       cp.y = fsgn*sqrt((rp.x^2*rp.y^2 - rp.x^2*y1p^2 - rp.y^2*x1p^2) /
                        (rp.x^2*y1p^2 + rp.y^2*x1p^2)
                       ) * -rp.y*x1p/rp.x

    where

                / +1,  fA != fS
        fsgn = {
                \ -1,  fA = fS

    Step 3:

        c.x = cos(phi)*cp.x - sin(phi)*cyp + (x1+x2)/2
        c.y = sin(phi)*cp.x + cos(phi)*cyp + (y1+y2)/2

    In general, the angle between two vectors (u.x, u.y) and (v.x, v.y)
    can be computed as

                      / arcos(dot(u,v)/sqrt(dot(u,u))*sqrt(dot(v,v))),   u.x*v.y-u.y*v.x>=0
        angle(u,v) = {
                      \ -arcos(dot(u,v)/sqrt(dot(u,u))*sqrt(dot(v,v))),  u.x*v.y-u.y*v.x<0

    Step 4:

        theta1 = angle([1,0],
                       [(x1p-cp.x)/r.x,(y1p-cp.y)/r.y])
        dangle = angle([(x1p-cp.x)/r.x,(y1p-cp.y)/r.y],
                       [(-x1p-cp.x)/r.x,(-y1p-cp.y)/r.y])

                    / dangle - 2*Pi,  fS=false AND d>0
                   /
                  /   dangle,         fS=false AND d<=0
        dtheta = {
                  \   dangle,         fS=true  AND d>=0
                   \
                    \ dangle + 2*Pi,  fS=true  AND d<0

    The arc path commands allow arbitrary numeric values so when these
    values result in invalid or out-of-range parameters when the above
    steps are applied, the following further steps are taken to ensure
    well-defined behavior.

    If (x1,y1) and (x2,y2) are identical, then this is equivalent to
    omitting the arc segment entirely.

    If either of /rh/ or /rv/ is zero, the arc is treated as a straight
    line segment from (x1,y1) to (x2,y2).

    Table 5.arcParameterSpecialization now maps the coordinate values
    for each arc path command to the parameters of the arc end-point
    parameterization above from which the arc's parametric representation
    can be obtained.

    Table 5.arcParameterSpecialization: Arc Path Command

    Token                         (x1,y1)     rh         rv         phi          (x2,y2)              fA               fS
    ----------------------------  ----------  ---------  ---------  -----------  -------------------  ---------------  -------
    SMALL_CCW_ARC_TO_NV           cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  c[3],c[4]            false            true
    RELATIVE_SMALL_CCW_ARC_TO_NV  cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  cp.x+c[3],cp.y+c[4]  false            true
    SMALL_CW_ARC_TO_NV            cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  c[3],c[4]            false            false
    RELATIVE_SMALL_CW_ARC_TO_NV   cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  cp.x+c[3],cp.y+c[4]  false            false
    LARGE_CCW_ARC_TO_NV           cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  c[3],c[4]            true             true
    RELATIVE_LARGE_CCW_ARC_TO_NV  cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  cp.x+c[3],cp.y+c[4]  true             true
    LARGE_CW_ARC_TO_NV            cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  c[3],c[4]            true             false
    RELATIVE_SMALL_CW_ARC_TO_NV   cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  cp.x+c[3],cp.y+c[4]  true             false
    CIRCULAR_CCW_ARC_TO_NV        A.x,A.y     abs(c[2])  abs(c[2])  0            B.x,B.y              (c[4]-c[3])>180  true
    CIRCULAR_CW_ARC_TO_NV         A.x,A.y     abs(c[2])  abs(c[2])  0            B.x,B.y              (c[4]-c[3])>180  false
    CIRCULAR_TANGENT_ARC_TO_NV    C.x,C.y     abs(c[4])  abs(c[4])  0            D.x,D.y              false            num>=0
    ARC_TO_NV                     cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  c[5],c[6]            c[3]!=0          c[4]!=0
    RELATIVE_ARC_TO_NV            cp.x,cp.y   abs(c[0])  abs(c[1])  c[2]*Pi/180  cp.x+c[5],cp.y+c[6]  c[3]!=0          c[4]!=0

    where, for CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV,

        A = (c[0]+c[2]*cos(c[3]*Pi/180),
             c[1]+c[2]*sin(c[3]*Pi/180))

        B = (c[0]+c[2]*cos(c[4]*Pi/180),
             c[1]+c[2]*sin(c[4]*Pi/180))

    and C, D, and num, for CIRCULAR_TANGENT_ARC_TO_NV, are computed
    through the following steps:

    Step 1:  Compute two tangent vectors:

        d0.x = cp.x - c[0]
        d0.y = cp.y - c[1]
        d2.x = c[2] - c[0]
        d2.y = c[3] - c[1]

    Step 2:  Compute scaling factors for tangent vectors:

        num   = d0.y*d2.x - d2.y*d0.x
        denom = sqrt(dot(d0,d0)*dot(d2,d2)) - dot(d0,d2)

        dist = abs(c[4] * num/denom)

        l0 = dist/sqrt(dot(d0,d0)) * c[4]/abs(c[4])
        l2 = dist/sqrt(dot(d2,d2)) * c[4]/abs(c[4])

    Step 3:  Add scaled directions to the tangent vector intersection
    point:

             / (c[0],c[1]) + d0 * l0,  denom!=0 AND c[4]!=0
        C = {
             \ (c[0],c[1]),            denom==0 OR c[4]==0

             / (c[0],c[1]) + d2 * l2,  denom!=0 AND c[4]!=0
        D = {
             \ (c[0],c[1]),            denom==0 OR c[4]==0

    PATH OBJECT SPECIFICATION

    Path objects can be specified in one of four ways:

    1)  explicitly from an array of commands and corresponding
        coordinates,

    2)  from a string conforming to one of two supported grammars to
        specify a string,

    3)  from a glyph within a font face from a system font or font file,
        or

    4)  by linearly combining one or more existing path objects with
        mutually consistent command sequences to form a new path.

    In any situation where a path object is specified or re-specified,
    the command's parameters are re-initialized as discussed in section
    5.X.1.5 unless otherwise specified.  However modification of path
    commands and coordinates (section 5.X.1.4) does not modify path
    parameters.

    5.X.1.1 Explicit Path Specification

    The command

        void PathCommandsNV(uint path,
                            sizei numCommands, const ubyte *commands,
                            sizei numCoords, enum coordType,
                            const void *coords);

    specifies a new path object named /path/ where /numCommands/
    indicates the number of path commands, read from the array
    /commands/, with which to initialize that path's command sequence.
    These path commands reference coordinates read sequentially from the
    /coords/ array.  The type of the coordinates read from the /coords/
    array is determined by the /coordType/ parameter which must be
    one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT,
    otherwise the INVALID_ENUM error is generated.

    The /numCommands/ elements of the /commands/ array must be tokens
    or character in Table 5.pathCommands.  The command sequence matches
    the element order of the /commands/ array.  Each command references
    a number of coordinates specified by "Coordinate count" column of
    Table 5.pathCommands, starting with the first (zero) element of
    the /coords/ array and advancing by the coordinate count for each
    command.  If any of these /numCommands/ command values are not
    listed in the "Token" or "Character aliases" columns of Table
    5.pathCommands, the INVALID_ENUM error is generated.

    The INVALID_OPERATION error is generated if /numCoords/ does not
    equal the number of coordinates referenced by the command sequence
    specified by /numCommands/ and /commands/ (so /numCoords/ provides a
    sanity check that the /coords/ array is being interpreted properly).
    The error INVALID_VALUE is generated if either /numCommands/ or
    /numCoords/ is negative.

    If the PathCommandsNV command results in an error, the path object
    named /path/ is not changed; if there is no error, the prior contents
    of /path/, if /path/ was an existent path object, are lost and the
    path object name /path/ becomes used.

    5.X.1.2 String Path Specification

    The command

        void PathStringNV(uint path, enum format,
                          sizei length, const void *pathString);

    specifies a new path object named /path/ where /format/ must be
    either PATH_FORMAT_SVG_NV or PATH_FORMAT_PS_NV, in which case the
    /length/ and /pathString/ are interpreted according to grammars
    specified in sections 5.X.1.2.1 and 5.X.1.2.2 respectively.
    The INVALID_VALUE error is generated if /length/ is negative.

    If the PathStringNV command results in an error, the path object
    named /path/ is not changed; if there is no error, the prior contents
    of /path/, if /path/ was an existent path object, are lost and the
    path object name /path/ becomes used.

    5.X.1.2.1 Scalable Vector Graphics Path Grammar

    If the /format/ parameter of PathStringNV is PATH_FORMAT_SVG_NV,
    the /pathString/ parameter is interpreted as a string of ubyte ASCII
    characters with /length/ elements.

    This string must satisfy the "svg-path" production in the path
    grammar below.  This grammar is taken directly from the Scalable
    Vector Graphics (SVG) 1.1 (April 30, 2009) specification.

    The following notation is used in the Backus-Naur Form (BNF)
    description of the grammar for an SVG path string:

        * *: 0 or more
        * +: 1 or more
        * ?: 0 or 1
        * (): grouping
        * ()^n: grouping with n repetitions where n is explained subsequently
        * |: separates alternatives
        * double quotes surround literals
        * #x: prefixes an ASCII character value followed by hexadecimal
          digits
        * ..: means any of an inclusive range of ASCII characters, so
          '0'..'9' means any digit character

    The following is the grammar for SVG paths.

        svg-path:
            wsp* moveto-drawto-command-groups? wsp*
        moveto-drawto-command-groups:
            moveto-drawto-command-group
            | moveto-drawto-command-group wsp* moveto-drawto-command-groups
        moveto-drawto-command-group:
            moveto wsp* drawto-commands?
        drawto-commands:
            drawto-command
            | drawto-command wsp* drawto-commands
        drawto-command:
            closepath
            | lineto
            | horizontal-lineto
            | vertical-lineto
            | curveto
            | smooth-curveto
            | quadratic-bezier-curveto
            | smooth-quadratic-bezier-curveto
            | elliptical-arc
        moveto:
            ( "M" | "m" ) wsp* moveto-argument-sequence
        moveto-argument-sequence:
            coordinate-pair
            | coordinate-pair comma-wsp? lineto-argument-sequence
        closepath:
            ("Z" | "z")
        lineto:
            ( "L" | "l" ) wsp* lineto-argument-sequence
        lineto-argument-sequence:
            coordinate-pair
            | coordinate-pair comma-wsp? lineto-argument-sequence
        horizontal-lineto:
            ( "H" | "h" ) wsp* horizontal-lineto-argument-sequence
        horizontal-lineto-argument-sequence:
            coordinate
            | coordinate comma-wsp? horizontal-lineto-argument-sequence
        vertical-lineto:
            ( "V" | "v" ) wsp* vertical-lineto-argument-sequence
        vertical-lineto-argument-sequence:
            coordinate
            | coordinate comma-wsp? vertical-lineto-argument-sequence
        curveto:
            ( "C" | "c" ) wsp* curveto-argument-sequence
        curveto-argument-sequence:
            curveto-argument
            | curveto-argument comma-wsp? curveto-argument-sequence
        curveto-argument:
            coordinate-pair comma-wsp? coordinate-pair comma-wsp? coordinate-pair
        smooth-curveto:
            ( "S" | "s" ) wsp* smooth-curveto-argument-sequence
        smooth-curveto-argument-sequence:
            smooth-curveto-argument
            | smooth-curveto-argument comma-wsp? smooth-curveto-argument-sequence
        smooth-curveto-argument:
            coordinate-pair comma-wsp? coordinate-pair
        quadratic-bezier-curveto:
            ( "Q" | "q" ) wsp* quadratic-bezier-curveto-argument-sequence
        quadratic-bezier-curveto-argument-sequence:
            quadratic-bezier-curveto-argument
            | quadratic-bezier-curveto-argument comma-wsp?
                quadratic-bezier-curveto-argument-sequence
        quadratic-bezier-curveto-argument:
            coordinate-pair comma-wsp? coordinate-pair
        smooth-quadratic-bezier-curveto:
            ( "T" | "t" ) wsp* smooth-quadratic-bezier-curveto-argument-sequence
        smooth-quadratic-bezier-curveto-argument-sequence:
            coordinate-pair
            | coordinate-pair comma-wsp? smooth-quadratic-bezier-curveto-argument-sequence
        elliptical-arc:
            ( "A" | "a" ) wsp* elliptical-arc-argument-sequence
        elliptical-arc-argument-sequence:
            elliptical-arc-argument
            | elliptical-arc-argument comma-wsp? elliptical-arc-argument-sequence
        elliptical-arc-argument:
            nonnegative-number comma-wsp? nonnegative-number comma-wsp?
                number comma-wsp flag comma-wsp flag comma-wsp coordinate-pair
        coordinate-pair:
            coordinate comma-wsp? coordinate
        coordinate:
            number
        nonnegative-number:
            integer-constant
            | floating-point-constant
        number:
            sign? integer-constant
            | sign? floating-point-constant
        flag:
            "0" | "1"
        comma-wsp:
            (wsp+ comma? wsp*) | (comma wsp*)
        comma:
            ","
        integer-constant:
            digit-sequence
        floating-point-constant:
            fractional-constant exponent?
            | digit-sequence exponent
        fractional-constant:
            digit-sequence? "." digit-sequence
            | digit-sequence "."
        exponent:
            ( "e" | "E" ) sign? digit-sequence
        sign:
            "+" | "-"
        digit-sequence:
            digit
            | digit digit-sequence
        digit:
            "0".."9"
        wsp:
            (#x20 | #x9 | #xD | #xA)

    The processing of the BNF must consume as much of a given BNF
    production as possible, stopping at the point when a character
    is encountered which no longer satisfies the production.  Thus,
    in the string "M 100-200", the first coordinate for the "moveto"
    consumes the characters "100" and stops upon encountering the minus
    sign because the minus sign cannot follow a digit in the production
    of a "coordinate".  The result is that the first coordinate will be
    "100" and the second coordinate will be "-200".

    Similarly, for the string "M 0.6.5", the first coordinate of the
    "moveto" consumes the characters "0.6" and stops upon encountering
    the second decimal point because the production of a "coordinate"
    only allows one decimal point. The result is that the first coordinate
    will be "0.6" and the second coordinate will be ".5".

    The grammar allows the string to be empty (zero length).  This is
    not an error, instead specifies a path with no commands.

    Table 5.svgCommands maps productions in the grammar above to the
    path commands in Table 5.pathCommands; each such path command, with
    its corresponding coordinates, is added to the path command sequence
    of the path object.  Each production listed in Table 5.svgCommands
    consumes a number of coordinates consistent with the path command
    token's coordinate count listed in Table 5.pathCommands.  The
    "coordinate" and "nonnegative-number" productions convert to a numeric
    coordinate value in the obvious way.  The "flag" production converts
    "0" and "1" to numeric coordinate values zero and one respectively.

    Table 5.svgCommands: SVG Grammar Commands to Path Command Tokens

                                                           Grammar's prior
        Production                                         command character  Path command token
        -------------------------------------------------  -----------------  -------------------------------------
        moveto-argument-sequence                           "M"                MOVE_TO_NV
                                                           "m"                RELATIVE_MOVE_TO_NV
        closepath                                          "Z" or "z"         CLOSE_PATH_NV
        lineto-argument-sequence                           "L"                LINE_TO_NV
                                                           "l"                RELATIVE_LINE_TO_NV
        horizontal-lineto-argument-sequence                "H"                HORIZONTAL_LINE_TO_NV
                                                           "h"                RELATIVE_HORIZONTAL_LINE_TO_NV
        vertical-lineto-argument-sequence                  "V"                VERTICAL_LINE_TO_NV
                                                           "v"                RELATIVE_VERTICAL_LINE_TO_NV
        quadratic-bezier-curveto-argument                  "Q"                QUADRATIC_CURVE_TO_NV
                                                           "q"                RELATIVE_QUADRATIC_CURVE_TO_NV
        smooth-quadratic-bezier-curveto-argument-sequence  "T"                SMOOTH_QUADRATIC_CURVE_TO_NV
                                                           "t"                RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV
        curveto-argument                                   "C"                CUBIC_CURVE_TO_NV
                                                           "c"                RELATIVE_CUBIC_CURVE_TO_NV
        smooth-curveto-argument                            "S"                SMOOTH_CUBIC_CURVE_TO_NV
                                                           "s"                RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV
        elliptical-arc-argument                            "A"                ARC_TO_NV
                                                           "a"                RELATIVE_ARC_TO_NV

    If the string fails to satisfy the svg-path production, the path
    object named /path/ is not changed.  The production may not be
    satisfied for one of two reasons: either the grammar cannot be not
    satisfied by the string, or the grammar is satisfied but there still
    remain a non-zero number of characters in the string.  Neither
    failure to satisfy the production generates an error; instead the
    PATH_ERROR_POSITION_NV state is set to the character offset where the
    grammar was first not satisfied or where the grammar was exhausted.
    If the string was parsed successfully and the command did not generate
    an error, the PATH_ERROR_POSITION_NV state is set to negative one
    to indicate success.

    5.X.1.2.2 PostScript Path Grammar

    If the /format/ parameter of PathStringNV is PATH_FORMAT_PS_NV,
    the /pathString/ parameter is interpreted as a string of ubyte ASCII
    characters with /length/ elements.

    This string must satisfy the "ps-path" production in the path
    grammar below.  This grammar is parses path specified in PostScript's
    subgrammar for user paths specified by "PostScript Language Reference
    Manual" 3rd edition.

    The following is the grammar (using the same notation as section
    5.X.1.2.1) for PS paths with special support for binary encoding modes
    (as explained below):

        ps-path:
            ps-wsp* user-path? ps-wsp*
            | ps-wsp* encoded-path ps-wsp*
        user-path:
            user-path-cmd
            | user-path-cmd ps-wsp+ user-path
        user-path-cmd:
            setbbox
            | ps-moveto
            | rmoveto
            | ps-lineto
            | rlineto
            | ps-curveto
            | rcurveto
            | arc
            | arcn
            | arct
            | ps-closepath
            | ucache
        setbbox:
            numeric-value numeric-value numeric-value numeric-value setbbox-cmd
        setbbox-cmd:
            "setbbox"
            | #x92 #x8F
        ps-moveto:
            numeric-value numeric-value moveto-cmd
        moveto-cmd:
            "moveto"
            | #x92 #x6B
        rmoveto:
            numeric-value numeric-value rmoveto-cmd
        rmoveto-cmd:
            "rmoveto"
            | #x92 #x86
        ps-lineto:
            numeric-value numeric-value lineto-cmd
        lineto-cmd:
            "lineto"
            | #x92 #x63
        rlineto:
            numeric-value numeric-value rlineto-cmd
        rlineto-cmd:
            "rlineto"
            | #x92 #x85
        ps-curveto:
            numeric-value numeric-value numeric-value numeric-value numeric-value numeric-value curveto-cmd
        curveto-cmd:
            "curveto"
            | #x92 #x2B
        rcurveto:
            numeric-value numeric-value numeric-value numeric-value numeric-value numeric-value rcurveto-cmd
        rcurveto-cmd:
            "rcurveto"
            | #x92 #x7A
        arc:
            numeric-value numeric-value numeric-value numeric-value numeric-value arc-cmd
        arc-cmd:
            "arc"
            | #x92 #x05
        arcn:
            numeric-value numeric-value numeric-value numeric-value numeric-value arcn-cmd
        arcn-cmd:
            "arcn"
            | #x92 #x06
        arct:
            numeric-value numeric-value numeric-value numeric-value numeric-value arct-cmd
        arct-cmd:
            "arct"
            | #x92 #x07
        ps-closepath:
            "closepath"
            | #x92 #x16
        ucache:
            "ucache"
            | #x92 #xB1
        encoded-path:
            data-array ps-wsp* operator-string
        data-array:
            "{" ps-wsp* numeric-value-sequence? "}"
            | homogeneous-number-array
            | ascii85-homogeneous-number-array
        operator-string:
            hexadecimal-binary-string
            | ascii85-string
            | short-binary-string
            | be-long-binary-string
            | le-long-binary-string
        hexadecimal-binary-string:
            "<" ps-wsp-chars* hexadecimal-sequence ps-wsp-chars* ">"
        hexadecimal-sequence:
            hexadecimal-digit
            | hexadecimal-digit ps-wsp-chars* hexadecimal-sequence
        hexadecimal-digit:
            digit
            | "a".."f" |
            | "A".."F"
        short-binary-string:
            #x8E one-byte ( one-byte )^n
                /where n is the value of the one-byte production decoded
                 as an unsigned integer, 0 through 255/
        be-long-binary-string:
            #x8F two-bytes ( one-byte )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 big-endian byte order/
        le-long-binary-string:
            #x90 two-bytes ( one-byte )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 little-endian byte order/
        numeric-value-sequence:
            numeric-value:
            | numeric-value numeric-value-sequence
        numeric-value:
            number ps-wsp+
            | radix-number ps-wsp+
            | be-integer-32bit
            | le-integer-32bit
            | be-integer-16bit
            | le-integer-16bit
            | le-integer-8bit
            | be-fixed-16bit
            | le-fixed-16bit
            | be-fixed-32bit
            | le-fixed-32bit
            | be-float-ieee
            | le-float-ieee
            | native-float-ieee
        be-integer-32bit:
            #x84 four-bytes
        le-integer-32bit:
            #x85 four-bytes
        be-integer-16bit:
            #x86 two-bytes
        le-integer-16bit:
            #x87 two-bytes
        le-integer-8bit:
            #x88 one-byte
        be-fixed-32bit:
            #x89 #x0..#x1F four-bytes
        le-fixed-32bit:
            #x89 #x80..#x9F four-bytes
        be-fixed-16bit:
            #x89 #x20..#x2F two-bytes
        le-fixed-16bit:
            #x89 #xA0..#xAF two-bytes
        be-float-ieee:
            #x8A four-bytes
        le-float-ieee:
            #x8B four-bytes
        native-float-ieee:
            #x8C four-bytes
        radix-number:
            base "#" base-number
        base:
            digit-sequence
        base-number:
            base-digit-sequence
        base-digit-sequence:
            base-digit
            | base-digit base-digit-sequence
        base-digit:
            digit
            | "a".."z"
            | "A".."Z"
        homogeneous-number-array:
            be-fixed-32bit-array
            | be-fixed-16bit-array
            | be-float-ieee-array
            | native-float-ieee-array
            | le-fixed-32bit-array
            | le-fixed-16bit-array
            | le-float-ieee-array
        be-fixed-32bit-array:
            #x95 #x0..#x1F two-bytes ( four-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 big-endian byte order/
        be-fixed-16bit-array:
            #x95 #x20..#x2F two-bytes ( two-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 big-endian byte order/
        be-float-ieee-array:
            #x95 #x30 two-bytes ( four-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 big-endian byte order/
        le-fixed-32bit-array:
            #x95 #x80..#x9F two-bytes ( four-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 little-endian byte order/
        le-fixed-16bit-array:
            #x95 #xA0..#xAF two-bytes ( two-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 little-endian byte order/
        le-float-ieee-array:
            #x95 #xB0 two-bytes ( four-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 little-endian byte order/
        native-float-ieee-array:
            #x95 ( #x31 | #xB1 ) two-bytes ( four-bytes )^n
                /where n is the value of the two-bytes production decoded
                 as an unsigned integer, 0 through 65535, decoded in
                 the native byte order/
        ascii85-string:
            "<~" (#x21..#x75 | "z" | psp-wsp )* "~>"
        ascii85-homogeneous-number-array:
            "<~" (#x21..#x75 | "z" | psp-wsp )* "~>"
        one-byte:
            #x0..#xFF
        two-bytes:
            #x0..#xFF #x0..#xFF
        four-bytes:
            #x0..#xFF #x0..#xFF #x0..#xFF #x0..#xFF
        ps-wsp:
            ps-wsp-chars
            | ps-comment
        ps-wsp-chars:
            ( #x20 | #x9 | #xA | #xC | #xD | #x0 )
        ps-comment:
            "%" ( #0..#9 | #xB..#xC | #xE..#xFF )* ( #xD | #xA )

    This grammar is not technically a pure BNF because it uses binary
    encoded data to encode how many characters should be as part of
    several productions (short-binary-string, native-float-ieee-array,
    etc.).

    The processing of the BNF must consume as much of a given BNF
    production as possible, stopping at the point when a character
    is encountered which no longer satisfies the production.

    The grammar allows the string to be empty (zero length). This
    is not an error, instead specifies a path with no commands.

    Table 5.psCommands maps productions in the grammar above to the path
    commands in Table 5.pathCommands; each such path command, with its
    corresponding coordinates, is added to the path command sequence
    of the path object.  Each production listed in Table 5.svgCommands
    consumes a quantity of values, matched by the "number" production,
    consistent with the path command token's coordinate count listed
    in Table 5.pathCommands.  The "setbbox" and "ucache" products are
    matched but do not result in path commands.

    Table 5.psCommands: PS Grammar Commands to Path Command Tokens

        Production    Path command token
        ------------  --------------------------
        arc           CIRCULAR_CCW_ARC_TO_NV
        arcn          CIRCULAR_CW_ARC_TO_NV
        arct          CIRCULAR_TANGENT_ARC_TO_NV
        ps-closepath  CLOSE_PATH_NV
        ps-curveto    CUBIC_CURVE_TO_NV
        ps-lineto     LINE_TO_NV
        ps-moveto     MOVE_TO_NV
        rcurveto      RELATIVE_CUBIC_CURVE_TO_NV
        rlineto       RELATIVE_LINE_TO_NV
        rmoveto       RELATIVE_MOVE_TO_NV
        setbbox       -
        ucache        -

    The "number" production converts to a numeric coordinate value
    in the obvious way.  The "radix-number" production converts the
    base-n integer conversion of its "base-number" production using
    the base indicated by the base-10 integer conversion of its "base"
    production where the base /n/ must be within the range 2 to 26.
    The "base-number" is interpreted in base /n/; the "base-number"
    production must contain digits ranging from 0 to /n/-1; digits greater
    than 9 are represented by the letters A through Z (or a through z)
    for the values 10 through 35 respectively.

    The "encoded-path" production provides a compact and precise way
    to encode paths with the commands and coordinates decoupled.

    The "data-array" subproductions provide a sequence of coordinate
    values for the encoded path's commands.  The "data-array"
    subproduction provides a sequence of numbers that is used by the
    following "operator-string" production.

    The "operator-string" subproduction is interpreted as a sequence
    of encoded path commands, one command per byte generated by
    "operator-string"'s "binary-string" production.

    Each hexadecimal character in the "hexadecimal-binary-string"
    production is a nibble (a 4-bit quantity).  Each pair of characters
    is two nibbles and they form a byte with the first nibble
    representing the most signification bits of the byte.  If the
    "hexadecimal-binary-string" production contains an odd number of
    hexadecimal characters, "0" is assumed to be suffixed to make an
    even number of characters (so "A7C" would encode the bytes 167 for
    "A7" followed by 192 for "C" which is treated as "C0" for 192).
    Table 5.encodedPathOpcodes maps the values contained in the operator
    string to path commands.  Each command consumes from the coordinate
    array supplied by the "data-array" production a number of values
    for the command's coordinates equal to the path command token's
    coordinate count listed in Table 5.pathCommands.  If the value for
    an element of the operator string is between 12 and 32 inclusive,
    the grammar fails to parse at this point.  If the value /n/ of an
    element of the operator string is between 32 and 255, then this value
    /n/-32 is treated as a repetition count and is treated as if /n/-32
    repetitions of the next command are contained in the operator string
    instead and the appropriate number of coordinates are consumed from
    the associated sequence of coordinate values.

    Table 5.encodedPathOpcodes

        Opcode  Name
        ------  ---------
        0       setbbox
        1       moveto
        2       rmoveto
        3       lineto
        4       rlineto
        5       curveto
        6       rcurveto
        7       arc
        8       arcn
        9       arct
        10      closepath
        11      ucache

    The ASCII characters in the "ascii85-binary-string" production
    consists of a sequence of printable ASCII characters between the "<~"
    and "~>" delimiters.  This represents arbitrary binary data using
    an encoding technique that products a 4:5 expansion as opposed to
    the 1:2 expansion for the "hexadecimal-binary-string" production.
    This encoding is known as ASCII base-85.

    Binary data in the ASCII base-85 encoding are encoded in 4-tuples
    (groups of 4) each 4-tuple is used to produce a 5-type of ASCII
    characters.  If the binary 4-tuple is (b1,b2,b3,b4) and the encoded
    5-tuple is (c1,c2,c3,c4,c5), then the relation between them is:

       (b1 * 256^3) + (b2 * 256^2) + (b3 * 256^1) + b4 =
       (c1 * 256^4) + (c2 * 256^3) + (c3 * 256^2) + (c4 * 256^3) + c5

    The four bytes of binary data are interpreted as a base-256 number and
    then converted into a base-85 number.  The five "digits" of this number,
    (c1,c2,c3,c4,c5), are then converted into ASCII characters by adding 33,
    which is the ASCII code for '!', to each.  ASCII characters in the
    range '!' to 'u' are used, where '!' represented the value 0 and 'u'
    represents the value 84.  As a special case, if all five digits are
    zero, they must be represented by either a single 'z' instead of by
    '!!!!'.

    If the encoded sequence ends with a sequence of characters that is
    not an even multiple of 4, the last 1, 2, or 3 characters to produce
    a special final partial 5-tuple.  Given n (1, 2, or 3) bytes of final
    binary data, an encoder must first append 4-n zero bytes to make
    a complete 4-tuple.  Then, the encoder must encode the 4-tuple in
    the usual way, but without applying the 'z' special case.  Finally,
    the encoder must write the first n+1 bytes of the resulting 5-tuple.
    Those bytes are immediately followed by the "~>" terminal marker.

    This encoding scheme is reversible and the GL is responsible for
    converting the ASCII base-85 string into its corresponding binary
    data.  White space within an ASCII base-85 encoded string is ignored.

    The following conditions constitute encoding violations of the ASCII
    base-85 scheme:

        *   The value represented by a 5-tuple is greater than 2^32-1

        *   The 'z' value occurs in the middle of a 5-tuple.

        *   A final partial 5-tuple contains only one character.

    Any such encoding violation is a parsing error.

    Once the ASCII base-85 string is decoded, this sequence of bytes
    is treated as operator elements in the identical manner as the
    elements for the "hexadecimal-string" subproduction.  This means
    invalid opcodes are possible and are treated as parsing errors, and
    Valid opcodes and counts consume coordinates from the "data-array"
    production to generate path commands with associated coordinates.

    The "short-binary-string", "be-long-binary-string", and
    "le-long-binary-string" subproductions of "operator-string" are
    binary encodings of a sequence of operator string elements.

    The "short-binary-string" has a count from 0 to 255 supplied by its
    "one-byte" subproduction which indicates how many bytes follow.
    These remaining (unsigned) bytes generate the sequence of operator
    string elements.

    The "be-long-binary-string" has a count from 0 to 65535 supplied by
    its "two-byte" subproduction which indicates how many bytes follow.
    These remaining (unsigned) bytes generate the sequence of operator
    string elements.  The "two-byte" subproduction is converted to a
    count by multiplying the first unsigned byte by 256 and adding it
    to the second unsigned byte.

    The "le-long-binary-string" has a count from 0 to 65535 supplied by
    its "two-byte" subproduction which indicates how many bytes follow.
    These remaining (unsigned) bytes generate the sequence of operator
    string elements.  The "two-byte" subproduction is converted to a
    count by multiplying the second unsigned byte by 256 and adding it
    to the first unsigned byte.

    The "encoded-path" fails to parse if invalid opcodes are detected
    in the operator string or the sequence of numbers for coordinates
    is exhausted prematurely.

    If the string fails to satisfy the ps-path production, the path
    object named /path/ is not changed.  The production may not be
    satisfied for one of three reasons: the grammar cannot be not
    satisfied by the string, the string has invalid sequences (such
    as ASCII base-85 violations, exhausting the coordinate data in the
    "data-array" production, or invalid opcodes encountered in the
    "operator-string" production), or the grammar is satisfied but
    there still remain a non-zero number of characters in the string.
    None of these failures to satisfy the grammar generates an error;
    instead the PATH_ERROR_POSITION_NV state is set to the character
    offset where the grammar was first not satisfied, violated
    semantically, or where the grammar was exhausted.  If the string
    was parsed successfully and the command did not generate an error,
    the PATH_ERROR_POSITION_NV state is set to negative one to indicate
    success.

    If a parsing error occurs, the exact value assigned to the
    PATH_ERROR_POSITION_NV state variable is implementation-dependent
    (because the specifics of error position determination is difficult
    to specify) though the determined error location should be nearby
    the first error.

    5.X.1.3 Font Glyph Path Specification

    PATH GLYPHS FROM CHARACTER CODE SEQUENCE

    The command

        void PathGlyphsNV(uint firstPathName,
                          enum fontTarget,
                          const void *fontName,
                          bitfield fontStyle,
                          sizei numGlyphs, enum type,
                          const void *charcodes,
                          enum handleMissingGlyphs,
                          uint pathParameterTemplate,
                          float emScale);

    creates, if no error occurs, a range of path objects named from
    /firstPathName/ to /firstPathName/+/numGlyphs/-1 based on the
    font face indicated by /fontTarget/, /fontName/, and /fontStyle/
    and the sequence of /numGlyphs/ character codes listed in the
    /charcodes/ array, as interpreted based by the /type/ parameter.
    However each particular name in the range /firstPathName/ to
    /firstPathName/+/numGlyphs/-1 is specified as a new path object only
    if that name is not already in use as a path object; if a name is
    already in use, that named path object is silently left undisturbed.
    A path object name is also left undisturbed if the
    /handleMissingGlyphs/ parameter is SKIP_MISSING_GLYPH_NV and the
    character code for a given glyph corresponds to the font's missing
    glyph or the character code is otherwise not available.

    The error INVALID_VALUE is generated if /numGlyphs/ or /emScale/
    is negative.

    The /fontTarget/ parameter must be one of STANDARD_FONT_NAME_NV,
    SYSTEM_FONT_NAME_NV, or FILE_NAME_NV; otherwise the INVALID_ENUM
    error is generated.

    The /handleMissingGlyphs/ parameter must be one of
    SKIP_MISSING_GLYPH_NV or USE_MISSING_GLYPH_NV; otherwise the
    INVALID_ENUM error is generated.

    If /fontTarget/ is STANDARD_FONT_NAME_NV, then /fontName/ is
    interpreted as a nul-terminated 8-bit ASCII character string that
    must be one of the following strings: "Serif", "Sans", "Mono",
    or "Missing"; otherwise the INVALID_VALUE error is generated.
    These "Serif", "Sans", and "Mono" names respectively correspond to
    serif, sans-serif, and sans monospaced font faces with the intent
    that the font face matches the appearance, metrics, and kerning
    of the DejaVu fonts of the same names.  All implementations /must/
    support these font names for the STANDARD_FONT_NAME_NV target.

    For the STANDARD_FONT_NAME_NV targets with "Serif", "Sans", and
    "Mono", all implementations /must/ support the first 256 character
    codes defined by Unicode and the ISO/IEC 8859-1 (Latin-1 Western
    European) character encoding though implementations are strongly
    encouraged to support as much of the Unicode character codes as the
    system's underlying font and language support provides.

    For the STANDARD_FONT_NAME_NV targets with "Missing", the entire
    sequence of path objects must be populated with an identical box
    outline with metrics matching this box.

    If /fontTarget/ is SYSTEM_FONT_NAME_NV, then /fontName/ is interpreted
    as a nul-terminated 8-bit ASCII character string that corresponds to a
    system-specific font name.  These names are intended to correspond to
    the fonts names typically used in web content (e.g. Arial, Georgia,
    Times Roman, Helvetica).  The mapping of the system font character
    string to a system font is assumed to be performed by the GL server.

    If /fontTarget/ is FILE_NAME_NV, then /fontName/ is interpreted as
    a nul-terminated 8-bit ASCII character string that corresponds to
    a system-specific file name in a standard outline font format.
    The specific interpretation of this name depends on the system
    conventions for identifying files by name.  This name can be an
    absolute or relative path.  The name is expected to include the
    font name's extension.  The mapping of the font file name to a
    font is assumed to be performed by the GL client.  What font file
    formats are supported is system dependent but implementations are
    encouraged to support outline font formats standard to the system
    (e.g. TrueType for Windows systems, etc.).

    If the /fontTarget/ and /fontName/ combination can not be loaded for
    any reason (including the file name could not be opened, the font
    name is not available on the system, the font file format is not
    supported, the font file format is corrupted, etc.) and there is no
    other error generated, the command succeeds silently (so no error
    is generated) and the range of named path objects is not modified.
    If the named path objects did not exist previously, they continue
    to not exist.

    The /fontStyle/ parameter is a bitfield allowed to have the
    bits BOLD_BIT_NV or ITALIC_BIT_NV set; if other bits are set, the
    INVALID_VALUE error is generated.  The font style is used as a hint to
    indicate the style of the font face.  Glyphs are generated with the
    font's bold or italic style respectively (or combination thereof)
    if the BOLD_BIT_NV or ITALIC_BIT_NV bits are set; otherwise, the
    value 0 or NONE indicates the default font face style should be used
    to generate the requested glyphs.  In situations where the bold or
    italic style of the font is encoded in the font name or file name,
    the /fontStyle/ parameter is ignored.

    The generated glyphs for the path objects named /firstPathName/
    to /firstPathName/+/numGlyphs/-1 are specified by the /numGlyphs/
    character codes listed in the /charcodes/ array where each element of
    the array is determined by the /type/ parameter that must be one of
    UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT, UTF8_NV, UTF16_NV,
    2_BYTES, 3_BYTES, and 4_BYTES with the array accessed in the same
    manner as the CallLists command's /type/ and /lists/ parameters
    (though not offset by the display list base), but indicating character
    codes instead of display list names.

    The character codes from the /charcodes/ array are Unicode character
    codes if the font in question can map from the Unicode character
    set to the font's glyphs.  If the font has no meaningful mapping
    from Unicode, the font's standard character set is used instead
    of Unicode (e.g. a font filled with non-standard symbols).  For a
    font supporting a character set that can be mapped to the Unicode
    character set, a best effort should be made to map the specified
    character code from its Unicode character code interpretation to
    the closest appropriate glyph in the specified font.

    Path objects created from glyphs by PathGlyphsNV have their path
    object metric state initialized from the metrics of the glyph from
    which they were specified.  Section 6.X.3. ("Path Object Glyph
    Typographic Queries") explains how these metrics are queried and
    what their values mean.  While the per-glyph metrics are expected to
    vary from glyph to glyph within a font face, the per-font metrics
    are expected to be identical for every path object created from a
    given font name and font style combination.

    Metrics in font space of glyphs are scaled by a value /s/ that is the
    ratio of the /emScale/ parameter divided by the font's units per Em;
    if the /emScale/ parameter equals zero, treat /emScale/ as if it was
    identical to the font's units per Em such that /s/ is exactly 1.0.
    Each glyph's outline are also scaled by /s/.  The metric values /not/
    scaled by /s/ are GLYPH_HAS_KERNING_BIT_NV, FONT_UNITS_PER_EM_BIT_NV,
    FONT_HAS_KERNING_BIT_NV, and FONT_NUM_GLYPH_INDICES_BIT_NV (since
    these metric values are not specified in font units).

    The FONT_NUM_GLYPH_INDICES_BIT_NV metric value returns -1 for path
    objects created with the STANDARD_FONT_NAME_NV (as such fonts are
    not accessed by glyph index, only character point); otherwise, the
    value is number of glyphs indices for the font, whether or not the
    path object is created from a character point or glyph index.

    When unknown or missing character codes in a font face are specified
    and the /handleMissingGlyph/ parameter is USE_MISSING_GLYPHS_NV,
    this situation should be handled in a manner appropriate to the
    character code, font face, and implementation.  Typically this
    involves using the font's missing glyph for the unknown or missing
    character code.

    If the /pathParameterTemplate/ parameter names an existing path
    object, that path object's current parameters listed in Table
    5.pathParameters (excepting PATH_FILL_MODE_NV as explained in
    the following paragraph) are used to initialize the respective
    parameters of path objects specified by this command; otherwise
    if the /pathParameterTemplate/ path object name does not exist,
    the initial path parameters are used as specified by table 6.Y
    (without generating an error).

    Path objects created from glyphs by PathGlyphsNV have their
    PATH_FILL_MODE_NV parameter, as explained in Section 5.X.1.5 ("Path
    Parameter Specification"), initialized according to the fill
    conventions of the font outlines within the font (instead of the
    COUNT_UP_NV default for paths specified by means other than glyphs).
    This may be one of:  COUNT_UP_NV if the font's outline winding
    convention is counterclockwise and its outline filling assumes the
    non-zero winding rule; COUNT_DOWN_NV if the font's outline winding
    convention is clockwise and its outline filling assumes the non-zero
    winding rule; or INVERT if the font's outline filling assumes the
    even-odd winding rule.

    PATH GLYPHS FROM CHARACTER CODE RANGE

    The command

        void PathGlyphRangeNV(uint firstPathName,
                              enum fontTarget,
                              const void *fontName,
                              bitfield fontStyle,
                              uint firstGlyph,
                              sizei numGlyphs,
                              enum handleMissingGlyphs,
                              uint pathParameterTemplate,
                              float emScale);

    allows a sequence of character codes in a font face to specify a
    sequence of path objects and is equivalent to

        int *array = malloc(sizeof(int)*numGlyphs);
        if (array) {
          for (int i=0; i<numGlyphs; i++) {
            array[i] = i + firstGlyph;
          }
          PathGlyphsNV(firstPathName, fontTarget, fontName, fontStyle,
                       numGlyphs, INT, array,
                       handleMissingGlyphs, pathParameterTemplate, emScale);
          free(array);
        } else {
          // generate OUT_OF_MEMORY error
        }

    PATH GLYPHS FROM GLYPH INDEX RANGE

    Advanced shaping of text renders glyphs by per-font glyph indices
    (rather than Unicode code point).  The commands

        enum PathGlyphIndexArrayNV(uint firstPathName,
                                   enum fontTarget,
                                   const void *fontName,
                                   bitfield fontStyle,
                                   uint firstGlyphIndex,
                                   sizei numGlyphs,
                                   uint pathParameterTemplate,
                                   float emScale);

        enum PathMemoryGlyphIndexArrayNV(uint firstPathName,
                                         enum fontTarget,
                                         sizeiptr fontSize,
                                         const void *fontData,
                                         sizei faceIndex,
                                         uint firstGlyphIndex,
                                         sizei numGlyphs,
                                         uint pathParameterTemplate,
                                         float emScale);

    create, if successful and no error occurs, a range of path objects
    that correspond to an array of glyphs as ordered by glyph index in
    a font face.  PathGlyphIndexArrayNV loads the font data from a file
    name or system font name while PathMemoryGlyphIndexArrayNV loads
    the font data from a standard font format in system memory.

    The commands return the value FONT_GLYPHS_AVAILABLE_NV when
    successful; otherwise one of the following values is returned
    depending on the nature of the failure.  The unsuccessful command
    returns the value FONT_TARGET_UNAVAILABLE_NV if the implementation
    does not support a valid /fontTarget/, FONT_UNAVAILABLE_NV if
    the font is not available (e.g. does not exist on the system), or
    FONT_UNINTELLIGIBLE_NV if the font is available but cannot be loaded
    for some implementation-dependent reason.  FONT_UNAVAILABLE_NV will
    not be returned by PathMemoryGlyphIndexArrayNV because the font
    data is read from system memory.  If the command generates an error,
    that error's enum value will be returned.  For example, an invalid
    value for /fontTarget/ will return INVALID_ENUM.  While the return
    value indicates the error, the error will /also/ be generated in the
    conventional way so GetError will return it and error callbacks are
    generated normally.

    When successful, path names /firstPathName/ through
    /firstPathName+numGlyphs-1/ now are specified as path objects
    corresponding to the sequence of glyphs in the font indicated
    by /fontTarget/, /fontSize/, and /fontData/ for glyph indices
    from /firstGlyphIndex/ to /firstGlyphIndex+numGlyphs-1/ where
    /firstPathName/ corresponds to the glyph index /firstGlyphIndex/
    and onward sequentially.  If a glyph index does not correspond to an
    actual glyph index in the font format, the respective path object is
    left undisturbed.  (It is the application's responsibility to know
    the valid range of glyph indices for the font.)  When unsuccessful
    other than due to an OUT_OF_MEMORY error, no path objects are
    specified or otherwise modified.

    The path objects are created in the same manner described for
    PathGlyphsNV in section 5.X.1.3 (Font Glyph Path Specification)
    except the GLYPH_HAS_KERNING_BIT_NV and FONT_HAS_KERNING_BIT_NV
    metrics are always false (because GetPathSpacingNV applies to
    glyphs specified from Unicode code points).  In particular, the
    /pathParameterTemplate/ and /emScale/ parameters have the same
    interpretation as the PathGlyphsNV command.

    For the PathGlyphIndexArrayNV command, the /fontTarget/ parameter
    must be either SYSTEM_FONT_NAME_NV or FILE_NAME_NV; otherwise the
    INVALID_ENUM error is generated.  The /fontStyle/ parameter is
    a bitfield allowed to have the bits BOLD_BIT_NV or ITALIC_BIT_NV
    set; if other bits are set, the INVALID_VALUE error is generated.
    The interpretation of the /fontTarget/, /fontName/, and /fontStyle/
    parameters is identical to the interpretation described in section
    5.X.1.3 (Font Glyph Path Specification).

    For the PathMemoryGlyphIndexArrayNV command, /fontTarget/ must
    be STANDARD_FONT_FORMAT_NV; otherwise INVALID_ENUM is generated
    (and returned).  STANDARD_FONT_FORMAT_NV implies: /fontSize/ is
    the size of the memory storing the font data in memory; /fontData/
    is a pointer to the beginning of the font data; and /faceIndex/ is
    the index of the face within the font, typically specified as zero.

    The specific standard font formats supported by
    STANDARD_FONT_FORMAT_NV are implementation-dependent, but the TrueType
    format should be supported.  Magic numbers if the font memory data
    are expected to be used to identify the specific font format.

    The INVALID_VALUE error is generated if any of /fontSize/ or
    /faceIndex/ or /emScale/ are negative.

    [NOTE: PathGlyphIndexRangeNV is deprecated in favor of
    PathGlyphIndexArrayNV and PathMemoryGlyphIndexArrayNV.]

    The command

        enum PathGlyphIndexRangeNV(enum fontTarget,
                                   const void *fontName,
                                   bitfield fontStyle,
                                   uint pathParameterTemplate,
                                   float emScale,
                                   uint baseAndCount[2]);

    creates, if successful and no error occurs, a range of path objects
    that correspond to the complete range of glyphs as ordered by glyph
    index in a font face.

    The command returns the value FONT_GLYPHS_AVAILABLE_NV when
    successful; otherwise one of the following values is returned
    depending on the nature of the failure.  The unsuccessful command
    returns the value FONT_TARGET_UNAVAILABLE_NV if the implementation
    does not support a valid /fontTarget/, FONT_UNAVAILABLE_NV if
    the font is not available (e.g. does not exist on the system), or
    FONT_UNINTELLIGIBLE_NV if the font is available but cannot be loaded
    for some implementation-dependent reason.  If the command generates
    an error, that error's enum value will be returned.  For example, an
    invalid value for /fontTarget/ will return INVALID_ENUM.  While the
    return value indicates the error, the error will /also/ be generated
    in the conventional way so GetError will return it and error callbacks
    are generated normally.

    The /fontTarget/ parameter must be either SYSTEM_FONT_NAME_NV
    or FILE_NAME_NV; otherwise the INVALID_ENUM error is generated.
    The interpretation of the /fontTarget/ and /fontName/ parameters
    is identical to the interpretation described in section 5.X.1.3
    (Font Glyph Path Specification).

    The error INVALID_VALUE is generated if /emScale/ is negative.

    The /fontStyle/ parameter is a bitfield allowed to have the
    bits BOLD_BIT_NV or ITALIC_BIT_NV set; if other bits are set, the
    INVALID_VALUE error is generated.

    When successful, elements 0 and 1 of the /baseAndCount/ array
    parameter are written values /B/ and /N/ respectively where the
    path names /B/ through /B+N-1/ are previously unused (i.e. there
    are /N/ previously unused path object names starting at /B/) but
    now are specified as path objects corresponding to the complete set
    of glyphs in the font indicated by /fontTarget/ and /fontName/.
    When unsuccessful (including when any error, even OUT_OF_MEMORY,
    is generated by the command), elements 0 and 1 of the /baseAndCount/
    array parameter are both written to zero.

    The path objects are created in the same manner described for
    PathGlyphsNV in section 5.X.1.3 (Font Glyph Path Specification)
    except the GLYPH_HAS_KERNING_BIT_NV and FONT_HAS_KERNING_BIT_NV
    metrics are always false (because GetPathSpacingNV applies to
    glyphs specified from Unicode code points).  In particular, the
    /pathParameterTemplate/ and /emScale/ parameters have the same
    interpretation as the PathGlyphsNV command.

    5.X.1.4 Path Modification

    Several commands allow the commands and/or coordinates of an existing
    path object to be modified.

    The command

        void PathCoordsNV(uint path,
                          sizei numCoords, enum coordType,
                          const void *coords);

    replaces all the coordinates of an existing path object with a new
    set of coordinates.  /path/ names the path object to modify; the
    error INVALID_OPERATION is generated if /path/ is not an existing
    path object.

    The new path coordinates are read sequentially from the
    /coords/ array.  The type of the coordinates read from the /coords/
    array is determined by the /coordType/ parameter which must be
    one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT,
    otherwise the INVALID_ENUM error is generated.

    The INVALID_OPERATION error is generated if /numCoords/ does not
    equal the number of coordinates referenced by the path object's
    existing command sequence (so /numCoords/ provides a sanity check
    that the /coords/ array is being interpreted properly).  The error
    INVALID_VALUE is generated if /numCoords/ is negative.

    If the PathCoordsNV command results in an error, the path object named
    /path/ is not changed; if there is no error, the prior coordinates of
    /path/ are lost.  If there is no error, the commands and parameters
    of the path object are not changed.

    The command

        void PathSubCoordsNV(uint path,
                             sizei coordStart,
                             sizei numCoords, enum coordType,
                             const void *coords);

    replaces a range of the coordinates of an existing path object with
    a new set of coordinates.  /path/ names the path object to modify;
    the error INVALID_OPERATION is generated if /path/ is not an existing
    path object.

    The new path coordinates are read sequentially from the
    /coords/ array.  The type of the coordinates read from the /coords/
    array is determined by the /coordType/ parameter which must be
    one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT,
    otherwise the INVALID_ENUM error is generated.

    The coordinates from the /coords/ array replace the coordinates
    starting at coordinate index (zero-based) /coordStart/ through
    /coordStart/+/numCoords/-1 inclusive in the existing path object's
    coordinate array.  If /numCoords/ is zero, no coordinates are changed.
    If /coordStart/+/numCoords/ is greater than the number of coordinates
    in the existing path object, the INVALID_OPERATION error is generated.
    If either /coordStart/ or /numCoords/ is negative, the INVALID_VALUE
    error is generated.

    If the PathCoordsNV command results in an error, the path object named
    /path/ is not changed; if there is no error, the prior coordinates
    within the updated range of /path/ are lost.  If there is no error,
    the commands, coordinates outside the updated range, and parameters
    of the path object are not changed.

    The command

        void PathSubCommandsNV(uint path,
                               sizei commandStart, sizei commandsToDelete,
                               sizei numCommands, const ubyte *commands,
                               sizei numCoords, enum coordType,
                               const void *coords);

    replaces a range of existing commands and their associated coordinates
    with a new sequence of commands and associated coordinates.  /path/
    names the path object to modify; the error INVALID_OPERATION is
    generated if /path/ is not an existing path object.

    The error INVALID_OPERATION is generated if any of /commandStart/,
    /commandsToDelete/, /numCommands/, or /numCoords/ is negative.

    The PathSubCommandsNV command works in two steps.
    First, deleting commands in the range /commandStart/ to
    /commandStart/+/commandsToDelete/-1 inclusive from the existing
    path object.  If /commandsToDelete/ exceeds the number of commands
    from /commandStart/ to the end of the path command sequence,
    all the commands from /commandsToDelete/ on are deleted.  This
    includes deleting the coordinates associated with these commands.
    If /commandsToDelete/ is zero, zero commands and zero coordinates are
    deleted.  Second, /numCommands/ read sequentially from the /commands/
    array are inserted into the existing path object immediately before
    index /commandStart/.  This includes inserting a corresponding number
    of coordinates from the /coords/ array.  If the index /commandStart/
    is greater than the largest valid command index of the path object,
    the commands are simply appended to the end of the path objects
    command and coordinate sequences.

    Each of the /numCommands/ commands in the /command/ array references
    a number of coordinates specified by "Coordinate count" column of
    Table 5.pathCommands, starting with the first (zero) element of
    the /coords/ array and advancing by the coordinate count for each
    command.  If any of these /numCommands/ commands are not listed
    in the "Token" or "Character aliases" columns of Table 5.pathCommands,
    the INVALID_ENUM error is generated.

    The INVALID_OPERATION error is generated if /numCoords/ does not equal
    the number of coordinates referenced by the command sequence to insert
    as specified by /numCommands/ and /commands/ (so /numCoords/ provides
    a sanity check that the /coords/ array is being interpreted properly).
    The error INVALID_VALUE is generated if any of /commandStart/,
    /commandsToDelete/, /numCommands/ or /numCoords/ are negative.

    The type of the coordinates in the /coords/ array is specified
    by /coordType/ and must be one of BYTE, UNSIGNED_BYTE, SHORT,
    UNSIGNED_SHORT, or FLOAT; otherwise the INVALID_ENUM error is
    generated.

    If the PathSubCommandsNV command results in an error, the path
    object named /path/ is not changed; if there is no error, the prior
    (now deleted) commands and coordinates within the updated range of
    /path/ are lost.  If there is no error, the commands, coordinates
    outside the deleted range, and parameters of the path object are not
    changed though commands and coordinates indexed beyond /commandStart/
    are shifted in their sequence within the path object to make room
    in the command and coordinate arrays for the newly inserted commands
    and coordinates.

    5.X.1.5 Path Parameter Specification

    Each path object has its own set of path parameters that control
    how the path object is filled and stroked when stenciled and covered.

    Table 5.pathParameters

        Name                             Type     Required Values or Range
        -------------------------------  -------  -----------------------------------------------
        PATH_STROKE_WIDTH_NV             float    non-negative
        PATH_INITIAL_END_CAP_NV          enum     FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV
        PATH_TERMINAL_END_CAP_NV         enum     FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV
        PATH_INITIAL_DASH_CAP_NV         enum     FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV
        PATH_TERMINAL_DASH_CAP_NV        enum     FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV
        PATH_JOIN_STYLE_NV               enum     MITER_REVERT_NV, MITER_TRUNCATE_NV, BEVEL_NV, ROUND_NV, NONE
        PATH_MITER_LIMIT_NV              float    non-negative
        PATH_DASH_OFFSET_NV              float    any value
        PATH_DASH_OFFSET_RESET_NV        enum     MOVE_TO_RESET_NV, MOVE_TO_CONTINUES_NV
        PATH_CLIENT_LENGTH_NV            float    non-negative
        PATH_FILL_MODE_NV                enum     COUNT_UP_NV, COUNT_DOWN_NV, INVERT
        PATH_FILL_MASK_NV                integer  any value
        PATH_FILL_COVER_MODE_NV          enum     CONVEX_HULL_NV, BOUNDING_BOX_NV
        PATH_STROKE_COVER_MODE_NV        enum     CONVEX_HULL_NV, BOUNDING_BOX_NV
        PATH_STROKE_MASK_NV              integer  any value
        PATH_STROKE_BOUND_NV             float    any value in [0.0,1.0]

    The commands

        void PathParameterivNV(uint path, enum pname, const int *value);
        void PathParameteriNV(uint path, enum pname, int value);
        void PathParameterfvNV(uint path, enum pname, const float *value);
        void PathParameterfNV(uint path, enum pname, float value);

    specify the value of path parameters for the specified path object
    named /path/.  The error INVALID_OPERATION is generated if /path/
    is not an existing path object.

    Each parameter has a single (scalar) value.

    /pname/ must be one of the tokens in the "Name" column of
    Table 5.pathParameters, PATH_END_CAPS_NV, or PATH_DASH_CAPS_NV.
    The required values or range of each allowed parameter name token
    is listed in Table 5.pathParameter's "Required Values/Range" column.

    For values of /pname/ listed in Table 5.pathsParameters, the specified
    parameter is specified by /value/ when /value/ is a float or int,
    or if /value/ is a pointer to a float or int, accessed through that
    pointer.  The error INVALID_VALUE is generated if the specified
    value is negative for parameters required to be non-negative in
    Table 5.pathParameters.  Values specified to be clamped to the [0,1] range
    in Table 5.pathParameters are so clamped prior to setting the
    specified path parameter to that clamped value.

    The /pname/ of PATH_END_CAPS_NV is handled specially and updates
    /both/ the PATH_INITIAL_END_CAP_NV and PATH_TERMINAL_END_CAP_NV
    parameters of the path with the specified value.  The /pname/
    of PATH_DASH_CAPS_NV is handled specially and updates /both/ the
    PATH_INITIAL_DASH_CAP_NV and PATH_TERMINAL_DASH_CAP_NV parameters
    of the path with the specified value.

    The error INVALID_VALUE is generated if the specified parameter value
    is not within the require range for parameters typed float or integer.
    The error INVALID_ENUM is generated if the specified parameter value
    is not one of the listed tokens for parameters typed enum.

    The dash pattern of a path object consists of a sequence of path-space
    lengths of alternating "on" and "off" dash segments.  The first
    value of the dash array defines the length, in path space, of the
    first "on" dash segment.  The second value defines the length of the
    following "off" segment.  Each subsequent pair of values defines one
    "on" and one "off" segment.

    Parameters to control the dash pattern of a stroked path are specified
    by the command

        void PathDashArrayNV(uint path,
                             sizei dashCount, const float *dashArray);

    where /path/ is the name of an existing path object.  The error
    INVALID_OPERATION is generated if /path/ is not an existing path
    object.

    A /dashCount/ of zero indicates the path object is not dashed; in
    this case, the /dashArray/ is not accessed.  Otherwise, /dashCount/
    provides a count of how many float values to read from the /dashArray/
    array.  If any of the /dashCount/ elements of /dashArray/ are
    negative, the INVALID_VALUE error is generated.

    If /dashCount/ is negative, the INVALID_VALUE error is generated.

    If an error occurs, the path object's existing dash pattern state
    is not changed.

    The path parameters of a newly specified path object are initialized
    as specified in Table 6.Y.

    5.X.1.6 Path Weighting, Interpolation, and Copying

    The command

        void WeightPathsNV(uint resultPath,
                           sizei numPaths,
                           const uint paths[], const float weights[]);

    linearly combines, as appropriate, the /numPaths/ path objects in
    the array paths based on each path object's respective weight from
    the weights array.  The resulting path creates or replaces the
    path object /resultPath/.  The INVALID_VALUE error is generated if
    /numPaths/ is less than one.

    If the /resultPath/ name also names one of the paths in the /paths/
    array, the path resulting from the linear combination of paths
    replaces the source path also named /resultPath/ but not until after
    the linear combination path has been determined.

    This command requires all the paths in the paths array to
    be /consistent/; otherwise the INVALID_OPERATION error is
    generated.  For all the paths to be /consistent/, all /numPaths/ paths
    in the /paths/ array must have the identical count of commands and
    each corresponding /i/th command in each path must have the identical
    command type.

    However the arc commands (specifically SMALL_CCW_ARC_TO_NV,
    RELATIVE_SMALL_CCW_ARC_TO_NV, SMALL_CW_ARC_TO_NV,
    RELATIVE_SMALL_CW_ARC_TO_NV, LARGE_CCW_ARC_TO_NV,
    RELATIVE_LARGE_CCW_ARC_TO_NV, LARGE_CW_ARC_TO_NV,
    RELATIVE_LARGE_CW_ARC_TO_NV, CIRCULAR_CCW_ARC_TO_NV,
    CIRCULAR_CW_ARC_TO_NV, CIRCULAR_TANGENT_ARC_TO_NV, ARC_TO_NV, and
    RELATIVE_ARC_TO_NV) can not be weighted because the linear combination
    of the curves these arc commands generate do not generally result in
    a command of the same form; so if any of these arc commands appears
    in a path object passed to WeightPathsNV the INVALID_OPERATION error
    is generated.

    The weighted path has a command sequence identical to any of the
    input path objects to be weighted (since all the input path command
    sequences are required to be identical).

    The weighted path has a coordinate sequence constructed by weighting
    each correspondingly indexed coordinate /i/ for all paths indexed by
    /j/ from zero to /numPaths/-1 in the /paths/ array.  Each coordinate
    /i/ from path /j/ is weighted by the weight in /weights/ indexed
    by /j/.

    The path parameters for the weighted path are copied from the path
    named by the first (0th) element of the /paths/ array.  The path
    metric values (as queried by GetPathMetricsNV in section 6.X.3)
    are all specified to be -1 for the newly specified path object
    (ignoring the path metrics for all the input path objects).
    Kerning information (as queriable by GetPathSpacingNV in section
    6.X.3) is also not copied.

    The command

        void InterpolatePathsNV(uint resultPath,
                                uint pathA, uint pathB,
                                float weight);

    is equivalent to

        uint paths[2] = { pathA, pathB };
        float weights[2] = { 1-weight, weight };
        WeightPathsNV(resultPath, 2, paths, weights);

    The command

        void CopyPathNV(uint resultPath, uint srcPath);

    copies the path object named /srcPath/ to the path object named
    /resultPath/.  The error INVALID_OPERATION is generated if /srcPath/
    does not exist.  The outline (commands and coordinates), parameters,
    and glyph metrics and kerning information (if they exist) are all
    copied without change.

    5.X.1.7 Path Transformation

    The command

        void TransformPathNV(uint resultPath,
                             uint srcPath,
                             enum transformType,
                             const float *transformValues);

    transforms the path object named /srcPath/ by the transform specified
    by the /transformType/ and its associated /transformValues/.
    The resulting path creates or replaces the path object /resultPath/.

    If the /resultPath/ and /srcPath/ names are identical, the path resulting
    from the transform replaces the name after the source path is transformed.

    The /transformType/ must be one of NONE, TRANSLATE_X_NV,
    TRANSLATE_Y_NV, TRANSLATE_2D_NV, TRANSLATE_3D_NV, AFFINE_2D_NV,
    AFFINE_3D_NV, TRANSPOSE_AFFINE_2D_NV, or TRANSPOSE_AFFINE_3D_NV.

        transformType               Matrix
        --------------------------  -------------------------
        NONE                        [   1   0   0   0 ]
                                    [   0   1   0   0 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        TRANSLATE_X_NV              [   1   0   0  v0 ]
                                    [   0   1   0   0 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        TRANSLATE_Y_NV              [   1   0   0   0 ]
                                    [   0   1   0  v0 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        TRANSLATE_2D_NV             [   1   0   0  v0 ]
                                    [   0   1   0  v1 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        TRANSLATE_3D_NV             [   1   0   0  v0 ]
                                    [   0   1   0  v1 ]
                                    [   0   0   1  v2 ]
                                    [   0   0   0   1 ]

        AFFINE_2D_NV                [  v0  v2   0  v4 ]
                                    [  v1  v3   0  v5 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        TRANSPOSE_AFFINE_2D_NV      [  v0  v1   0  v2 ]
                                    [  v3  v4   0  v5 ]
                                    [   0   0   1   0 ]
                                    [   0   0   0   1 ]

        AFFINE_3D_NV                [  v0  v3  v6  v9 ]
                                    [  v1  v4  v7 v10 ]
                                    [  v2  v5  v8 v11 ]
                                    [   0   0   0   1 ]

        TRANSPOSE_AFFINE_3D_NV      [  v0  v1  v2  v3 ]
                                    [  v4  v5  v6  v7 ]
                                    [  v8  v9 v10 v11 ]
                                    [   0   0   0   1 ]

    Table 5.transformType:  Mapping from /transformType/ to a 4x4
    transform matrix where v/i/ is the ith (base 0) element of the
    /transformValues/ array.

    The transformation of a path proceeds path command by path command.
    Each path command results in a transformed path command equivalent
    to what would happen if every point on the path command segment were
    transformed by the transform from Table 5.transformType and had a
    projective normalization applied.

    Commands with absolute control points have their control points
    transformed by the effective 4x4 projective matrix, and the resulting
    x & y coordinates serve as the transformed command's respective
    control point.

    Control points of relative commands are first made into absolute
    coordinates given the command's current control point, transformed
    in the same manner as an absolute control point, and then adjusted
    back to relative to their transformed current control point.

    Horizontal and vertical line to commands are promoted to corresponding
    "line to" commands if the transformed command is not an exactly
    horizontal or vertical command respectively after transformation;
    otherwise, these commands are not promoted but may transition from
    horizontal to vertical or vice versa as the case may be.

    Commands for partial elliptical arcs generate an equivalent new
    transformed arc.

    XXX more detail/math about arcs?

    The CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV commands are
    converted to transformed *_ARC_TO_NV commands if the transformed
    circular arc is itself not a circular arc.

    The CIRCULAR_TANGENT_ARC_TO_NV command is converted into a LINE_TO_NV
    command and *_ARC_TO_NV command if the transformed circular arc is
    itself not a circular arc.

    The CLOSE_PATH_NV and RESTART_PATH_NV (having no control points)
    are undisturbed by path transformation.  The order of path commands
    is invariant under path transformation.

    5.X.1.8  Path Name Management

    The command

        uint GenPathsNV(sizei range);

    returns an integer /n/ such that names /n/, ..., /n+range-1/ are
    previously unused (i.e. there are /range/ previously unused path object
    names starting at /n/).  These names are marked as used, for the
    purposes of subsequent GenPathsNV only, but they do not acquire
    path object state until each particular name is used to specify
    a path object.

    Path objects are deleted by calling

        void DeletePathsNV(uint path, sizei range);

    where /path/ contains /range/ names of path objects to be delete.
    After a path object is deleted, its name is again unused.  Unused
    names in /paths/ are silently ignored.

    The query

        boolean IsPathNV(uint path);

    returns TRUE if /path/ is the name of a path object.  If path is
    not the name of a path object, or if an error condition occurs,
    IsPathNV returns FALSE.  A name retuned by GenPathsNV, but without
    a path specified for it yet, is not the name of a path object.

    5.X.2 Path Rendering

    Path objects update the framebuffer through one of two processes:
    "stenciling" that updates /just/ the stencil buffer with the path's
    coverage information, and "covering" that rasterizes fragments into
    the framebuffer for a region guaranteed to cover the region of path
    coverage updated by stenciling, assuming the same path object,
    fill mode or stroking parameters, transformation state, and set of
    accessible samples (as will be explained).

    5.X.2.1 Path Stenciling

    STENCILING FILLED PATHS

    The command

        void PathStencilFuncNV(enum func, int ref, uint mask);

    configures the stencil function, stencil reference value, and stencil
    read mask to be used by the StencilFillPathNV and StencilStrokePathNV
    commands described subsequently.  The parameters accept the same
    values allowed by the StencilFunc command.

    The command

        void PathStencilDepthOffsetNV(float factor, float units);

    configures the depth offset factor and units state (see section 3.6.4)
    to be used by the StencilFillPathNV and StencilStrokePathNV commands
    described subsequently.

    The command

        void StencilFillPathNV(uint path,
                               enum fillMode, uint mask);

    transforms into window space the outline of the path object named
    /path/ based on the current modelview, projection, viewport,
    and depth range transforms (ignoring any vertex and/or geometry
    shader or program that might be active/enabled) and then updates
    the stencil values of all /accessible samples/ (explained below) in
    the framebuffer.  Each sample's stencil buffer value is updated based
    on the winding number of that sample with respect to the transformed
    outline of the path object with any non-closed subpath forced closed
    and the specified /fillMode/.

    If /path/ does not name an existing path object, the command does
    nothing (and no error is generated).

    If the path's command sequence specifies unclosed subpaths (so not
    contours) due to MOVE_TO_NV commands, such subpaths are trivially
    closed by connecting with a line segment the initial and terminal
    control points of each such path command subsequence.

    Transformation of a path's outline works by taking all positions
    on the path's outline in 2D path space (x,y) and constructing an
    object space position (x,y,0,1) that is then used as the (xo,yo,zo,wo)
    position in section 2.12 ("Fixed-Function Vertex Transformation")
    to compute corresponding eye-space coordinates (xe,ye,ze,we) and
    clip-space coordinates (xc,yc,zc,wc).  A path outline's clip-space
    coordinates are further transformed into window space as described in
    section 2.16 ("Coordinate Transformations").  This process provides a
    mapping 2D path coordinates to 2D window coordinates and depth values.
    The resulting 2D window coordinates are undefined if any of the
    transformations involved are singular or may be inaccurate if any
    of the transformations (or their combination) are ill-conditioned.

    The winding number for a sample with respect to the path outline,
    transformed into window space, is computed by counting the (signed)
    number of revolutions around the sample point when traversing each
    (trivially closed if necessary) contour once in the transformed path.
    This traversal is performed in the order of the path's command
    sequence.  Starting from an initially zero winding count, each
    counterclockwise revolution when the front face mode is CCW (or
    clockwise revolution when the front face mode is CW) around the sample
    point increments the winding count by one; while each clockwise
    revolution when the front face mode is CCW (or counterclockwise
    revolution when the front face mode is CW) around the sample point
    decrements the winding count by one.

    The /mask/ parameter controls what subset of stencil bits are affected
    by the command.  If the /mask/ parameter is zero, the path object's
    fill mask parameter (PATH_FILL_MASK_NV) is considered the effective
    value of /mask/.

    The /fillMode/ parameter must be one of INVERT, COUNT_UP_NV,
    COUNT_DOWN_NV, or PATH_FILL_MODE_NV; otherwise the INVALID_ENUM error
    is generated.  INVERT inverts the bits set in the effective /mask/
    value for each sample's stencil value if the winding number for the
    given sample is odd.  COUNT_UP_NV adds with modulo n arithmetic the
    winding number of each sample with the sample's prior stencil buffer
    value; the result of this addition is written into the sample's
    stencil value but the bits of the stencil value not set in the
    effective /mask/ value are left unchanged.  COUNT_DOWN_NV subtracts
    with modulo /n/ arithmetic the winding number of each sample with the
    sample's prior stencil buffer value; the result of this subtraction is
    written into the sample's stencil value but the bits of the stencil
    value not set in the effective /mask/ value are left unchanged.
    PATH_FILL_MODE_NV uses the path object's counting mode parameter
    (one of INVERT, COUNT_UP_NV, or COUNT_DOWN_NV).

    The value of /n/ for the modulo /n/ arithmetic used by COUNT_UP_NV
    and COUNT_DOWN_NV is the effective /mask/+1.  The error INVALID_VALUE
    is generated if the specified /fillMode/ is COUNT_UP_NV or
    COUNT_DOWN_NV and the specified /mask/+1 is not an integer power
    of two.  If the /fillMode/ is PATH_FILL_MODE_NV; the path object's
    counting mode parameter is COUNT_UP_NV or COUNT_DOWN_NV; and the
    effective mask+1 value is not an integer power of two, treat the
    mask as zero (effectively meaning no stencil bits will be modified).

    ACCESSIBLE SAMPLES WITH RESPECT TO A TRANSFORMED PATH

    The accessible samples of a transformed path that are updated are
    the samples that remain after discarding the following samples:

        *   Any sample that would be clipped as specified in section 2.22
            ("Primitive Clipping") because its corresponding position in
            clip space (xc,yc,zc,wc) or (xe,ye,ze,we) would be clipped
            by the clip volume or enabled client-defined clip planes.

        *   Any sample that would not be updated during polygon rendering
            due to polygon stipple (section 3.6.2) if POLYGON_STIPPLE
            is enabled.

        *   Any sample that would fail the pixel ownership test (section
            4.1.1) if rasterized.

        *   Any sample that would fail the scissor test (section 4.1.2)
            if SCISSOR_TEST is enabled.

        *   Any sample that would fail the depth test (section 4.1.6)
            if DEPTH_TEST is enabled where the fragment depth for the
            depth test comes from the depth plane of the path when
            transformed by the modelview, projection, viewport, and
            depth range transforms and depth offset (section 3.6.4)
            has been applied based on the slope of this plane operating
            as if POLYGON_OFFSET_FILL is forced enabled and using the
            factor and units parameters set by PathStencilDepthOffsetNV
            (rather than the state set by PolygonOffset).

        *   Any sample that would fail the depth bounds test (section
            4.1.X in EXT_depth_bounds_test specification) if
            DEPTH_BOUNDS_TEST_EXT is enabled.

    And for the StencilFillPathNV and StencilStrokePathNV commands (so
    not applicable to the CoverFillPathNV and CoverStrokePathNV commands):

        *   Any sample that would fail the (implicitly enabled) stencil
            test (section 4.1.5) with the stencil function configured
            based on the path stencil function state configured by
            PathStencilFuncNV.  In the case of the StencilFillPathNV
            and StencilStrokePathNV commands and their instanced
            versions (section 5.X.2.3), the effective stencil read
            mask for the stencil mask is treated as the value of
            PATH_STENCIL_VALUE_MASK bit-wise ANDed with the bit-invert
            of the effective /mask/ parameter value; otherwise, for the
            cover commands, the stencil test operates normally.  In the
            case the stencil test fails during a path stencil operation,
            the stencil fail operation is ignored and the pixel's stencil
            value is left undisturbed (as if the stencil operation was
            KEEP).

        *   The state of the face culling (CULL_FACE) enable is ignored.

    STENCILING STROKED PATHS

    The command

        void StencilStrokePathNV(uint path,
                                 int reference, uint mask);

    transforms into window space the stroked region of the path object
    named /path/ based on the current modelview, projection, viewport,
    and depth range transforms (ignoring any vertex and/or geometry
    shader or program that might be active/enabled) and then updates
    the stencil values of a subset of the accessible samples (see above)
    in the framebuffer.

    If /path/ does not name an existing path object, the command does
    nothing (and no error is generated).

    The path object's stroke width parameter (PATH_STROKE_WIDTH_NV) in
    path space units determines the width of the path's stroked region.

    When the dash array count of a path object is zero (dashing is
    considered subsequently), the stroke of a transformed path's outline
    is the region of window space defined by the union of:

        *   Sweeping an orthogonal centered line segment of the (above
            determined) effective stroke width along each path segment
            in the path's transformed outline.

        *   End cap regions (explained below) appended to the initial
            and terminal control points of non-closed command sequences
            in the path.  For a sequence of commands that form a closed
            contour, the end cap regions are ignored.

        *   Join style regions (explained below) between connected path
            segments meet.

    Any accessible samples within the union of these three regions are
    considered within the path object's stroke.

    The /mask/ parameter controls what subset of stencil bits are affected
    by the command.  If the /mask/ parameter is zero, the path object's
    stroke mask parameter (PATH_STROKE_MASK_NV) is considered the effective
    value of /mask/.

    A sample's stencil bits that are set in the effective /mask/ value
    are updated with the specified stencil /reference/ value if the
    sample is accessible (as specified above) and within the stroke of
    the transformed path's outline.

    Every path object has an initial and terminal end cap parameter
    (PATH_INITIAL_END_CAP_NV and PATH_TERMINAL_END_CAP_NV) that is
    one of FLAT, SQUARE_NV, ROUND_NV, or TRIANGULAR_NV.  There are no
    samples within a FLAT end cap.  The SQUARE_NV cap extends centered
    and tangent to the given end (initial or terminal) of the subpath
    for half the effective stroke width; in other words, a square cap
    is a half-square that kisses watertightly the end of a subpath.
    The ROUND_NV cap appends a semi-circle, centered and tangent,
    with the diameter of the effective stroke width to the given end
    (initial or terminal) of the subpath; in other words, a round cap
    is a semi-circle that kisses watertightly the end of a subpath.
    The TRIANGULAR_NV cap appends a right triangle, centered and tangent,
    with its hypotenuse flush to the given end of the subpath; in other
    words, a triangular cap is a right triangle that kisses watertightly
    the end of a subpath with the triangle's longest side.

    Every path object has a join style parameter (PATH_JOIN_STYLE_NV)
    that is one of BEVEL_NV, ROUND_NV, MITER_REVERT_NV, MITER_TRUNCATE_NV,
    or NONE; each path object also has a miter limit value.  The BEVEL_NV
    join style inserts a triangle with two vertices at the outside
    corners where two connected path segments join and a third vertex at
    the common end point shared by the two path segments.  The ROUND_NV
    join style inserts a wedge-shaped portion of a circle centered at
    the common end point shared by the two path segments; the radius of
    the circle is half the effective stroke width.  There are no samples
    within a NONE join style.  The MITER_REVERT_NV join style inserts a
    quadrilateral with two opposite vertices at the outside corners where
    the two connected path segments join and two opposite vertices with
    one on the path's junction between the two joining path segments and
    the other at the common end point shared by the two path segments.
    However, the MITER_REVERT_NV join style behaves as the BEVEL_NV
    style if the sine of half the angle between the two joined segments
    is less than the path object's PATH_STROKE_WIDTH value divided by
    the path's PATH_MITER_LIMIT_NV value.  The MITER_TRUNCATE_NV join
    style is similar to MITER_REVERT_NV but rather than reverting to a
    bevel when the miter limit is exceeded, instead the tip of the miter
    quadrilateral is truncated such that the miter does not extend beyond
    the miter limit.

    When the dash array count of a path object is /not/ zero, the path is
    broken up into a sequence of paths based on the path object's dash
    array count, dash array, dash offset, and dash cap parameters (see
    section 5.X.1.5).  This sequence of paths are handled as if their
    dash count array is zero so their stroked region can be determined
    for this stroking case that has already been explained.

    The dash pattern defined by the dash array is a sequence of lengths of
    alternating "on" and "off" dash segments.  The first (0th) element of
    the dash array defines the length, in path space, of the first "on"
    dash segment.  The second value defines the length of the following
    "off" segment.  Each subsequent pair of values defines on "on"
    and one "off" segment.

    The initial cap of the first dash segment uses the path's initial
    dash cap style state (PATH_INITIAL_END_CAP_NV) as the effective
    initial end cap for this first dash segment; the terminal cap
    of the last dash segment uses the path's terminal dash cap style
    state (PATH_TERMINAL_END_CAP_NV) as the effective terminal cap for
    this last dash segment; all other caps of dash segments use the
    PATH_INITIAL_DASH_CAP_NV for the initial cap of the segment and the
    PATH_TERMINAL_DASH_CAP_NV for the terminal cap of the segment.

    The MOVE_TO_RESETS_NV value for a path's dash offset reset parameter
    (PATH_DASH_OFFSET_RESET_NV) means that the dash offset resets to the
    path's dash offset parameter upon a MOVE_TO_NV, RELATIVE_MOVE_TO_NV,
    RESTART_PATH_NV, or RECT_NV command (an command that does an implicit
    or explicit move-to) while dashing the path's command sequence.
    The MOVE_TO_CONTINUES_NV value means that the dash pattern
    progresses normally (without reset) when dashing a MOVE_TO_NV or
    RELATIVE_MOVE_TO_NV command.

    Every path object has a stroke approximation bound parameter
    (PATH_STROKE_BOUND_NV) that is a floating-point value /sab/ clamped
    between 0.0 and 1.0 and set and queried with the PATH_STROKE_BOUND_NV
    path parameter.  Exact determination of samples swept an orthogonal
    centered line segment along cubic Bezier segments and rational
    quadratic Bezier curves (so non-circular partial elliptical arcs) is
    intractable for real-time rendering so an approximation is required;
    /sab/ intuitively bounds the approximation error as a percentage of
    the path object's stroke width.  Specifically, this path parameter
    requests the implementation to stencil any samples within /sweep/
    object space units of the exact sweep of the path's cubic Bezier
    segments or partial elliptical arcs to be sampled by the stroke where

      sweep = ((1-sab)*sw)/2

    where /sw/ is the path object's stroke width.  The initial value
    of /sab/ when a path is created is 0.2.  In practical terms, this
    initial value means the stencil sample positions coverage within 80%
    (100%-20%) of the stroke width of cubic and rational quadratic stroke
    segments should be sampled.

    If the path object's client length parameter (PATH_CLIENT_LENGTH_NV)
    value /clen/ is non-zero, prior to generating the dashed segments, the
    dash pattern and dash offset lengths should be scaled by (multiplied
    by) the clen/plen where /plen/ is the path object's computed length
    (PATH_COMPUTED_LENGTH_NV).

    5.X.2.2 Path Covering

    COVERING FILLED PATHS

    The command

        void PathCoverDepthFuncNV(enum zfunc);

    configures the depth function to be used by the CoverFillPathNV and
    CoverStrokePathNV commands described subsequently.  The /zfunc/ parameter
    accepts the same values allowed by the DepthFunc command.

    The command

        void CoverFillPathNV(uint path, enum coverMode);

    transforms into window space the outline of the path object named
    /path/ based on the current modelview, projection, viewport,
    and depth range transforms (ignoring any vertex and/or geometry
    shader or program that might be active/enabled) and rasterizes a
    subset of the accessible samples in the framebuffer guaranteed to
    include all samples that would be have a net stencil value change if
    StencilFillPathNV were issued with the same modelview, projection,
    and viewport state.  During this rasterization, the stencil test
    operates normally and as configured; the expectation is the stencil
    test will be used to discard samples not determined "covered" by a
    prior StencilFillPathNV command.  The depth function, if DEPTH_TEST is
    enabled, during this rasterization uses the function specified by
    PathCoverDepthFuncNV (instead of the state specified by DepthFunc).

    If /path/ does not name an existing path object, the command does
    nothing (and no error is generated).

    /coverMode/ must be one of CONVEX_HULL_NV, BOUNDING_BOX_NV, or
    PATH_FILL_COVER_MODE_NV.  The PATH_FILL_COVER_MODE_NV uses the path
    object's PATH_FILL_COVER_MODE_NV parameter value as the effective
    fill cover mode of the cover command.

    When /coverMode/ is CONVEX_HULL_NV or BOUNDING_BOX_NV, the subset
    of accessible pixels that are rasterized are within a convex
    hull or bounding box respectively (each expected to be reasonably
    tight) surrounding all the samples guaranteed to be rasterized by
    CoverFillPathNV.  The bounding box must be orthogonally aligned
    to the path space coordinate system.  (The area of the bounding
    box in path space is guaranteed to be greater than or equal the
    area of the convex hull in path space.) Each rasterized sample
    will be rasterized once and exactly once when CONVEX_HULL_NV or
    BOUNDING_BOX_NV is specified.

    While samples with a net stencil change /must/ be rasterized,
    implementations are explicitly allowed to vary in the rasterization
    of samples for which StencilFillPathNV would /not/ change sample's
    net stencil value.  This means implementations are allowed to (and,
    in fact, are expected to) conservatively "exceed" the region strictly
    stenciled by the path object.

    CoverFillPathNV /requires/ the following rasterization invariance:
    calling CoverFillPathNV for the same (unchanged) path object with
    fixed (unchanged) modelview, projection, and viewport transform state
    with the same (unchanged) set of accessible samples will rasterize
    the exact same set of samples with identical interpolated values
    for respective fragment/sample locations.

    COVERING STROKED PATHS

    The command

        void CoverStrokePathNV(uint path, enum coverMode);

    operates in the same manner as CoverFillPathNV except the region
    guaranteed to be rasterized is, rather than the region within /path/'s
    filled outline, instead the region within the /path/'s stroked region
    as determined by StencilStrokePathNV.  During this rasterization,
    the stencil test operates normally and as configured; the expectation
    is the stencil test will be used to discard samples not determined
    "covered" by a prior StencilStrokePathNV command.  As with CoverFillPathNV,
    the depth function, if DEPTH_TEST is enabled, uses the function specified
    by PathCoverDepthFuncNV.

    /coverMode/ must be one of CONVEX_HULL_NV, BOUNDING_BOX_NV, or
    PATH_STROKE_COVER_MODE_NV.  The PATH_STROKE_COVER_MODE_NV uses
    the path object's PATH_STROKE_COVER_MODE_NV parameter value as the
    effective stroke cover mode of the cover command.

    If /path/ does not name an existing path object, the command does
    nothing (and no error is generated).

    Analogous to the rasterization guarantee of CoverFillPathNV with
    respect to StencilFillPathNV, CoverStrokePathNV guarantees that all
    samples rasterized by StencilStrokePathNV, given the same transforms
    and accessible pixels and stroke width, will also be rasterized by
    the corresponding CoverStrokePathNV.

    CoverStrokePathNV /requires/ the following rasterization invariance:
    calling CoverStrokePathNV for the same (unchanged) path object with
    fixed (unchanged) modelview, projection, and viewport transform
    state and with the same (unchanged) set of accessible samples will
    rasterize the exact same set of samples with identical interpolated
    values for respective fragment/sample locations.

    PATH COVERING RASTERIZATION DETAILS

    The GL processes fragments rasterized by path cover commands in
    much the same manner as fragments generated by conventional polygon
    rasterization.  However path rendering /ignores/ the following
    operations:

        *  Interpolation of per-vertex data (section 3.6.1).  Path
           primitives have neither conventional vertices nor per-vertex
           data.  Instead fragments generate interpolated per-fragment
           colors, texture coordinate sets, and fog coordinates as a
           linear function of object-space or eye-space path coordinate's
           or using the current color, texture coordinate set, or fog
           coordinate state directly.

        *  Polygon smooth (section 3.6.3).

        *  Polygon mode (section 3.6.4).  Fragments generated by path
           covering never result from point or line rasterizations.

    Polygon stippling (section 3.6.2), depth offset (section 3.6.5), and
    polygon multisample rasterization (3.6.6) do apply to path covering.

    Front and back face determination (explained in section 3.6.1 for
    polygons) operates somewhat differently for transformed paths than
    polygons.  The path's convex hull, bounding box, or multiple hulls
    (depending on the /coverMode/) are specified to wind counterclockwise
    in object space though the transformation of the convex hull into
    window space could reverse this winding.  Whether the GL's front face
    state is CCW or CCW (as set by the FrontFace command) determines
    if the path is front facing or not.  Because the specific vertices
    that belong to the covering geometry are implementation-dependent,
    when the signed area of the covering geometry (computed with equation
    3.8) is sufficiently near zero, the facingness of the path in such
    situations is ill-defined.

    The determination of whether a path transformed into window space is
    front facing or not affects face culling if enabled (section 3.6.1),
    the gl_FrontFacing built-in variable (section 3.12.22), and separate
    (two-sided) stencil testing (section 4.1.5).

    Once fragments have been generated by path covering, the fragments
    are shaded in the same manner as fragments generated by polygon
    rasterization with the following exception:  If a GLSL program is
    in use, any vertex or geometry shader linked into the GLSL program
    is ignored. The fragment shader operates normally except that
    user-defined inputs to the fragment shader behave as specified by
    ProgramPathFragmentInputGenNV. When supported, the fragment shader
    could also use the built-in varying inputs: gl_Texcoord[i],
    gl_Color, gl_SecondaryColor, and gl_FogFragCoord.

    COLOR GENERATION FOR PATH COVER COMMANDS

    The command

        void PathColorGenNV(enum color,
                            enum genMode,
                            enum colorFormat, const float *coeffs);

    controls how the primary and secondary interpolated colors are
    computed for fragment shading operations that occur as a result of
    CoverFillPathNV or CoverStrokePathNV.

    /color/ must be one of PRIMARY_COLOR,
    PRIMARY_COLOR_NV, SECONDARY_COLOR_NV to specify the indicated color
    generation state for the primary, primary, and secondary color
    respectively; otherwise INVALID_ENUM is generated.

    /genMode/ must be one of NONE, OBJECT_LINEAR,
    PATH_OBJECT_BOUNDING_BOX_NV, EYE_LINEAR, or CONSTANT; otherwise
    INVALID_ENUM is generated.

    NONE means the color is not generated but rather uses the
    corresponding color's current color state.  OBJECT_LINEAR means that
    the specified color is generated from a linear combination of the 2D
    path coordinates (x,y).  EYE_LINEAR means the specified color
    is generated from a linear combination of path's 2D coordinates
    transformed in eye space, so (xe, ye, ze, we) from section 2.12
    ("Fixed-Function Vertex Transformation").  CONSTANT means the specified
    color is generated from the specified constant coefficients.

    When covering single paths with CoverFillPathNV or CoverStrokePathNV,
    PATH_OBJECT_BOUNDING_BOX_NV means the specified color is generated
    as a function of object-space (x,y) coordinate normalized to the
    [0..1]x[0..1] range where (0,0) is the corner of the path object's
    bounding box with the minimum x and minimum y coordinates and (1,1)
    is the corner of the path object's bounding box with the maximum x and
    maximum y coordinates.  Using PATH_OBJECT_BOUND_BOX_NV for /genMode/
    means generated colors are undefined if either the width or height
    of the path's bounding box is zero.

    When covering instanced paths with CoverFillPathInstancedNV or
    CoverStrokePathInstancedNV using the BOUNDING_BOX_OF_BOUNDING_BOXES_NV
    cover mode (see section 5.X.2.3), the specified color is generated
    as a function of object-space (x,y) coordinate normalized to the
    [0..1]x[0..1] range where (0,0) is the corner of the bounding box of
    the union of bounding boxes of the set of instanced path objects and
    (1,1) is the corner of the same union bounding box with the maximum
    x and maximum y coordinates.

    When /genMode/ is NONE, then /colorFormat/ must be NONE;
    otherwise INVALID_ENUM is generated.  When /genMode/ is not NONE,
    then /colorFormat/ must be one of LUMINANCE, ALPHA, INTENSITY,
    LUMINANCE_ALPHA, RGB, or RGBA; otherwise INVALID_ENUM is generated.

    In the following equations used for path color generation, coeffs[i]
    is the /i/th element (base zero) of the /coeffs/ array; Rc, Gc,
    Bc, and Aa are the red, green, blue, and alpha colors of the current
    primary or secondary color (depending on the color parameter) when the
    path is covered; and x, y, z, and w are determined by the /genMode/.

    When /genMode/ is EYE_LINEAR, xcoeffs[i] is the /i/th element (base
    zero) of a /xcoeffs/ array generated by multiplying each respective
    vector of four elements of coeffs by the current inverse modelview
    matrix when PathColorGenNV is called.

        xcoeffs[0..3]   = coeffs[0..3]   * MV^-1
        xcoeffs[4..7]   = coeffs[4..7]   * MV^-1
        xcoeffs[8..11]  = coeffs[8..11]  * MV^-1
        xcoeffs[12..15] = coeffs[12..12] * MV^-1

    [[ NOTATION:

       xxx[0..3] is a vector form from xxx[0], xxx[1], xxx[2], and xxx[3]

       MV^-1 is the inverse of the current modelview matrix when PathColorGenNV happens.

    ]]

    If the /genMode/ is NONE, no values from the /coeffs/ array are
    accessed and the R, G, B, and A components of a covered fragment's
    varying color (be it primary or secondary depending on color)
    are computed:

        R = Rc
        G = Gc
        B = Bc
        A = Ac

    If /colorFormat/ is LUMINANCE and /genMode/ is either OBJECT_LINEAR
    or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from the
    /coeffs/ array and the R, G, B, and A components of a covered
    fragment's varying color are computed:

        R = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        G = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        B = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        A = Ac

    Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are
    accessed and the varying color components are computed:

        R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        G = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        B = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        A = Ac

    Alternatively if the /genMode/ is CONSTANT, then:

        R = xcoeffs[0]
        G = xcoeffs[0]
        B = xcoeffs[0]
        A = Ac

    If /colorFormat/ is INTENSITY and /genMode/ is either OBJECT_LINEAR
    or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from
    the /coeffs/ array and the R, G, B, and A components of a covered
    fragment's varying color are computed:

        R = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        G = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        B = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        A = coeffs[0] * x + coeffs[1] * y + coeffs[2]

    Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are
    accessed and the varying color components are computed:

        R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        G = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        B = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        A = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we

    Alternatively if the /genMode/ is CONSTANT, then:

        R = xcoeffs[0]
        G = xcoeffs[0]
        B = xcoeffs[0]
        A = xcoeffs[0]

    If /colorFormat/ is ALPHA and /genMode/ is either OBJECT_LINEAR
    or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from
    the /coeffs/ array and the R, G, B, and A components of a covered
    fragment's varying color are computed:

        R = Rc
        G = Gc
        B = Bc
        A = coeffs[0] * x + coeffs[1] * y + coeffs[2]

    Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are
    accessed and the varying color components are computed:

        R = Rc
        G = Gc
        B = Bc
        A = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we

    Alternatively if the /genMode/ is CONSTANT, then:

        R = Rc
        G = Gc
        B = Bc
        A = xcoeffs[0]

    If /colorFormat/ is RGB and /genMode/ is either OBJECT_LINEAR or
    PATH_OBJECT_BOUNDING_BOX_NV, then 9 values are accessed from the
    /coeffs/ array and the R, G, B, and A components of a covered
    fragment's varying color are computed:

        R = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        G = coeffs[3] * x + coeffs[4] * y + coeffs[5]
        B = coeffs[6] * x + coeffs[7] * y + coeffs[8]
        A = Ac

    Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are
    accessed and the varying color components are computed:

        R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2]  * ze + xcoeffs[3]  * we
        G = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6]  * ze + xcoeffs[7]  * we
        B = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we
        A = Ac

    Alternatively if the /genMode/ is CONSTANT, then:

        R = xcoeffs[0]
        G = xcoeffs[1]
        B = xcoeffs[2]
        A = Ac

    If /colorFormat/ is RGBA and /genMode/ is either OBJECT_LINEAR
    or PATH_OBJECT_BOUNDING_BOX_NV, then 12 values are accessed from
    the /coeffs/ array and the R, G, B, and A components of a covered
    fragment's varying color are computed:

        R = coeffs[0] * x + coeffs[1]  * y + coeffs[2]
        G = coeffs[3] * x + coeffs[4]  * y + coeffs[5]
        B = coeffs[6] * x + coeffs[7]  * y + coeffs[8]
        A = coeffs[9] * x + coeffs[10] * y + coeffs[11]

    Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are
    accessed and the varying color components are computed:

        R = xcoeffs[0]  * xe + xcoeffs[1]  * ye + xcoeffs[2]  * ze + xcoeffs[3]  * we
        G = xcoeffs[4]  * xe + xcoeffs[5]  * ye + xcoeffs[6]  * ze + xcoeffs[7]  * we
        B = xcoeffs[8]  * xe + xcoeffs[9]  * ye + xcoeffs[10] * ze + xcoeffs[11] * we
        A = xcoeffs[12] * xe + xcoeffs[13] * ye + xcoeffs[14] * ze + xcoeffs[15] * we

    Alternatively if the /genMode/ is CONSTANT, then:

        R = xcoeffs[0]
        G = xcoeffs[1]
        B = xcoeffs[2]
        A = xcoeffs[3]

    The state required for path color generation for each color (primary
    and secondary) is a four-valued integer for the path color generation
    mode and 16 floating-point coefficients.  The initial mode is NONE
    and the coefficients are all initially zero.

    As many coefficients are copied by the PathColorGenNV command
    to the 16 floating-point coefficient state as are referenced by
    the respective generation expression involving /colorFormat/ and
    /genMode/; unreferenced coefficients in the array of 16 coefficients
    are set to zero.

    TEXTURE COORDINATE SET GENERATION FOR PATH COVER COMMANDS

    The command

        void PathTexGenNV(enum texCoordSet,
                          enum genMode,
                          int components, const float *coeffs);

    controls how texture coordinate sets are computed for fragment
    shading operations that occur as a result of CoverFillPathNV or
    CoverStrokePathNV.

    /texCoordSet/ must be one of TEXTURE0 through
    TEXTUREn where /n/ is one less than the implementation-dependent
    value of MAX_TEXTURE_COORDS; otherwise INVALID_ENUM is generated.

    /genMode/ must be one of NONE, OBJECT_LINEAR,
    PATH_OBJECT_BOUNDING_BOX_NV, or EYE_LINEAR; otherwise INVALID_ENUM
    is generated.

    /components/ must be 0 if /genMode/ is NONE or for other allowed
    /genMode/ values must be one of 1, 2, 3, or 4; otherwise INVALID_VALUE
    is generated.  /components/ determines how many texture coordinate
    components of the texture coordinate set, how many coefficients read
    from the /coeffs/ array, and the linear equations used to generate the
    s, t, r, and q texture coordinates of the varying texture coordinate
    set specified by /texCoordSet/.

    In the following equations, coeffs[i] is the /i/th element (base
    zero) of the /coeffs/ array; sc, tc, rc, and qa are the s, t, r,
    and q texture coordinates of the texture coordinate set indicated
    by /texCoordSet/ when the path is covered; and x, y, z, and w are
    determined by the /genMode/ in the same manner as PathColorGenNV's
    /genMode/.

    When /genMode/ is EYE_LINEAR, xcoeffs[i] is the /i/th element (base
    zero) of a /xcoeffs/ array generated by multiplying each respective
    vector of four elements of coeffs by the current inverse modelview
    matrix when PathColorGenNV is called.

        xcoeffs[0..3]   = coeffs[0..3]   * MV^-1
        xcoeffs[4..7]   = coeffs[4..7]   * MV^-1
        xcoeffs[8..11]  = coeffs[8..11]  * MV^-1
        xcoeffs[12..15] = coeffs[12..12] * MV^-1

    [[ NOTATION:

       xxx[0..3] is a vector form from xxx[0], xxx[1], xxx[2], and xxx[3]

       MV^-1 is the inverse of the current modelview matrix when PathColorGenNV happens.

    ]]

    If the /components/ is 0, no values from the /coeffs/ array are
    accessed and the s, t, r, and q coordinates of a covered fragment's
    varying texture coordinate set for /texCoordSet/ are computed:

        s = sc
        t = tc
        r = rc
        q = qc

    If the /components/ is 1 and /genMode/ is either OBJECT_LINEAR or
    PATH_OBJECT_BOUNDING_BOX_NV, 3 values from the /coeffs/ array are
    accessed and the s, t, r, and q coordinates of a covered fragment's
    varying texture coordinate set for /texCoordSet/ are computed:

        s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        t = tc
        r = rc
        q = qc

    Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are
    accessed and the varying texture coordinate set for /texunit/ are
    computed:

        s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        t = tc
        r = rc
        q = qc

    Alternatively if the /genMode/ is CONSTANT, then:

        s = xcoeffs[0]
        t = tc
        r = rc
        q = qc

    If the /components/ is 2 and /genMode/ is either OBJECT_LINEAR or
    PATH_OBJECT_BOUNDING_BOX_NV, 6 values from the /coeffs/ array are accessed and the
    s, t, r, and q coordinates of a covered fragment's varying texture
    coordinate set for /texCoordSet/ are computed:

        s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        t = coeffs[3] * x + coeffs[4] * y + coeffs[5]
        r = rc
        q = qc

    Alternatively if the /genMode/ is EYE_LINEAR, then 8 values are
    accessed and the varying texture coordinate set for /texunit/ are
    computed:

        s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we
        t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we
        r = rc
        q = qc

    Alternatively if the /genMode/ is CONSTANT, then:

        s = xcoeffs[0]
        t = xcoeffs[1]
        r = rc
        q = qc

    If the /components/ is 3 and /genMode/ is either OBJECT_LINEAR or
    PATH_OBJECT_BOUNDING_BOX_NV, 9 values from the /coeffs/ array are accessed and the
    s, t, r, and q coordinates of a covered fragment's varying texture
    coordinate set for /texCoordSet/ are computed:

        s = coeffs[0] * x + coeffs[1] * y + coeffs[2]
        t = coeffs[3] * x + coeffs[4] * y + coeffs[5]
        r = coeffs[6] * x + coeffs[7] * y + coeffs[8]
        q = qc

    Alternatively if the /genMode/ is CONSTANT, then:

        s = xcoeffs[0]
        t = xcoeffs[1]
        r = xcoeffs[2]
        q = qc

    Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are
    accessed and the varying texture coordinate set for /texunit/ are
    computed:

        s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2]  * ze + xcoeffs[3]  * we
        t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6]  * ze + xcoeffs[7]  * we
        r = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we
        q = qc

    If the /components/ is 4 and /genMode/ is either OBJECT_LINEAR or
    PATH_OBJECT_BOUNDING_BOX_NV, 12 values from the /coeffs/ array are accessed and the
    s, t, r, and q coordinates of a covered fragment's varying texture
    coordinate set for /texCoordSet/ are computed:

        s = coeffs[0] * x + coeffs[1]  * y + coeffs[2]
        t = coeffs[3] * x + coeffs[4]  * y + coeffs[5]
        r = coeffs[6] * x + coeffs[7]  * y + coeffs[8]
        q = coeffs[9] * x + coeffs[10] * y + coeffs[11]

    Alternatively if the /genMode/ is EYE_LINEAR, then 16 values are
    accessed and the varying texture coordinate set for /texunit/ are
    computed:

        s = xcoeffs[0]  * xe + xcoeffs[1]  * ye + xcoeffs[2]  * ze + xcoeffs[3]  * we
        t = xcoeffs[4]  * xe + xcoeffs[5]  * ye + xcoeffs[6]  * ze + xcoeffs[7]  * we
        r = xcoeffs[8]  * xe + xcoeffs[9]  * ye + xcoeffs[10] * ze + xcoeffs[11] * we
        q = xcoeffs[12] * xe + xcoeffs[13] * ye + xcoeffs[14] * ze + xcoeffs[15] * we

    Alternatively if the /genMode/ is CONSTANT, then:

        s = xcoeffs[0]
        t = xcoeffs[1]
        r = xcoeffs[2]
        q = xcoeffs[3]

    The state required for path color generation for each texture
    coordinate set is a four-valued integer for the path texture
    coordinate set generation mode and 16 floating-point coefficients.
    The initial mode is NONE and the coefficients are all initially zero.

    As many coefficients are copied by the PathTexGenNV command to
    the 16 floating-point coefficient state as are referenced by the
    respective generation expression involving /components/ and /genMode/;
    unreferenced coefficients in the array of 16 coefficients are set
    to zero.

    FOG COORDINATE GENERATION FOR PATH COVER COMMANDS

    The command

        void PathFogGenNV(enum genMode);

    controls how the fog coordinate is computed for fragment
    shading operations that occur as a result of CoverFillPathNV or
    CoverStrokePathNV.

    /genMode/ must be either FOG_COORDINATE or FRAGMENT_DEPTH; otherwise
    INVALID_ENUM is generated.

    If the /genMode/ is FOG_COORDINATE, then current fog coordinate is
    used (without varying) for all fragment generated by covering the
    filled or stroked path.

    If the /genMode/ is FRAGMENT_DEPTH, then the current fog coordinate
    is -ze, the interpolated negated (non-perspective-divided) eye-space
    Z coordinate from transforming of path's 2D coordinates transformed
    in eye space, so (xe, ye, ze, we) from section 2.12 ("Fixed-Function
    Vertex Transformation").

    The state required for path fog generation is a two-valued integer for
    the path fog generation mode; the mode is initially FRAGMENT_DEPTH.

    5.X.2.3 Instanced Path Stenciling and Covering

    Path rendering often depends on rendering a collection of paths at
    once. The most common case of this is rendering text as a set of
    glyphs corresponding to each character of text.  To support this
    usage efficiently, GL includes commands for instanced path stenciling
    and covering.

    The command

        void StencilFillPathInstancedNV(sizei numPaths,
                                        enum pathNameType, const void *paths,
                                        uint pathBase,
                                        enum fillMode, uint mask,
                                        enum transformType,
                                        const float *transformValues);

    stencils a sequence of filled paths.

    The /pathBase/ is an offset added to the /numPaths/ path names read
    from the /paths/ array (interpreted based on /pathNameType/).

    The /pathNameType/ determines the type of elements of the /paths/
    array and must be one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT,
    INT, UNSIGNED_INT, FLOAT, UTF8_NV, UTF16_NV, 2_BYTES, 3_BYTES,
    or 4_BYTES; otherwise the INVALID_ENUM error is generated.

    The /transformType/ must be one of NONE, TRANSLATE_X_NV,
    TRANSLATE_Y_NV, TRANSLATE_2D_NV, TRANSLATE_3D_NV, AFFINE_2D_NV,
    AFFINE_3D_NV, TRANSPOSE_AFFINE_2D_NV, or TRANSPOSE_AFFINE_3D_NV;
    otherwise the INVALID_ENUM error is generated.

    The /fillMode/ and /mask/ are validated identically to the same-named
    parameters of StencilFillPathNV.

    The StencilFillPathInstancedNV command is equivalent to:

        const float *v = transformValues;
        for (int i = 0; i<numPaths; i++) {
          double m[16];

          GetDoublev(MODELVIEW_MATRIX, m);  // save matrix
          v = applyTransformType(transformType, v);
          uint pathName;
          bool ok = getPathName(pathNameType, paths, pathBase, pathName);
          if (!ok)
            return;  // stop early
          if (IsPathNV(pathName)) {
            StencilFillPathNV(pathName, fillMode, mask);
          }
          MatrixLoaddEXT(MODELVIEW, m);  // restore matrix
        }

    assuming these helper functions for applyTransformType and
    getPathName:

        const float *applyTransformType(enum transformType, const float *v)
        {
          float m[16];
          switch (transformType) {
          case NONE:
            break;
          case TRANSLATE_X_NV:
            MatrixTranslateEXT(MODELVIEW, *v++, 0, 0);
            break;
          case TRANSLATE_Y_NV:
            MatrixTranslateEXT(MODELVIEW, 0, *v++, 0);
            break;
          case TRANSLATE_2D_NV:
            MatrixTranslateEXT(MODELVIEW, *v++, *v++, 0);
            break;
          case TRANSLATE_3D_NV:
            MatrixTranslateEXT(MODELVIEW, *v++, *v++, *v++);
            break;
          case AFFINE_2D_NV:
            m[0] =v[0]; m[4] =v[2]; m[8] =0; m[12]=v[4];
            m[1] =v[1]; m[5] =v[3]; m[9] =0; m[13]=v[5];
            m[2] =0;    m[6] =0;    m[10]=1; m[14]=0;
            m[3] =0;    m[7] =0;    m[11]=0; m[15]=1;
            v += 6;
            MatrixMultfEXT(MODELVIEW, m);
            break;
          case TRANSPOSE_AFFINE_2D_NV:
            m[0] =v[0]; m[4] =v[1]; m[8] =0; m[12]=v[2];
            m[1] =v[3]; m[5] =v[4]; m[9] =0; m[13]=v[5];
            m[2] =0;    m[6] =0;    m[10]=1; m[14]=0;
            m[3] =0;    m[7] =0;    m[11]=0; m[15]=1;
            v += 6;
            MatrixMultfEXT(MODELVIEW, m);
            break;
          case AFFINE_3D_NV:
            m[0] =v[0]; m[4] =v[3]; m[8] =v[6]; m[12]=v[9];
            m[1] =v[1]; m[5] =v[4]; m[9] =v[7]; m[13]=v[10];
            m[2] =v[2]; m[6] =v[5]; m[10]=v[8]; m[14]=v[11];
            m[3] =0;    m[7] =0;    m[11]=1;    m[15]=0;
            v += 12;
            MatrixMultfEXT(MODELVIEW, m);
            break;
          case TRANSPOSE_AFFINE_3D_NV:
            m[0] =v[0]; m[4] =v[1]; m[8] =v[2];  m[12]=v[3];
            m[1] =v[4]; m[5] =v[5]; m[9] =v[6];  m[13]=v[7];
            m[2] =v[8]; m[6] =v[9]; m[10]=v[10]; m[14]=v[11];
            m[3] =0;    m[7] =0;    m[11]=1;     m[15]=0;
            v += 12;
            MatrixMultfEXT(MODELVIEW, m);
            break;
          default:  // generate INVALID_ENUM
          }
          return v;
        }

        bool getPathName(enum pathNameType, const void *&paths,
                         uint pathBase, uint &pathName)
        {
          switch (pathNameType) {
          case BYTE:
            {
              const byte *p = (const byte*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case UNSIGNED_BYTE:
            {
              const ubyte *p = (const ubyte*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case SHORT:
            {
              const short *p = (const short*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case UNSIGNED_SHORT:
            {
              const ushort *p = (const ushort*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case INT:
            {
              const int *p = (const int*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case UNSIGNED_INT:
            {
              const uint *p = (const uint*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case FLOAT:
            {
              const float *p = (const float*)paths;
              pathName = pathBase + p[0];
              paths = p+1;
              return true;
            }
          case 2_BYTES:
            {
              const ubyte *p = (const ubyte*)paths;
              pathName = pathBase + (p[0]<<8 | p[1]);
              paths = p+2;
              return true;
            }
          case 3_BYTES:
            {
              const ubyte *p = (const ubyte*)paths;
              pathName = pathBase + (p[0]<<16 | p[1]<<8 | p[0]);
              paths = p+3;
              return true;
            }
          case 4_BYTES:
            {
              const ubyte *p = (const ubyte*)paths;
              pathName = pathBase + (p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]);
              paths = p+4;
              return true;
            }
          case UTF8_NV:
            {
              const ubyte *p = (const ubyte*)paths;
              ubyte c0 = p[0];
              if ((c0 & 0x80) == 0x00) {
                // Zero continuation (0 to 127)
                pathName = pathBase + c0;
                p += 1;
              } else {
                ubyte c1 = p[1];
                if ((c1 & 0xC0) != 0x80) {
                  // Stop processing the UTF byte sequence early.
                  return false;
                }
                if ((c0 & 0xE0) == 0xC0) {
                  // One contination (128 to 2047)
                  pathName = pathBase + ((c1 & 0x3F) | (c0 & 0x1F) << 6);
                  if (pathName < 128) {
                    return false;
                  }
                  p += 2;
                } else {
                  ubyte c2 = p[2];
                  if ((c2 & 0xC0) != 0x80) {
                    // Stop processing the UTF byte sequence early.
                    return false;
                  }
                  if ((c0 & 0xF0) == 0xE0) {
                    // Two continuation (2048 to 55295 and 57344 to 65535)
                    pathName = pathBase + ((c2 & 0x3F) | (c1 & 0x3F) << 6 |
                                           (c0 & 0xF) << 12);
                    if ((pathName >= 55296) && (pathName <= 57343)) {
                      // Stop processing the UTF byte sequence early.
                      return false;
                    }
                    if (pathName < 2048) {
                      return false;
                    }
                    p += 3;
                  } else {
                    ubyte c3 = p[3];
                    if ((c3 & 0xC0) != 0x80) {
                      // Stop processing the UTF byte sequence early.
                      return false;
                    }
                    if ((c0 & 0xF8) == 0xF0) {
                      // Three continuation (65536 to 1114111)
                      pathName = pathBase + ((c3 & 0x3F) | (c2 & 0x3F) << 6 |
                                             (c1 & 0x3F) << 12 | (c0 & 0x7) << 18);
                      if (pathName < 65536 && pathName > 1114111) {
                        return false;
                      }
                      p += 4;
                    } else {
                      // Skip invalid or restricted encodings.
                      // Stop processing the UTF byte sequence early.
                      return false;
                    }
                  }
                }
              }
              paths = p;
              return true;
            }
          case UTF16_NV:
            {
              const ushort *p = (const ushort*)paths;

              ushort s0 = p[0];
              if ((s0 < 0xDB00) || (s0 > 0xDFFF)) {
                  pathName = pathBase + s0;
                  p += 1;
              } else {
                if ((s0 >= 0xDB00) && (s0 <= 0xDBFF)) {
                  ushort s1 = p[1];
                  if ((s1 >= 0xDC00) && (s1 <= 0xDFFF)) {
                    pathName = pathBase + (((s0 & 0x3FF) << 10 |
                                            (s1 & 0x3FF)) + 0x10000);
                    p += 2;
                  } else {
                    // Stop processing the UTF byte sequence early.
                    return false;
                  }
                } else {
                  return false;
                }
              }
              paths = p;
              return true;
            }
          default:
              << generate INVALID_ENUM >>
              return false;
          }
        }

    The command

        void StencilStrokePathInstancedNV(sizei numPaths,
                                          enum pathNameType, const void *paths,
                                          uint pathBase,
                                          int reference, uint mask,
                                          enum transformType,
                                          const float *transformValues);

    stencils a sequence of stroked paths and is equivalent to:

        const float *v = transformValues;
        for (int i = 0; i<numPaths; i++) {
          double m[16];

          GetDoublev(MODELVIEW_MATRIX, m);  // save matrix
          v = applyTransformType(transformType, v);
          uint pathName;
          bool ok = getPathName(pathNameType, paths, pathBase, pathName);
          if (!ok)
            return;  // stop early
          if (IsPathNV(pathName)) {
            StencilStrokePathNV(pathName, reference, mask);
          }
          MatrixLoaddEXT(MODELVIEW, m);  // restore matrix
        }

    assume the helper functions for applyTransformType and
    getPathName defined above.

    The command

        void CoverFillPathInstancedNV(sizei numPaths,
                                      enum pathNameType, const void *paths,
                                      uint pathBase,
                                      enum coverMode,
                                      enum transformType,
                                      const float *transformValues);

    covers a sequence of filled paths and is equivalent to:

        if (coverMode == BOUNDING_BOX_OF_BOUNDING_BOXES_NV) {
          renderBoundingBox(PATH_FILL_BOUNDING_BOX_NV,
                            numPaths,
                            pathNameType, paths,
                            pathBase,
                            transformType, transformValues);
        } else {
          const float *v = transformValues;
          for (int i = 0; i<numPaths; i++) {
            double m[16];
            uint path;

            GetDoublev(MODELVIEW_MATRIX, m);  // save matrix
            v = applyTransformType(transformType, v);
            uint pathName;
            bool ok = getPathName(pathNameType, paths, pathBase, pathName);
            if (!ok)
              return;  // stop early
            if (IsPathNV(pathName)) {
              << set fragment shader instance ID to i >>
              CoverFillPathNV(pathName, cover);
            }
            MatrixLoaddEXT(MODELVIEW, m);  // restore matrix
          }
        }

    assuming these helper functions for applyTransformType and
    getPathName defined above as well as:

        void renderBoundingBox(enum boundingBoxType,
                               sizei numPaths,
                               enum pathNameType,
                               const void *paths,
                               uint pathBase,
                               enum transformType,
                               const float *transformValues)
        {
          boolean hasBounds = FALSE;
          float boundsUnion[4], bounds[4];

          const float *v = transformValues;
          for (int i = 0; i<numPaths; i++) {
            uint pathName;
            bool ok = getPathName(pathNameType, paths, pathBase, pathName);
            if (!ok)
              return;  // stop early
            if (IsPathNV(pathName)) {
              GetPathParameterfvNV(pathName, boundingBoxType, bounds);
              switch (transformType) {
              case NONE:
                break;
              case TRANSLATE_X_NV:
                bounds[0] += v[0];
                bounds[2] += v[0];
                v += 1;
                break;
              case TRANSLATE_Y_NV:
                bounds[1] += v[0];
                bounds[3] += v[0];
                v += 1;
                break;
              case TRANSLATE_2D_NV:
                bounds[0] += v[0];
                bounds[1] += v[1];
                bounds[2] += v[0];
                bounds[3] += v[1];
                v += 2;
                break;
              case TRANSLATE_3D_NV: // ignores v[2]
                bounds[0] += v[0];
                bounds[1] += v[1];
                bounds[2] += v[0];
                bounds[3] += v[1];
                v += 3;
                break;
              case AFFINE_2D_NV:
                bounds[0] = bounds[0]*v[0] + bounds[0]*v[2] + v[4];
                bounds[1] = bounds[1]*v[1] + bounds[1]*v[3] + v[5];
                bounds[2] = bounds[2]*v[0] + bounds[2]*v[2] + v[4];
                bounds[3] = bounds[3]*v[1] + bounds[3]*v[3] + v[5];
                v += 6;
                break;
              case TRANSPOSE_AFFINE_2D_NV:
                bounds[0] = bounds[0]*v[0] + bounds[0]*v[1] + v[2];
                bounds[1] = bounds[1]*v[3] + bounds[1]*v[4] + v[5];
                bounds[2] = bounds[2]*v[0] + bounds[2]*v[1] + v[2];
                bounds[3] = bounds[3]*v[3] + bounds[3]*v[4] + v[5];
                v += 6;
                break;
              case AFFINE_3D_NV:  // ignores v[2], v[5], v[6..8], v[11]
                bounds[0] = bounds[0]*v[0] + bounds[0]*v[3] + v[9];
                bounds[1] = bounds[1]*v[1] + bounds[1]*v[4] + v[10];
                bounds[2] = bounds[2]*v[0] + bounds[2]*v[3] + v[9];
                bounds[3] = bounds[3]*v[1] + bounds[3]*v[4] + v[10];
                v += 12;
                break;
              case TRANSPOSE_AFFINE_3D_NV:  // ignores v[2], v[6], v[8..11]
                bounds[0] = bounds[0]*v[0] + bounds[0]*v[1] + v[3];
                bounds[1] = bounds[1]*v[4] + bounds[1]*v[5] + v[7];
                bounds[2] = bounds[2]*v[0] + bounds[2]*v[1] + v[3];
                bounds[3] = bounds[3]*v[4] + bounds[3]*v[5] + v[7];
                v += 12;
                break;
              default:  // generate INVALID_ENUM
              }
              if (bounds[0] > bounds[2]) {
                float t = bounds[2];
                bounds[2] = bounds[0];
                bounds[0] = t;
              }
              if (bounds[1] > bounds[3]) {
                float t = bounds[3];
                bounds[3] = bounds[1];
                bounds[1] = t;
              }
              if (hasBounds) {
                if (bounds[0] < boundsUnion[0]) {
                  boundsUnion[0] = bounds[0];
                }
                if (bounds[1] < boundsUnion[1]) {
                  boundsUnion[1] = bounds[1];
                }
                if (bounds[2] > boundsUnion[2]) {
                  boundsUnion[2] = bounds[2];
                }
                if (bounds[3] > boundsUnion[3]) {
                  boundsUnion[3] = bounds[3];
                }
              } else {
                for (int i=0; i<4; i++) {
                  boundsUnion[i] = bounds[i];
                }
                hasBounds = TRUE;
              }
            }
          }
          if (hasBounds) {
            boolean polygonSmoothEnable = IsEnabled(POLYGON_SMOOTH);
            int polygonModes[2];
            GetIntegerv(POLYGON_MODE, polygonModes);
            PolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            Disable(GL_POLYGON_SMOOTH);
            Rectf(boundsUnion[0], boundsUnion[1], boundsUnion[2], boundsUnion[3]);
            PolygonMode(FRONT, polygonModes[0]);
            PolygonMode(BACK, polygonModes[1]);
            if (polygonSmoothEnable) {
              Enable(POLYGON_SMOOTH);
            } else {
              Disable(POLYGON_SMOOTH);
            }
          }
        }

    The GetPathParameterfvNV query, used in the code above, is introduced
    in section 6.X.1 ("Path Object Parameter Queries").

    The command

         void CoverStrokePathInstancedNV(sizei numPaths,
                                         enum pathNameType, const void *paths,
                                         uint pathBase,
                                         enum coverMode,
                                         enum transformType,
                                         const float *transformValues);

    covers a sequence of stroked paths and is equivalent to:

        if (coverage == BOUNDING_BOX_OF_BOUNDING_BOXES_NV) {
          renderBoundingBox(PATH_STROKE_BOUNDING_BOX_NV,
                            numPaths,
                            pathNameType, paths,
                            pathBase,
                            transformType, transformValues);
        } else {
          const float *v = transformValues;
          for (int i = 0; i<numPaths; i++) {
            double m[16];

            GetDoublev(MODELVIEW_MATRIX, m);  // save matrix
            v = applyTransformType(transformType, v);
            uint pathName;
            bool ok = getPathName(pathNameType, paths, pathBase, pathName);
            if (!ok)
              return;  // stop early
            if (IsPathNV(pathName)) {
              << set fragment shader instance ID to i >>
              CoverStrokePathNV(pathName, cover);
            }
            MatrixLoaddEXT(MODELVIEW, m);  // restore matrix
          }
        }

    assuming these helper functions for applyTransformType,
    getPathName, and renderBoundingBox defined above.

    5.X.2.4 Path Stenciling Then Covering

    The following command combine the stencil and cover operations on
    paths into a single command.

    The command

        void StencilThenCoverFillPathNV(uint path, enum fillMode, uint mask, enum coverMode);

    is equivalent to the two commands

        StencilFillPathNV(path, fillMode, mask);
        CoverFillPathNV(path, coverMode);

    unless either command would generate an error; for any such error
    other than OUT_OF_MEMORY, only that error is generated.

    The command

        void StencilThenCoverStrokePathNV(uint path, int reference, uint mask, enum coverMode);

    is equivalent to the two commands

        StencilStrokePathNV(uint path, int reference, uint mask);
        CoverStrokePathNV(uint path, enum coverMode);

    unless either command would generate an error; for any such error
    other than OUT_OF_MEMORY, only that error is generated.

    The command

        void StencilThenCoverFillPathInstancedNV(sizei numPaths,
                                                 enum pathNameType, const void *paths,
                                                 uint pathBase,
                                                 enum fillMode, uint mask,
                                                 enum coverMode,
                                                 enum transformType,
                                                 const float *transformValues);

    is equivalent to the two commands

        StencilFillPathInstancedNV(sizei numPaths,
                                   enum pathNameType, const void *paths,
                                   uint pathBase,
                                   enum fillMode, uint mask,
                                   enum coverMode,
                                   enum transformType,
                                   const float *transformValues);
        CoverFillPathInstancedNV(sizei numPaths,
                                 enum pathNameType, const void *paths,
                                 uint pathBase,
                                 enum fillMode, uint mask,
                                 enum coverMode,
                                 enum transformType,
                                 const float *transformValues);

    unless either command would generate an error; for any such error
    other than OUT_OF_MEMORY, only that error is generated.

    The command

        void StencilThenCoverStrokePathInstancedNV(sizei numPaths,
                                                   enum pathNameType, const void *paths,
                                                   uint pathBase,
                                                   int reference, uint mask,
                                                   enum coverMode,
                                                   enum transformType,
                                                   const float *transformValues);

    is equivalent to the two commands

        StencilStrokePathInstancedNV(sizei numPaths,
                                     enum pathNameType, const void *paths,
                                     uint pathBase,
                                     int reference, uint mask,
                                     enum transformType,
                                     const float *transformValues);
        CoverStrokePathInstancedNV(sizei numPaths,
                                   enum pathNameType, const void *paths,
                                   uint pathBase,
                                   enum coverMode,
                                   enum transformType,
                                   const float *transformValues);

    unless either command would generate an error; for any such error
    other than OUT_OF_MEMORY, only that error is generated.

 -- Section 5.4 "Display Lists"

    Add to the list of commands not compiled into display lists:

    "Path objects:  GenPathsNV, DeletePathsNV."

Additions to Chapter 6 of the OpenGL 3.2 (unabridged) Specification (State and
State Requests)

 -- Insert section 6.X "Path Object Queries" after 6.1.18 "Renderbuffer
    Object Queries"

    6.X. Path Rendering Queries

    6.X.1. Path Object Parameter Queries

    The queries

        void GetPathParameterivNV(uint path, enum pname, int *value);
        void GetPathParameterfvNV(uint path, enum pname, float *value);

    obtains the current value of the /param/ path parameter of the path
    object named /name/; the error INVALID_OPERATION is generated if
    /name/ is not an existing path object.  /value/ is a pointer to a
    scalar or array of the appropriate type, int for GetPathParameterivNV
    and float for GetPathParameterfvNV, in which to place the returned
    data.

    Table 6.readOnlyPathParameters

        Name                         Type     Description
        ---------------------------  -------  ----------------------------
        PATH_COMMAND_COUNT_NV        int      Length of the path's
                                              command sequence
        PATH_COORD_COUNT_NV          int      Length of the path's
                                              coordinate sequence
        PATH_DASH_ARRAY_COUNT_NV     int      Length of the path's
                                              dash array
        PATH_COMPUTED_LENGTH_NV      float    Computed path-space
                                              length of all the
                                              segments in the path
                                              (see section 6.X.4)
        PATH_OBJECT_BOUNDING_BOX_NV  4*float  tight path-space bounding
                                              box around the path's
                                              covered fill region
        PATH_FILL_BOUNDING_BOX_NV    4*float  Conservative path-space
                                              bounding box around the
                                              path's covered fill region
        PATH_STROKE_BOUNDING_BOX_NV  4*float  Conservative path-space
                                              bounding box around the
                                              path's covered stroke region

    /param/ must be one of the tokens listed in Table 5.pathParameters
    or Table 6.readOnlyPathParameters; otherwise the INVALID_ENUM
    error is generated.  The parameters from Table 5.pathParameters
    always return a single (scalar) value.  The parameters from
    Table 6.readOnlyPathParameters a single (scalar) value for all the
    parameters but the PATH_*_BOUNDING_BOX_NV parameters; these bounding
    box parameters return a vector of 4 values.  These four values are
    the minimum (x1,y1) corner of the respective path-space bounding
    box and the maximum (x2,y2) corner of the respective path-space
    orthogonally aligned bounding box, returned in (x1,y1,x2,y2) order.
    (This guarantees x1<=x2 and y1<=y2.)  Float parameters queried by
    GetPathParameterivNV are rounded to the nearest integer (where values
    with a floating-point fraction of 0.5 round up).

    The PATH_OBJECT_BOUNDING_BOX_NV bounding box is intended to bound
    tightly the region of path space containing the path's outline.
    The PATH_FILL_BOUNDING_BOX_NV bounding box matches the rectangle
    region covered by the CoverFillPathNV command with the BOUNDING_BOX_NV
    /coverMode/.  With either the PATH_OBJECT_BOUNDING_BOX_NV or
    PATH_FILL_BOUNDING_BOX_NV bounding boxes of a path object, a point at
    (x,y) such that x<x1 or x>x2 or y<y1 or y>y2 is guaranteed to /not/
    be within the filled outline of the path.

    The PATH_STROKE_BOUNDING_BOX_NV bounding box matches the rectangle
    region covered by the CoverFillPathNV command with the BOUNDING_BOX_NV
    /coverMode/.  With the PATH_STROKE_BOUNDING_BOX_NV bounding box of
    a path object, a point at (x,y) such that x<x1 or x>x2 or y<y1 or
    y>y2 is guaranteed to /not/ be within the stroked region of the path.

    6.X.2. Path Object Varying Arrays Queries

    Path objects support a variable number of commands, coordinates,
    and dash lengths.

    The query

        void GetPathCommandsNV(uint path, ubyte *commands);

    returns the sequence of commands within the path object named /name/
    into the array named /commands/; the error INVALID_OPERATION is
    generated if /name/ is not an existing path object.  The number of
    commands returned is identical to the value of the path object's
    PATH_COMMAND_COUNT_NV parameter.  The application is responsible
    for ensuring /commands/ array has sufficient space.

    Any path commands specified with a character alias value (from Table
    5.pathCommands) is returned as the command's token value instead.

    The query

        void GetPathCoordsNV(uint path, float *coords);

    returns the sequence of coordinates within the path object named
    /name/ into the array named /coords/; the error INVALID_OPERATION
    is generated if /name/ is not an existing path object.  The number
    of commands returned is identical to the value of the path object's
    PATH_COORD_COUNT_NV parameter.  The application is responsible for
    ensuring /coords/ array has sufficient space.

    Boolean coordinates such as the large/small and sweep flags for arcs
    are always returned as 1.0 or 0.0 for true and false respectively.
    Other coordinates are returned as they were specified.

    The query

        void GetPathDashArrayNV(uint path, float *dashArray);

    returns the sequence of dash lengths within the path object named
    /name/ into the array named /coords/; the error INVALID_OPERATION is
    generated if /name/ is not an existing path object.  The number of
    dash lengths returned is identical to the value of the path object's
    PATH_DASH_ARRAY_COUNT_NV parameter.  The application is responsible
    for ensuring /dashArray/ has sufficient space.

    6.X.3. Path Object Glyph Typographic Queries

    GLYPH METRIC QUERIES

    To facilitate proper text layout, the command

        void GetPathMetricsNV(bitfield metricQueryMask,
                              sizei numPaths,
                              enum pathNameType, const void *paths,
                              uint pathBase,
                              sizei stride,
                              float *metrics);

    queries glyph metrics associated with a sequence of path objects
    specified by the /glyphBase/, /count/, /pathNameType/, and /paths/
    parameters.  Metrics are associated with path objects specified by
    PathGlyphsNV or PathGlyphRangeNV (see section 5.X.1.3).

    There are two kinds of metrics:

    *  Per-glyph metrics that are typically different for each glyph.

    *  Per-font face metrics that are identical for all glyphs belonging
       to a given font face.

    Per-font face metrics are aggregate metrics such as the maximum
    ascender or descender for all the glyphs in the font face.

    /metricQueryMask/ is a bitfield constructed from the bits listed
    in Table 6.perGlyphMetrics and Table 6.perFontFaceMetrics.  If a bit
    is set in /metricQueryMask/ not listed in these tables, the error
    INVALID_VALUE is generated.

    /stride/ is the byte (machine units) offset separating each group of
    returned metrics for a given path object.  If /stride/ is negative
    or /stride/ is not a multiple of the size of float in bytes (machine
    units), the INVALID_VALUE error is generated.  The INVALID_OPERATION
    error is generated if /stride/ divided by the size of float in bytes
    is not either zero or else greater than or equal to the number of
    metrics specified for querying in the metricQueryMask (based on the
    number of specified bits specified in the mask) times the size of
    float in bytes.  A /stride/ of zero is specially handled; the value
    zero is interpreted to indicate the number of bytes (machine units)
    such that the all the metrics are written in a tightly packed array,
    so the size of float in bytes times the number of specified bits in
    the /metricQueryMask/ bitfield.

    For path objects not created with either PathGlyphsNV or
    PathGlyphRangeNV or non-existent, all glyph metrics return -1.

    This metric information for a path object is /not/ updated if
    the commands or coordinates or parameters of that path object are
    changed.

    Figure 6.horizontalGlyphMetrics:  Horizontal Glyph Metrics

                ^
                |    xMin         xMax
                |     |            |
                |     |   width    |
                |     |<---------->|
                |     |            |
                |     +============+ - - - - - - - - - - - yMax
                |     I            I   ^               ^
                |     I            I   | hBearingY     |
                |     I            I   |               |
      hBearingX |---->I  GLYPH     I   |        height |
                |     I   OUTLINE  I   |               |
            ----O-----I------------I------*--->        |
               /|     I    HERE    I      |            |
              / |     I            I      |            v
        origin  |     +============+ - - -|- - - - - - - - yMin
                |                         |
                |------------------------>|
                |   hAdvance              |

    Figure 6.verticalGlyphMetrics:  Vertical Glyph Metrics

               vBearingX
              |<---------|   origin
              |          | /
              |          |/
    ---------------------O----------------------------->
              |          |                  |    |
              |          |       vBearingY  |    |
              |          |                  v    |
     yMax - - +================+ - - - - - - - - |
              I          |     I     ^           |
              I          |     I     |           |
              I    GLYPH |     I     |           |
              I     OUTLINE    I     | height    |
              I      HERE|     I     |           |
              I          |     I     |           |
              I          |     I     |           |
              I          |     I     v           | vAdvance
     yMin - - +================+ - - -           |
              |          |     |                 v
              |          * - - - - - - - - - - - -
              |          |     |
             xMin        v   xMax

    Table 6.perGlyphMetrics

                                                             Bit number
                                                 Glyph       from LSB
        Bit field name                           metric tag  in bitmask  Description (units in path space)
        ---------------------------------------  ----------  ----------  -------------------------------------------
        GLYPH_WIDTH_BIT_NV                       width       0           Glyph's width
        GLYPH_HEIGHT_BIT_NV                      height      1           Glyph's height
        GLYPH_HORIZONTAL_BEARING_X_BIT_NV        hBearingX   2           Left side bearing for horizontal layout
        GLYPH_HORIZONTAL_BEARING_Y_BIT_NV        hBearingY   3           Top side bearing for horizontal layout
        GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV  hAdvance    4           Advance width for horizontal layout
        GLYPH_VERTICAL_BEARING_X_BIT_NV          vBearingX   5           Left side bearing for vertical layout
        GLYPH_VERTICAL_BEARING_Y_BIT_NV          vBearingY   6           Top side bearing for vertical layout
        GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV    vAdvance    7           Advance height for vertical layout
        GLYPH_HAS_KERNING_BIT_NV                 -           8           True if glyph has a kerning table.

    Table 6.perFontFaceMetrics

                                                 Bit number
                                                 from LSB
        Bit field name                           in bitmask  Description (units in path space)
        ---------------------------------------  ----------  ---------------------------------------------------
        FONT_X_MIN_BOUNDS_BIT_NV                 16          Horizontal minimum (left-most) of the font bounding
                                                             box.  The font bounding box (this metric and the
                                                             next 3) is large enough to contain any glyph from
                                                             the font face.
        FONT_Y_MIN_BOUNDS_BIT_NV                 17          Vertical minimum (bottom-most) of the font bounding
                                                             box.
        FONT_X_MAX_BOUNDS_BIT_NV                 18          Horizontal maximum (right-most) of the font
                                                             bounding box.
        FONT_Y_MAX_BOUNDS_BIT_NV                 19          Vertical maximum (top-most) of the font bounding
                                                             box.
        FONT_UNITS_PER_EM_BIT_NV                 20          Number of units in path space (font units) per
                                                             Em square for this font face.  This is typically
                                                             2048 for TrueType fonts, and 1000 for PostScript
                                                             fonts.
        FONT_ASCENDER_BIT_NV                     21          Typographic ascender of the font face.  For font
                                                             formats not supplying this information, this value
                                                             is the same as FONT_Y_MAX_BOUNDS_BIT_NV.
        FONT_DESCENDER_BIT_NV                    22          Typographic descender of the font face (always a
                                                             positive value).  For font formats not supplying
                                                             this information, this value is the same as
                                                             FONT_Y_MIN_BOUNDS_BIT_NV.
        FONT_HEIGHT_BIT_NV                       23          Vertical distance between two consecutive baselines
                                                             in the font face (always a positive value).
        FONT_MAX_ADVANCE_WIDTH_BIT_NV            24          Maximal advance width for all glyphs in this font
                                                             face.  (Intended to make word wrapping computations
                                                             easier.)
        FONT_MAX_ADVANCE_HEIGHT_BIT_NV           25          Maximal advance height for all glyphs in this
                                                             font face for vertical layout.  For font formats
                                                             not supplying this information, this value is the
                                                             same as FONT_HEIGHT_BIT_NV.
        FONT_UNDERLINE_POSITION_BIT_NV           26          Position of the underline line for this font face.
                                                             This position is the center of the underling stem.
        FONT_UNDERLINE_THICKNESS_BIT_NV          27          Thickness of the underline of this font face.
        FONT_HAS_KERNING_BIT_NV                  28          True if font face provides a kerning table
        FONT_NUM_GLYPH_INDICES_BIT_NV            29          Number of glyph indices for this font.

    consulted by the GetPathSpacingNV command discussed below
    ("GLYPH SPACING QUERIES").

    The query

        void GetPathMetricRangeNV(bitfield metricQueryMask,
                                  uint firstPathName,
                                  sizei numPaths,
                                  sizei stride,
                                  float *metrics);

    is equivalent to

        int *array = malloc(sizeof(int)*numGlyphs);
        if (array) {
          for (int i=0; i<numGlyphs; i++) {
            array[i] = i + firstPathName;
          }
          GetPathMetricsNV(metricQueryMask,
                           numPaths,
                           INT, array,
                           pathBase,
                           stride, metrics);
          free(array);
        } else {
          // generate OUT_OF_MEMORY error
        }

    GLYPH SPACING QUERIES

    The query

        void GetPathSpacingNV(enum pathListMode,
                              sizei numPaths,
                              enum pathNameType, const void *paths,
                              uint pathBase,
                              float advanceScale,
                              float kerningScale,
                              enum transformType,
                              float *returnedSpacing);

    returns a sequence of /numPaths/-1 glyph spacing vectors in path
    space for spacing the specified sequence of path object pairs.
    The returned vectors are written into the /returnedSpacing/ array.

    /pathListMode/ must be one of ADJACENT_PAIRS_NV,
    ACCUM_ADJACENT_PAIRS_NV, or FIRST_TO_REST_NV; otherwise the
    INVALID_ENUM error is generated.

    If /numPaths/ is negative, the error INVALID_VALUE is generated

    /pathNameType/ determines the type of elements of the /paths/ array
    and must be one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, INT,
    UNSIGNED_INT, FLOAT, UTF8_NV, UTF16_NV, 2_BYTES, 3_BYTES, or 4_BYTES;
    otherwise the INVALID_ENUM error is generated.

    /transformType/ must be either TRANSLATE_X_NV or TRANSLATE_2D_NV;
    otherwise the INVALID_ENUM error is generated.

    In the absence of parameter errors, the following pseudo-code
    implements this query:

        double accumX = 0,
               accumY = 0;
        float returnX = 0,
              returnY = 0;
        uint firstPath;
        bool ok = getPathName(pathNameType, paths, pathBase, firstPath);
        if (!ok)
          return;  // stop early
        for (int i = 0; i<numPaths-1; i++) {
          uint secondPath;
          bool ok = getPathName(pathNameType, paths, pathBase, secondPath);
          if (!ok)
            return;  // stop early
          if (transformType == TRANSLATE_X_NV) {
            returnedSpacing[i] = returnX;
          } else {
            // transformType == TRANSLATE_2D_NV
            returnedSpacing[2*i  ] = returnX;
            returnedSpacing[2*i+1] = returnY;
          }
          float x = advanceScale * advanceX(firstPath) +
                    kerningScale * kerningX(firstPath,secondPath);
          float y = kerningScale * kerningY(firstPath,secondPath);
          if (pathListMode == ACCUM_ADJACENT_PAIRS_NV) {
            returnX = accumX;
            returnY = accumY;
            accumX += x;
            accumY += y;
          } else {
            returnX = x;
            returnY = y;
          }
          if (pathListMode != FIRST_TO_REST_NV) {
            firstPath = secondPath;
          }
        }

    The getPathName function is found in section 5.X.2.3 (Instanced Path
    Stenciling and Covering).

    The advance, kerningX, and kerningY functions operate as follows:

    The advance function returns the hAdvance metric of path object
    name passed to the function, but if the path object lacks glyph
    metrics, the difference between the horizontal bounds of the path
    object's bounding box (determined by PATH_OBJECT_BOUNDING_BOX_NV)
    are returned instead.  If the named path object passed to advance
    does not exist, zero is returned.

    The kerningX and kerningY functions return the X and Y kerning
    distances respectively between the character codes of the first
    (typically left) and second (typically right) path objects if they
    belong to the same font face; otherwise, zero is returned.  If the
    vertical kerning metrics are unavailable for the font face or either
    named path object does not exist, zero is returned for kerningY.
    (When the FONT_HAS_KERNING_BIT_NV or GLYPH_HAS_KERNING_BIT_NV glyph
    metrics are false for the first path object name, kerningX and
    kerningY must return zero.)

    Spacing information (horizontal advance or kerning) in a path object
    is not changed if the path's commands, coordinates, or parameters
    change--except in the case where the horizontal kerning value is
    determined by the first path's object bounding box.

    6.X.4. Path Object Geometric Queries

    The query

        boolean IsPointInFillPathNV(uint path,
                                    uint mask, float x, float y);

    computes the winding number of the path-space 2D (x,y) point given
    by /x/ and /y/ with respect to the path object named /path/ and
    returns TRUE if the winding count ANDed with /mask/ is non-zero;
    otherwise the query returns FALSE.  If the /mask/ parameter is zero,
    substitute the path object's PATH_FILL_MASK_NV parameter value
    when ANDing with the winding count.  The error INVALID_OPERATION is
    generated if /path/ does not exist.

    This point-inside computation occurs in /path space/ rather than in
    the window space as the StencilFillPathNV command operates.

    The query

        boolean IsPointInStrokePathNV(uint path,
                                      float x, float y);

    returns TRUE if the path-space 2D (x,y) point given by /x/ and
    /y/ is within the stroked region of the path object named /path/;
    otherwise the query returns FALSE.  The error INVALID_OPERATION is
    generated if /path/ does not exist.

    The stroked region's stroke width is specified by the path object's
    stroke width parameter.

    The stroked region is defined as in section 5.X.2.1 ("Path
    Stenciling") so accounts for the path object's current end cap,
    join style, and dashing parameters.

    This point-inside computation occurs in /path space/ rather than in
    the window space as the StencilStrokePathNV command operates.

    The query

        float GetPathLengthNV(uint path,
                              sizei startSegment, sizei numSegments);

    returns an approximation of the geometric length of a given portion
    of a path object named /path/.  The portion of the path measured is
    from the (0-indexed) /startSegment/ through the next /numSegments/.
    The returned length is measured in path-space units.  The error
    INVALID_OPERATION is generated if /path/ does not exist.

    The geometric length of the path's measured portion depends only
    on the path's commands and associated coordinates for the indicated
    range of segments and the respective coordinates of these segments.
    The geometric length of the path does not, for example, depend on
    the path's dashing parameters.

    The MOVE_TO_NV and RELATIVE_MOVE_TO_NV commands contribute zero
    units to the computed geometric length.  For all other path commands,
    a path segment's geometric length contribution /s/ is:

        s = int(sqrt(fx(t)^2+fy(t)^2), t, 0, 1)

    [[ int(f(t),t,a,b) computes the definite integration of the function
       f(t) over the interval [a,b]. ]]

    where /fx/ and /fy/ is the partial derivative of the command's
    respective path segment parametric function found in Table
    5.pathCommands.

    The return value, assuming no error, is the sum of all /s/ values
    for segments /startSegment/ through /startSegment/+/numSegments/-1
    inclusive.  If /numSegments/ is zero and no error is generated,
    0 is returned.

    The INVALID_VALUE error is generated in any of the following
    circumstances:

        *   /startSegment/ is negative,

        *   /numSegments/ is negative,

        *   /startSegment/+/numSegments/-1 is greater than the index of
            the final path segment.

    If an error occurs, -1.0 is returned.  When no error occurs, the
    return value is always non-negative.

    If /startSegment/ is zero and /numSegments/ is equal to the
    value of /path/'s PATH_COMMAND_COUNT_NV parameter and no error
    is generated, the value returned is identical to (equals) the value
    returned if GetPathParameterfvNV were used to query the value of
    /path/'s PATH_COMPUTED_LENGTH_NV parameter.

    The query

        boolean PointAlongPathNV(uint path,
                                 sizei startSegment, sizei numSegments,
                                 float distance,
                                 float *x, float *y,
                                 float *tangentX, float *tangentY);

    returns the point lying a given distance along a given portion of a
    path object specified by /path/ and the unit-length tangent vector
    at that point.  The boolean return value is TRUE if /distance/
    is within (inclusive) the arc length of the range of segments from
    /startSegment/ to /startSegment/+/numSegments/-1; otherwise FALSE
    is returned.

    The 2D point's (x,y) position is written to the values indicated
    by the /x/ and /y/ pointers respectively.  The tangent vector is
    written to the values indicated by the /tangentX/ and /tangentY/
    points.  However if /x/, /y/, /tangentX/, or /tangentY/ is a
    NULL pointer, no value is written to such NULL pointers.  Only the
    subpath consisting of the /numSegments/ path segments beginning with
    /startSegment/ (where the initial path segment has index 0) is used.
    PointAlongPathNV only considers this subpath.

    If /distance/ is less than or equal to zero, the starting point
    of the path is used (and the query returns FALSE).  If /distance/
    is greater than the path length (i.e., the value returned when the
    GetPathLengthNV query is called with the same /startSegment/ and
    /numSegments/ parameters), the final point along the subpath is used
    (and the query returns FALSE).

    The error INVALID_OPERATION is generated if /path/ does not exist.

    The error INVALID_VALUE is generated if /startSegment/
    or /numSegments/ are negative.  The error INVALID_VALUE is
    generated if /startSegment/ is greater than the index of /path/'s
    final path segment. The error INVALID_VALUE is generated if
    /startSegment/+/numSegments/-1 is less than zero or greater than
    the index of /path/'s final path segment.

    Because it is not possible in general to compute exact distances along
    a path, an implementation is not required to use exact computation
    even for segments where such computations are possible.

    Implementations are not required to compute distances exactly, as
    long as the satisfy the constraint that as /distance/ increases
    monotonically the returned point and tangent move forward
    monotonically along the path.

    Implementations should use the same distance-along-a-path algorithm
    for PointAlongPathNV as is used for dashing a stroked path.  (The dash
    count and dashing array state of the path object is irrelevant to
    the results of this query.)

    Where an implementation is able to determine that the point being
    queried lies exactly at a discontinuity or cusp, the incoming point
    and tangent should be returned.

    6.X.5. Path Color and Texture Coordinate Generation Queries

    The queries

        void GetPathColorGenivNV(enum color, enum pname, int *value);
        void GetPathColorGenfvNV(enum color, enum pname, float *value);

    return path color generation state.  /color/ must be one of
    PRIMARY_COLOR, PRIMARY_COLOR_NV, SECONDARY_COLOR_NV to return the
    requested color generation state for the primary, primary, and
    secondary color respectively.  /pname/ must be either PATH_GEN_MODE_NV,
    PATH_GEN_COLOR_FORMAT_NV, or PATH_GEN_COEFF_NV.

    If /pname/ is PATH_GEN_MODE_NV, the scalar value of the respective
    color's path generation mode is written to the value referenced by
    the /value/ pointer.

    If /pname/ is PATH_GEN_COLOR_FORMAT_NV, the scalar value of the
    respective color's path generation color format is written to the
    value reference by the /value/ pointer.

    If /pname/ is PATH_GEN_COEFF_NV, 16 coefficients for the respective
    color's path generation are written to the array referenced by the
    /value/ pointer.  Assuming no error is generated, 16 coefficients
    are written no matter what the path color generation mode is though
    coefficients not accessed by the indicated path color generation
    mode are returned as zero.

    The queries

        void GetPathTexGenivNV(enum texCoordSet, enum pname, int *value);
        void GetPathTexGenfvNV(enum texCoordSet, enum pname, float *value);

    return path texture coordinate set generation state.  /texCoordSet/
    indicates the texture coordinate set being queried and must be
    one of TEXTURE0 through TEXTUREn where /n/ is one less than the
    implementation-dependent value of MAX_TEXTURE_COORDS; otherwise
    INVALID_ENUM is generated.  /pname/ must be either PATH_GEN_MODE_NV
    PATH_GEN_COMPONENTS_NV, or PATH_GEN_COEFF_NV.

    If /pname/ is PATH_GEN_MODE_NV, the scalar value of the respective
    texture coordinate set's path generation mode is written to the
    value referenced by the /value/ pointer.

    If /pname/ is PATH_GEN_COMPONENTS_NV, the scalar value of the
    respective texture coordinate set's path generation number of
    components is written to the value reference by the /value/ pointer.

    If /pname/ is PATH_GEN_COEFF_NV, 16 coefficients for the respective
    texture coordinate set's path generation are written to the array
    referenced by the /value/ pointer.  Assuming no error is generated, 16
    coefficients are written no matter what the path texture generation
    mode is though coefficients not accessed by the indicated path
    texture generation mode are returned as zero.

Additions to the AGL/GLX/WGL Specifications

    Path objects are shared between AGL/GLX/WGL rendering contexts if
    and only if the rendering contexts share display lists.  No change
    is made to the AGL/GLX/WGL API.

    Changes to path objects shared between multiple rendering contexts
    will be serialized (i.e., the changes, queries, deletions, and
    stencil/cover operations will occur in a specific order).

Additions to the OpenGL Shading Language

    None

GLX Protocol

    XXX

Errors

    XXX

Dependencies on ARB_program_interface_query.

    When ARB_program_interface_query is not supported, all references to
    FRAGMENT_INPUT_NV and ProgramPathFragmentInputGenNV should be ignored.

Dependencies on Core Profile and OpenGL ES

    When NV_path_rendering is advertised, the following functionality
    must be supported...

    References to the following commands should be ignored:

        PathColorGenNV
        PathTexGenNV
        PathFogGenNV
        GetPathColorGenivNV
        GetPathColorGenfvNV
        GetPathTexGenivNV
        GetPathTexGenfvNV

    including the state set and queried by these commands.

    References to the following tokens should be ignored:

        PATH_FOG_GEN_MODE_NV
        PRIMARY_COLOR
        PRIMARY_COLOR_NV
        SECONDARY_COLOR_NV
        PATH_GEN_COLOR_FORMAT_NV

    References to the following GLSL built-in variables should be ignored:

        gl_TexCoord
        gl_MaxTextureCoords
        gl_Color
        gl_FrontColor
        gl_BackColor
        gl_SecondaryColor
        gl_FrontSecondaryColor
        gl_BackSecondaryColor
        gl_FogFragCoord

    The following types are defined as alias to the GL tokens:

        2_BYTES_NV                                      0x1407 // from GL compat
        3_BYTES_NV                                      0x1408 // from GL compat
        4_BYTES_NV                                      0x1409 // from GL compat
        EYE_LINEAR_NV                                   0x2400 // from GL compat
        OBJECT_LINEAR_NV                                0x2401 // from GL compat
        CONSTANT_NV                                     0x8576 // from GL compat

    The following entry points (specified by the EXT_direct_state_access
    extension) MUST be supported:

        void MatrixLoadfEXT(enum matrixMode, const float *m);
        void MatrixLoaddEXT(enum matrixMode, const double *m);

        void MatrixMultfEXT(enum matrixMode, const float *m);
        void MatrixMultdEXT(enum matrixMode, const double *m);

        void MatrixLoadTransposefEXT(enum matrixMode, const float *m);
        void MatrixLoadTransposedEXT(enum matrixMode, const float *m);

        void MatrixMultTransposefEXT(enum matrixMode, const float *m);
        void MatrixMultTransposedEXT(enum matrixMode, const float *m);

        void MatrixLoadIdentityEXT(enum matrixMode);

        void MatrixRotatefEXT(enum matrixMode, float angle,
                              float x, float y, float z);
        void MatrixRotatedEXT(enum matrixMode, double angle,
                              double x, double y, double z);

        void MatrixScalefEXT(enum matrixMode,
                             float x, float y, float z);
        void MatrixScaledEXT(enum matrixMode,
                             double x, double y, double z);

        void MatrixTranslatefEXT(enum matrixMode,
                                 float x, float y, float z);
        void MatrixTranslatedEXT(enum matrixMode,
                                 double x, double y, double z);

        void MatrixOrthoEXT(enum matrixMode, double l, double r,
                            double b, double t, double n, double f);
        void MatrixFrustumEXT(enum matrixMode, double l, double r,
                              double b, double t, double n, double f);

        void MatrixPushEXT(enum matrixMode);
        void MatrixPopEXT(enum matrixMode);

    These commands must support the PATH_PROJECTION_NV and PATH_MODELVIEW_NV
    tokens for matrixMode.  The associated modelview and projection matrix
    state, including matrix stacks, MUST be supported.  These token values
    for matrices are supported:

        PATH_PROJECTION_NV                                    0x1701
        PATH_MODELVIEW_NV                                     0x1700

        PATH_MODELVIEW_STACK_DEPTH_NV                         0x0BA3
        PATH_MODELVIEW_MATRIX_NV                              0x0BA6
        PATH_MAX_MODELVIEW_STACK_DEPTH_NV                     0x0D36
        PATH_TRANSPOSE_MODELVIEW_MATRIX_NV                    0x84E3
        PATH_PROJECTION_STACK_DEPTH_NV                        0x0BA4
        PATH_PROJECTION_MATRIX_NV                             0x0BA7
        PATH_MAX_PROJECTION_STACK_DEPTH_NV                    0x0D38
        PATH_TRANSPOSE_PROJECTION_MATRIX_NV                   0x84E4

    The last 8 tokens are supported by GetFloatv, GetIntegerv, GetDoublev
    to query associated path modelview and projection state.

    The values of sc, tc, rc, and qc discussed in section 5.X.2.2 "Path
    Covering" are always zero in a Core profile context as these values
    involve deprecated state.

New State

 -- NEW table 6.X, "Path (state per context)" following Table 6.33, "Renderbuffer"

    Get Value                            Type     Get Command          Initial Value   Description               Section       Attribute
    -----------------------------------  -------  -------------------  --------------  ------------------------  ------------  --------------
    PATH_GEN_MODE_NV                     2xZ4     GetPathColorGenivNV  NONE            path's color              6.X.5         lighting
                                                                                       generation mode
    PATH_GEN_COLOR_FORMAT_NV             2xZ6     GetPathColorGenivNV  NONE            path's color              6.X.5         lighting
                                                                                       generation color format
    PATH_GEN_COEFF_NV                    2x16xR   GetPathColorGenfvNV  all 0's         path's color gen mode     6.X.5         lighting
                                                                                       generation coefficients
    PATH_GEN_MODE_NV                     nxZ4     GetPathTexGenivNV    NONE            path's texture            6.X.5         texture
                                                                                       generation mode
    PATH_GEN_COMPONENTS_NV               nxZ5     GetPathTexGenivNV    0               path's texture            6.X.5         texture
                                                                                       generation number of
                                                                                       components
    PATH_GEN_COEFF_NV                    nx16xR   GetPathTexGenfvNV    all 0's         path's texture            6.X.5         texture
                                                                                       generation coefficients
    PATH_FOG_GEN_MODE_NV                 Z2       GetIntegerv          FRAGMENT_DEPTH  path's fog generation     5.X.2.1       fog
                                                                                       mode
    PATH_ERROR_POSITION_NV               Z        GetIntegerv          -1              last path string          5.X.1.2       -
                                                                                       error position
    PATH_STENCIL_FUNC_NV                 Z8       GetIntegerv          ALWAYS          path stenciling function  5.X.2.1       stencil-buffer
    PATH_STENCIL_REF_NV                  Z+       GetIntegerv          0               path stenciling           5.X.2.1       stencil-buffer
                                                                                       reference value
    PATH_STENCIL_VALUE_MASK_NV           Z+       GetIntegerv          1's             path stencil read mask    5.X.2.1       stencil-buffer
    PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV  R        GetFloatv            0               path stencil depth        5.X.2.1       polygon
                                                                                       offset factor
    PATH_STENCIL_DEPTH_OFFSET_UNITS_NV   R        GetFloatv            0               path stencil depth        5.X.2.1       polygon
                                                                                       units factor
    PATH_COVER_DEPTH_FUNC_NV             Z8       GetIntegerv          LESS            path covering depth       5.X.2.2       depth-buffer
                                                                                       function

    where n is the implementation-dependent number of texture coordinate
    sets (MAX_TEXTURE_COORDS).

 -- NEW table 6.Y, "Path (state per path object)" following Table 6.X

    Get Value                        Type     Get Command           Initial Value         Description                       Section       Attribute
    -------------------------------  -------  --------------------  --------------------  --------------------------------  ------------  ---------
    -                                nxZ8*    GetPathCommandsNV     -                     path's sequence of path commands  6.X.1         -
    -                                mxR      GetPathCoordsNV       -                     path's sequence of path           6.X.1         -
                                                                                          coordinates
    -                                cxR      GetPathDashArrayNV    -                     dash array contents               5.X.1.5       -
    PATH_COMMAND_COUNT_NV            Z+       GetPathParameterivNV  -                     path's count of path commands     6.X.1         -
    PATH_COORD_COUNT_NV              Z+       GetPathParameterivNV  -                     path's count of path coordinates  6.X.1         -
    PATH_COMPUTED_LENGTH_NV          R+       GetPathParameterfvNV  -                     GL's calculation of the path's    6.X.1         -
                                                                                          length
    PATH_STROKE_WIDTH_NV             R+       GetPathParameterfvNV  1.0                   stroke width                      5.X.1.5       -
    PATH_INITIAL_END_CAP_NV          Z4       GetPathParameterivNV  FLAT                  path's initial end cap style      5.X.1.5       -
    PATH_TERMINAL_END_CAP_NV         Z4       GetPathParameterivNV  FLAT                  path's terminal end cap style     5.X.1.5       -
    PATH_JOIN_STYLE_NV               Z4       GetPathParameterivNV  MITER_REVERT_NV       path's join style                 5.X.1.5       -
    PATH_MITER_LIMIT_NV              R+       GetPathParameterfvNV  4                     path's miter limit                5.X.1.5       -
    PATH_DASH_ARRAY_COUNT_NV         Z+       GetPathParameterivNV  0                     path's count of dashes in the     5.X.1.5       -
                                                                                          path's dash array                 5.X.1.5       -
    PATH_DASH_OFFSET_NV              R        GetPathParameterfvNV  0.0                   path's dash offset                5.X.1.5       -
    PATH_DASH_OFFSET_RESET_NV        Z2       GetPathParameterivNV  MOVE_TO_CONTINUES_NV  path's dash offset reset          5.X.1.5       -
    PATH_CLIENT_LENGTH_NV            R+       GetPathParameterfvNV  0.0                   the client-supplied calculation   5.X.1.5       -
                                                                                          of the path's length
    PATH_INITIAL_DASH_CAP_NV         Z4       GetPathParameterivNV  FLAT                  path's initial dash cap style     5.X.1.5       -
    PATH_TERMINAL_DASH_CAP_NV        Z4       GetPathParameterivNV  FLAT                  path's terminal dash cap style    5.X.1.5       -
    PATH_FILL_MODE_NV                Z3       GetPathParameterivNV  COUNT_UP_NV           path's default fill mode          5.X.1.5       -
    PATH_FILL_MASK_NV                Z+       GetPathParameterivNV  all 1's               path's default fill mask          5.X.1.5       -
    PATH_FILL_COVER_MODE_NV          Z4       GetPathParameterivNV  CONVEX_HULL_NV        path's default fill cover mode    5.X.1.5       -
    PATH_STROKE_COVER_MODE_NV        Z4       GetPathParameterivNV  CONVEX_HULL_NV        path's default stroke cover mode  5.X.1.5       -
    PATH_STROKE_MASK_NV              Z+       GetPathParameterivNV  all 1's               path's default stroke mask        5.X.1.5       -
    PATH_STROKE_BOUND_NV             R[0,1]   GetPathParameterfvNV  0.2 (20%)             path's stroke approximation       5.X.1.5       -
                                                                                          bound
    PATH_OBJECT_BOUNDING_BOX_NV      R4       GetPathParameterfvNV  -                     path's outline bounding box       6.X.1         -
    PATH_FILL_BOUNDING_BOX_NV        R4       GetPathParameterfvNV  -                     path's fill bounding box          6.X.1         -
    PATH_STROKE_BOUNDING_BOX_NV      R4       GetPathParameterfvNV  -                     path's stroke bounding box        6.X.1         -

    where n is the number of commands in a path object, m is the number
    of coordinates in a path object, and c is the dash array count of
    a path object.

 -- NEW table 6.Z, "Path Glyph Metrics (state per path object)" following Table 6.Z

    Get Value                                Type     Get Command            Initial Value  Description                  Section       Attribute
    ---------------------------------------  -------  ---------------------  -------------  ---------------------------  ------------  ---------
    GLYPH_WIDTH_BIT_NV                       R        GetPathMetricsNV  see 5.X.1.3    path's glyph width                6.X.3         -
    GLYPH_HEIGHT_BIT_NV                      R        GetPathMetricsNV  see 5.X.1.3    path's glyph height               6.X.3         -
    GLYPH_HORIZONTAL_BEARING_X_BIT_NV        R        GetPathMetricsNV  see 5.X.1.3    path's glyph left side bearing    6.X.3         -
                                                                                       for horizontal layout
    GLYPH_HORIZONTAL_BEARING_Y_BIT_NV        R        GetPathMetricsNV  see 5.X.1.3    path's glyph top side bearing     6.X.3         -
                                                                                       for horizontal layout
    GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV  R        GetPathMetricsNV  see 5.X.1.3    path's glyph advance width        6.X.3         -
                                                                                       for horizontal layout
    GLYPH_VERTICAL_BEARING_X_BIT_NV          R        GetPathMetricsNV  see 5.X.1.3    path's glyph left side bearing    6.X.3         -
                                                                                       for vertical layout
    GLYPH_VERTICAL_BEARING_Y_BIT_NV          R        GetPathMetricsNV  see 5.X.1.3    path's glyph top side bearing     6.X.3         -
                                                                                       for vertical layout
    GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV    R        GetPathMetricsNV  see 5.X.1.3    path's glyph advance width        6.X.3         -
                                                                                       for vertical layout
    GLYPH_HAS_KERNING_BIT_NV                 B        GetPathMetricsNV  see 5.X.1.3    whether or not glyph has kerning  6.X.3         -
                                                                                       table

 -- NEW table 6.W, "Path Font Metrics (state per path object though identical for glyphs from the same font face)" following Table 6.Z

    Get Value                        Type     Get Command       Initial Value  Description                              Section       Attribute
    -------------------------------  -------  ----------------  -------------  ---------------------------------------  ------------  ---------
    FONT_X_MIN_BOUNDS_BIT_NV         R        GetPathMetricsNV  see 5.X.1.3    path's horizontal minimum (left-most)    6.X.3         -
                                                                               of the font bounding box
    FONT_Y_MIN_BOUNDS_BIT_NV         R        GetPathMetricsNV  see 5.X.1.3    path's vertical minimum (bottom-most)    6.X.3         -
                                                                               of the font bounding box
    FONT_X_MAX_BOUNDS_BIT_NV         R        GetPathMetricsNV  see 5.X.1.3    path's horizontal maximum (right-most)   6.X.3         -
                                                                               of the font bounding box
    FONT_Y_MAX_BOUNDS_BIT_NV         R        GetPathMetricsNV  see 5.X.1.3    path's vertical maximum (top-most)       6.X.3         -
                                                                               of the font bounding box
    FONT_UNITS_PER_EM_BIT_NV         R        GetPathMetricsNV  see 5.X.1.3    path's number of units in path space     6.X.3         -
                                                                               (font units) per Em square for font
                                                                               face
    FONT_ASCENDER_BIT_NV             R        GetPathMetricsNV  see 5.X.1.3    path's typographical ascender (in font   6.X.3         -
                                                                               units) of the font face
    FONT_DESCENDER_BIT_NV            R        GetPathMetricsNV  see 5.X.1.3    path's typographical descender (in font  6.X.3         -
                                                                               units) of the font face
    FONT_HEIGHT_BIT_NV               R+       GetPathMetricsNV  see 5.X.1.3    path's font face vertical distance       6.X.3         -
                                                                               between two consecutive baselines
                                                                               (in font units)
    FONT_MAX_ADVANCE_WIDTH_BIT_NV    R        GetPathMetricsNV  see 5.X.1.3    path's maximal advance width (in font    6.X.3         -
                                                                               units) for all glyphs in font face
    FONT_MAX_ADVANCE_HEIGHT_BIT_NV   R        GetPathMetricsNV  see 5.X.1.3    path's maximal advance height (in font   6.X.3         -
                                                                               units) for all glyphs in font face
                                                                               for vertical layout
    FONT_UNDERLINE_POSITION_BIT_NV   R        GetPathMetricsNV  see 5.X.1.3    path's position (in font units) of the   6.X.3         -
                                                                               center of underline line for font face
    FONT_UNDERLINE_THICKNESS_BIT_NV  R        GetPathMetricsNV  see 5.X.1.3    thickness (in font units) of the         6.X.3         -
                                                                               underline for font face
    FONT_HAS_KERNING_BIT_NV          B        GetPathMetricsNV  see 5.X.1.3    whether or not glyph has kerning         6.X.3         -
                                                                               table
    FONT_NUM_GLYPH_INDICES_BIT_NV    Z+       GetPathMetricsNV  see 5.X.1.3    number of glyph indices in font face     6.X.3         -

    Increment "n" in the Type field of the "Program Interface State"
    table by 1 to correspond to the FRAGMENT_INPUT_NV program interface.

    Add the following rows to the table labeled "Program Object Resource
    State" (only fragment input resources support this state):

                                                        Initial
    Get Value               Type  Get Command           Value      Description                                  Sec.
    ----------------------  ----  --------------------  ---------  -------------------------------------------  -----
    PATH_GEN_MODE_NV         Z4    GetProgramResourceiv  NONE       Path fragment input generation mode
    PATH_GEN_COMPONENTS_NV   Z5    GetProgramResourceiv  0          Number of path fragment input components
    PATH_GEN_COEFF_NV        16*R  GetProgramResourceiv  all zeros  Path fragment input generation coefficients

New Implementation Dependent State

    None

NVIDIA Implementation Details

 -- API revision 1.0

    Released in NVIDIA Driver Release 275.33 (June 2011).

 -- API revision 1.1

    Follow-on release (circa September 2011) adds these path
    commands for ISO PDF 32000 support:

        GL_RESTART_PATH_NV
        GL_DUP_FIRST_CUBIC_CURVE_TO_NV
        GL_DUP_LAST_CUBIC_CURVE_TO_NV
        GL_RECT_NV

    These path commands are not operational (generate GL_INVALID_ENUM
    errors) if used in 275.xx or 280.xx drivers.

    Follow-on release (circa September 2011) adds these transformType
    parameters:

        GL_NONE
        GL_TRANSLATE_3D_NV
        GL_AFFINE_3D_NV
        GL_TRANSPOSE_AFFINE_3D_NV

    These transformType tokens are not operational (generate
    GL_INVALID_ENUM errors) if used in 275.xx or 280.xx drivers.

 -- API revision 1.2

    Follow-on release (circa December 2013) adding these commands:

        void glMatrixLoad3x2fNV(GLenum matrixMode, const GLfloat *m);
        void glMatrixLoad3x3fNV(GLenum matrixMode, const GLfloat *m);
        void glMatrixLoadTranspose3x3fNV(GLenum matrixMode, const GLfloat *m);

        void glMatrixMult3x2fNV(GLenum matrixMode, const GLfloat *m);
        void glMatrixMult3x3fNV(GLenum matrixMode, const GLfloat *m);
        void glMatrixMultTranspose3x3fNV(GLenum matrixMode, const GLfloat *m);

        void glStencilThenCoverFillPathNV(GLuint path, GLenum fillMode,
                                          GLuint mask, GLenum coverMode);
        void glStencilThenCoverStrokePathNV(GLuint path, GLint reference,
                                            GLuint mask, GLenum coverMode);
        void glStencilThenCoverFillPathInstancedNV(GLsizei numPaths,
                                                   GLenum pathNameType,
                                                   const void *paths,
                                                   GLuint pathBase,
                                                   GLenum fillMode, uint mask,
                                                   GLenum coverMode,
                                                   GLenum transformType,
                                                   const GLfloat *transformValues);
        void glStencilThenCoverStrokePathInstancedNV(GLsizei numPaths,
                                                     GLenum pathNameType,
                                                     const void *paths,
                                                     GLuint pathBase,
                                                     GLint reference, uint mask,
                                                     GLenum coverMode,
                                                     GLenum transformType,
                                                     const GLfloat *transformValues);
        enum glPathGlyphIndexRangeNV(GLenum fontTarget,
                                     const void *fontName,
                                     GLbitfield fontStyle,
                                     GLuint pathParameterTemplate,
                                     GLfloat emScale,
                                     GLuint baseAndCount[2]);

    If the window system's GetProcAddress mechanism for GL commands returns
    NULL for these function names, these API revision 1.2 features are
    not available.  Likewise the these tokens are not supported either.

        GL_ROUNDED_RECT_NV
        GL_RELATIVE_ROUNDED_RECT_NV
        GL_ROUNDED_RECT2_NV
        GL_RELATIVE_ROUNDED_RECT2_NV
        GL_ROUNDED_RECT4_NV
        GL_RELATIVE_ROUNDED_RECT4_NV
        GL_ROUNDED_RECT8_NV
        GL_RELATIVE_ROUNDED_RECT8_NV
        GL_RELATIVE_RECT_NV

    These tokens may be returned by glPathGlyphIndexRangeNV:

        GL_FONT_GLYPHS_AVAILABLE_NV
        GL_FONT_TARGET_UNAVAILABLE_NV
        GL_FONT_UNAVAILABLE_NV
        GL_FONT_UNINTELLIGIBLE_NV

 -- API revision 1.3

    Follow-on release (circa May 2014, first appearing in the 337.88
    drivers) adding these commands:

    These new path commands:

        GL_CONIC_CURVE_TO_NV
        GL_RELATIVE_CONIC_CURVE_TO_NV
        GL_RELATIVE_RECT_NV

    New path glyph metric query:

        GL_FONT_NUM_GLYPH_INDICES_BIT_NV

    New return values from glyph index path specification commands:

        GL_FONT_UNINTELLIGIBLE_NV
        GL_STANDARD_FONT_FORMAT_NV

    New programInferface token:

        FRAGMENT_INPUT_NV

    New (aliased) matrix tokens for ES support:

        PATH_PROJECTION_NV
        PATH_MODELVIEW_NV

        PATH_MODELVIEW_STACK_DEPTH_NV
        PATH_MODELVIEW_MATRIX_NV
        PATH_MAX_MODELVIEW_STACK_DEPTH_NV
        PATH_TRANSPOSE_MODELVIEW_MATRIX_NV
        PATH_PROJECTION_STACK_DEPTH_NV
        PATH_PROJECTION_MATRIX_NV
        PATH_MAX_PROJECTION_STACK_DEPTH_NV
        PATH_TRANSPOSE_PROJECTION_MATRIX_NV

    New glyph index path specification commands:

        enum glPathGlyphIndexArrayNV(GLuint firstPathName,
                                     GLenum fontTarget,
                                     const void *fontName,
                                     GLbitfield fontStyle,
                                     GLuint firstGlyphIndex,
                                     GLsizei numGlyphs,
                                     GLuint pathParameterTemplate,
                                     GLfloat emScale);
        enum glPathMemoryGlyphIndexArrayNV(GLuint firstPathName,
                                           GLenum fontTarget,
                                           GLsizeiptr fontSize,
                                           const void *fontData,
                                           GLsizei faceIndex,
                                           GLuint firstGlyphIndex,
                                           GLsizei numGlyphs,
                                           GLuint pathParameterTemplate,
                                           GLfloat emScale);

    GLSL-related commands:

        void glProgramPathFragmentInputGenNV(GLuint program,
                                             GLint location,
                                             GLenum genMode,
                                             GLint components,
                                             const GLfloat *coeffs);

        void glGetProgramResourcefvNV(GLuint program, GLenum programInterface,
                                      GLuint index, GLsizei propCount,
                                      const GLenum *props, GLsizei bufSize,
                                      GLsizei *length, GLfloat *params);

    If the window system's GetProcAddress mechanism for GL commands returns
    NULL for these function names, these API revision 1.3 features are
    not available.  Likewise the these tokens are not supported either.

 -- Performance improvements:

    Release 304.xx and on substantially improves the performance of
    path rendering stencil and cover operations on NVIDIA Fermi- and
    Kepler-based GPUs (GeForce 400 Series and on).

    Release 314.xx improves the performance of initially specifying or
    modifying a path object prior to stenciling or covering the paths.

 -- Bugs:

    Due to NVIDIA driver bug 1315267, path objects were not actually
    shared among contexts prior to Driver release 320.xx (July 2013).

Issues

    1.  What should this extension be called?

        RESOLVED:  NV_path_rendering

        The extension adds an entirely new rendering paradigm for filled
        and stroked paths, hence "path rendering".

        "path" alone was considered but deemed to vague.

    2.  Should this extension support specifying paths based on glyphs in fonts?

        RESOLVED:  Yes.

        There are several problems solved by including first-class path
        specification via glyphs in fonts.

        1)  Support for glyphs from fonts are an expected part of nearly
        all path rendering systems.  Not including glyph support will force
        all path rendering applications to build their own glyph system.

        2)  Fonts, particularly for Asian languages, can be large.
        By putting glyph specification from fonts directly into
        the extension, implementations will have the opportunity to
        cache commonly loaded font glyphs, including shared on-GPU
        representations.

        3)  Also because fonts have many glyphs, first-pass specification
        of a range of glyphs allows the GL implementation to load glyphs
        sparsely in response to use.  It isn't appropriate to burden
        applications with the burden of properly caching large sets of
        glyphs from fonts.  So while Unicode glyphs 0 through 2^21-1
        might be loaded for an entire Unicode font, the GL implementation
        could only actually load queried and used path objects.

        4)  Locating font files tends to be very system-specific.  To the
        extent OpenGL supports cross-platform rendering, minimizing
        system-specific aspects of rendering increases the cross-platform
        nature of OpenGL applications.

        5)  I still feel bad about glutBitmapCharacter and
        glutStrokeCharacter being so lame; I thought something better
        would take their place but nothing has.

    3.  Should this extension provide a one-shot (single-pass) way to fill
        and stroke path objects?

        RESOLVED:  No.

        The two-pass decoupling of path rendering into stenciling and
        covering operations has lots of advantages.

        Some of the advantages are:

        1)  The cover step has complete control over how the fragment
            shader is configured.  GLSL, assembly, or fixed-function
            (glTexEnv, glFog, etc.) fragment shading can all be used
            without conflating the path's coverage determination with
            the shading.

        1a) If shading resources are used to implement the path coverage
            determination such as interpolants or textures, these
            resources aren't over-subscribed as could occur in a
            one-step API.

        2)  GPUs can accelerate stencil-only rendering during the stencil
            step in ways that are rasterization and bandwidth efficient.

        3)  Path rendering standards all allow a rendered path to be clipped
            by another arbitrary (clipping) path.  This can even be
            done recursively sometimes.  When the stencil coverage
            determination is a separate step from the shading, such
            clipping operations are easy to accomplish as simply multiple
            stenciled stencil steps.  Otherwise clipping a path to another
            path is a complex intersection and re-tessellation task.

        4)  A two-step stencil, then cover" approach makes it
            straightforward to guarantee that pixels and samples are
            only visited once per path rendering as path rendering
            standards require.

        5)  Unconventional but efficient algorithms such as reverse
            Painter's algorithm are straightforward to implement when
            stencil and covering steps are decoupled.  In this case,
            the stencil buffer simply never allows a pixel to be shaded
            a second time once covered.

        6)  Dilations and erosions can be performed with the two-step
            approach.  You can fill a shape and then stroke the shape
            to dilate the shape.  Then cover with both fill and stroking.

        7)  Novel stroking effects such as pin-striping are easy to
            accomplish.  You can stroke a path with a stroke width of 7.5
            to write stencil to 1 and then stroke the same curve with
            a stroke width of 3.1 to write a stencil of 0.  Then cover
            stroked path with a stroke width of 7.5 and accomplish the
            pen-striping.

    4.  What string formats should be supported for paths?

        UNRESOLVED:  Definitely SVG and PostScript.  Perhaps Silverlight?

        Silverlight's path syntax is very similar to SVG but allows
        infinity values and the specification of the fill mode.

        Adobe's Type 2 charstring format, part of Adobe's Compact
        Font Format (CFF) standard, provides yet another encoding
        of a path outline.  This is a binary, rather than textual,
        format that exists within OpenType and Type 2 font formats.
        It includes glyph hinting information.  The utility of accepting
        the Type 2 charstring format is not sufficient for inclusion for
        a number of reasons.  Content creation tools don't target this
        format for arbitrary path descriptions.  This extension already
        provides commands (glPathGlyphsNV and glPathGlyphRangeNV) for
        specifying path objects from font glyphs.  And the font hinting
        information the format provides would just be ignored.

    5.  Should there be a query to return a path as a string?

        RESOLVED: No, returning dynamic strings of variable length is too hard.

        Unlike parsing which is straightforward but slightly difficult,
        building a string from the results of glGetPathCommandsNV and
        glGetPathCoordsNV is not hard.  But there's no one "right"
        way to build a string for a given path.

        There are  various string encodings of varying compactness and
        readability.  How much precision is really required for converting
        a floating-point coordinate to a string representation varies?

    6.  Should path rendering allow per-vertex specification of attributes?

        RESOLVED:  No.

        There is no allowance for the specification of interpolants
        (colors, texture coordinates, etc.) specified per control point.
        Assigning per-vertex values to control points doesn't really
        make sense in the context of path rendering.  Instead a mechanism
        for generating color, texture coordinate, and fog generation as
        a linear function of object space.

        The glPathTexGenNV, glPathColorGenNV, and glPathFogGenNV commands
        provide this mechanism.

        glPathColorGenNV, glPathTexGenNV, and glPathFogGenNV
        provide a way to specify coefficients for plane equations based
        on the object-space or eye-space (x,y,1) position of a fragment
        generating by covering a filled or stroked path.

        For those used to conventional 3D graphics where geometry is
        defined by meshes of triangles, not having per-vertex attributes
        sounds really strange.  But this is the natural situation for
        path rendering.  Paths do not really have vertices but rather
        control points.

    7.  Should path rendering use the existing texture coordinate
        generation state (glTexGen)?

        RESOLVED:  No, this extension should have its own path-specific
        texture coordinate generation state controlled by glPathColorGenNV
        and glPathTexGenNV.

        The existing texture coordinate generation state has modes such
        as sphere, normal, and reflection mapping that make no sense for
        path rendering (since there are no per-vertex normals).

        Also it is very desirable to keep the per-vertex attribute
        computations (normal transformation, lighting, texture coordinate
        generation) completely separate from the varying computations
        for path rendering.  This means the vertex processing program
        needed for path rendering isn't changed by state updates intended
        to control geometric and image primitives.

    8.  How does path rendering work if all the fixed-function state,
        particularly the modelview and projection matrices and named vertex
        attributes (primary color, etc.) have been deprecated?

        RESOLVED:  ARB_compatibility (for OpenGL 3.1) or the Compatibility
        profile (for OpenGL 3.2 and up) is useful and supports the
        glPathColorGenNV, glPathTexGenNV, and glPathFogGenNV commands
        to interact properly with fixed-function OpenGL.

        NV_path_rendering assumes that the modelview and projection
        matrices combine to transform the path into clip space.
        Without these matrices, there's no way to get the path
        transformed.  Therefore these matrices are introduced through
        EXT_direct_state_access commands when only the Core profile is
        supported.

        Without ARB_compatibility or the Compatibility profile, there is
        no way for GLSL to access built-in varyings as these have been
        deprecated.  This means generated or passed-through colors and
        texture coordinate sets are inaccessible.  There's also no longer
        a way to compile a fragment shader that doesn't have a vertex
        shader.  The ARB_separate_shader_objects extension (core in OpenGL
        4.1) now allows a fragment shader to be specified in a program
        object with a vertex shader.  The ARB_program_interface_query
        extension (core in OpenGL 4.3) allows queries to specific program
        object resources.  The glProgramPathFragmentInputGenNV provides
        a means, in combination with the ARB_separate_shader_objects and
        ARB_program_interface_query extensions, to configure fragment
        input generation for GLSL fragment shaders use during the "cover"
        step of path rendering without reference to fixed-function
        mechanisms.

        See the "Dependencies on Core Profile and OpenGL ES" section
        and issue 133 for more details about the Core profile support.

    9.  How does a GLSL fragment shader processing fragment generated by
        covering path access fragment varyings?

        RESOLVED:  The obvious way is to used the gl_TexCoord[], gl_Color,
        and gl_SecondaryColor built-in varyings for texture coordinate
        sets, primary color, and secondary color respectively.

        Any user-specified varyings will be undefined since there is no
        upstream geometry or vertex shader to write them.

    10. How should the command token values be assigned?

        RESOLVED:  Consistent with OpenVG's enumeration values but ALSO using
        the SVG command characters too.

        The two token addition (missing from OpenVG's supported commands)
        are relative and absolute 7-component partial elliptical arc
        tokens (GL_ARC_TO_NV and GL_RELATIVE_ARC_TO_NV) that include the
        large/small and sweep flags as coordinates.  These corresponds
        to the SVG 'arcto' commands.

        Using character codes, in addition to tokens, allows simpler
        path descriptions coded with C character arrays (strings) such
        as "MLLCz" instead of the equivalent verbose aggregate array
        initializer { GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV,
        GL_CUBIC_CURVE_TO_NV, GL_CLOSE_PATH_NV }.

        Also note there are NO character codes for the eight 5-component
        partial elliptical arc commands because these commands lack
        exact analogues in the SVG path command syntax.

        There are also commands corresponding to PostScript's circular arc
        commands (arc, arcn, and arct), also without character aliases.

        Unfortunately the path command token values do NOT match the
        SVGPathSeg interface path segment type values because these
        values overlap with the OpenVG enumeration values.

        Excepting the printable ASCII character command tokens, absolute
        command token values should always be even, while relative
        command token values should always be odd.

    11. Why are the glyph metric bits in the order they are specified?

        RESOLVED:  The glyph metric order matches the FreeType 2 library's
        FT_Glyph_Metrics structure for the per-glyph metrics. The
        per-font metric order matches the FreeType 2 library's FT_FaceRec
        structure.

        Kerning information for a font face can be queried with the
        separate query glGetPathSpacingNV because the kerning displacement
        is not per-glyph, but rather dependent on a sequence of two
        glyphs.

    12. What glyph metric information is beyond the scope of this extension?

        RESOLVED:  Metrics for vertical kerning, bi-directional layout,
        ligatures, etc.  are beyond the scope of this extension.

        Kerning information for horizontal layout is available.

        The scope of the metrics provided by this extension are sufficient
        for basic kerned and non-kerned horizontal and non-kerned vertical
        text layout.

        Applications that want more sophisticated metric information
        should either query the metrics from the corresponding system
        font directly or load the glyph outline data entirely from the
        application.

    13. What glyph outline information is beyond the scope of this
        extension?

        RESOLVED:  For now, normal (indicated by GL_NONE), italic,
        bold, and bold/italic font faces are supported.  Other styles
        (small caps, etc.) may be added with future extensions to this
        extension, but the four supported font styles are sufficient.

        This is consistent with FreeType 2's support for  the
        FT_STYLE_FLAG_ITALIC and FT_STYLE_FLAG_BOLD flags.

    14. Should horizontal kerning information always be available?

        RESOLVED:  Yes, if the font provides this kerning information.

    15. Why is the horizontal kerning information for a pair of path
        objects returned as a 2D (x,y) displacement?

        RESOLVED:  TrueType fonts always return kerning information
        as a sequence of horizontal displacements in x, but not y (the
        displacement is assumed to be zero in y).  However PostScript
        fonts can support a 2D displacement.

        This matches the behavior of FreeType 2's FT_Get_Kerning function.

        Note that the returned (x,y) float pairs are NOT immediately
        suitable to be used as values for the /transformValues/
        array parameter to StencilFillPathInstancedNV,
        StencilStrokePathInstancedNV, CoverFillPathInstancedNV, or
        CoverStrokePathInstancedNV with a /transformType/ parameter
        of TRANSLATE_2D_NV.  The application would be responsible for
        accumulating the various translates to provide proper horizontal
        layout.  When all the y values are zero (as will often be the
        case), GL_TRANSLATE_1D_NV could be used instead.

    16. Should the path name zero be treated specially?

        RESOLVED:  No.  There's no need for specially handling the zero
        name for a path object.

    17. What tokens for color should glPathColorGenNV accept?

        RESOLVED:  GL_PRIMARY_COLOR (from OpenGL 1.3), GL_PRIMARY_COLOR_NV
        (from NV_register_combiners), and GL_SECONDARY_COLOR_NV (from
        NV_register_combiners).

        GL_PRIMARY_COLOR and GL_PRIMARY_COLOR_NV have different token
        values; to avoid an API pitfall, both are accepted.

        (There is no core GL_SECONDARY_COLOR token.)

    18. Should two-sided color be supported for path rendering?

        RESOLVED:  No.  No path rendering standards support this concept.

        Two-sided lighting could be simulated with two passes and face
        culling.

    19. How do PostScript's user path operators correspond to
        NV_path_rendering's path command tokens?

        RESOLVED:

            PostScript path
            operator         Path command token
            ---------------  -----------------------------
            arc              GL_CIRCULAR_CCW_ARC_TO_NV
            arcn             GL_CIRCULAR_CW_ARC_TO_NV
            arcto            GL_CIRCULAR_TANGENT_ARC_TO_NV
            closepath        GL_CLOSE_PATH_NV
            curveto          GL_CUBIC_CURVE_TO_NV
            lineto           GL_LINE_TO_NV
            moveto           GL_MOVE_TO_NV
            rcurveto         GL_RELATIVE_CUBIC_CURVE_TO_NV
            rlineto          GL_RELATIVE_LINE_TO_NV
            rmoveto          GL_RELATIVE_MOVE_TO_NV
            setbbox          /ignored/
            ucache           /ignored/

        The setbbox (set bounding box) operator "establishes a bounding
        box for the current path, within which the coordinates of all
        subsequent path construction operators must fall."  There is
        no such requirement in this extension so this bounding box
        information is parsed but ignored.

        The ucache (user cache) operator "notifies the PostScript
        interpreter that the enclosing user path is to be retained in
        the cache if the path is not already there."  This notion that
        paths are expensive and so must be cached is not particularly
        applicable to this extension because all path object are in
        some sense cached.  Therefore the ucache operator is parsed
        but ignored.

    20. How do OpenVG 1.1's commands (as enumerated by the VGPathCommand
        and VGPathCommand enumerations) correspond to NV_path_rendering's
        path command tokens?

        RESOLVED:

            OpenVG path
            segment command    Path command token
            -----------------  ----------------------------------------
            VG_CLOSE_PATH      GL_CLOSE_PATH_NV
            VG_CUBIC_TO        GL_CUBIC_CURVE_TO_NV
            VG_CUBIC_TO_ABS    "
            VG_CUBIC_TO_REL    GL_RELATIVE_CUBIC_CURVE_TO_NV
            VG_HLINE_TO        GL_HORIZONTAL_LINE_TO_NV
            VG_HLINE_TO_ABS    "
            VG_HLINE_TO_REL    GL_RELATIVE_HORIZONTAL_LINE_TO_NV
            VG_LCCWARC_TO      GL_LARGE_CCW_ARC_TO_NV
            VG_LCCWARC_TO_ABS  "
            VG_LCCWARC_TO_REL  GL_RELATIVE_LARGE_CCW_ARC_TO_NV
            VG_LCWARC_TO       GL_LARGE_CW_ARC_TO_NV
            VG_LCWARC_TO_ABS   "
            VG_LCWARC_TO_REL   GL_RELATIVE_LARGE_CW_ARC_TO_NV
            VG_LINE_TO         GL_LINE_TO_NV
            VG_LINE_TO_ABS     "
            VG_LINE_TO_REL     GL_RELATIVE_LINE_TO_NV
            VG_MOVE_TO         GL_MOVE_TO_NV
            VG_MOVE_TO_ABS     "
            VG_MOVE_TO_REL     GL_RELATIVE_MOVE_TO_NV
            VG_QUAD_TO         GL_QUADRATIC_CURVE_TO_NV
            VG_QUAD_TO_ABS     "
            VG_QUAD_TO_REL     GL_RELATIVE_QUADRATIC_CURVE_TO_NV
            VG_SCCWARC_TO      GL_SMALL_CCW_ARC_TO_NV
            VG_SCCWARC_TO_ABS  "
            VG_SCCWARC_TO_REL  GL_RELATIVE_SMALL_CCW_ARC_TO_NV
            VG_SCUBIC_TO       GL_SMOOTH_CUBIC_TO_NV
            VG_SCUBIC_TO_ABS   "
            VG_SCUBIC_TO_REL   GL_RELATIVE_SMOOTH_CUBIC_TO_NV
            VG_SCWARC_TO       GL_SMALL_CW_ARC_TO_NV
            VG_SCWARC_TO_ABS   "
            VG_SCWARC_TO_REL   GL_RELATIVE_SMALL_CW_ARC_TO_NV
            VG_SQUAD_TO        GL_SMOOTH_QUADRATIC_CURVE_TO_NV
            VG_SQUAD_TO_ABS    "
            VG_SQUAD_TO_REL    GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV
            VG_VLINE_TO        GL_VERTICAL_LINE_TO_NV
            VG_VLINE_TO_ABS    "
            VG_VLINE_TO_REL    GL_RELATIVE_VERTICAL_LINE_TO_NV

    21. What should the initial GL_PATH_FILL_MODE_NV state be?

        RESOLVED:  GL_PATH_FILL_MODE_NV should initially be
        GL_COUNT_UP_NV.

        This is consistent with SVG default non-zero fill rule and the
        typical usage of PostScript.

        However this is the opposite of Silverlight's default fill rule
        which is even-odd.

    22. Should we support a GL_PATH_FORMAT_SL3_NV for Silverlight 3.0 be
        added?

        UNRESOLVED:  Silverlight 3.0's path markup syntax includes
        support for two extensions of the SVG 1.1 path grammar:  1)
        specification of a fill rule ("F0" is even-odd, "F1" is non-zero)
        at the beginning of the string; and 2) allowing "Infinity",
        "-Infinity" and "NaN" (all case-sensitive) as special values
        allowed instead of standard numerical values.

        Seems like a reasonable thing to support.

        The fill rule specification is straightforward.  This would
        simply allow the path object's GL_PATH_FILL_MODE_NV parameter to
        be specified as part of the path string specification.  The "F0"
        or "F1" would not be treated as an actual path command however.

        Note that Silverlight's default fill rule if none is specified is
        EvenOdd whereas NV_path_rendering's default GL_PATH_FILL_MODE_NV
        is GL_COUNT_UP_NV (essentially a non-zero rule).  So specifying a
        path with the Silverlight format would have a different initial
        value for GL_PATH_FILL_MODE_NV if "F0" or no initial F
        command is specified.

        What exactly would it mean to allow infinite and not-a-number
        values for the coordinate values of a path object?  Infinite is
        probably representable today by simply writing a number with a
        sufficiently large enough magnitude.  Allowing not-a-number is
        probably more

    23. Should there be some maximum specified limit for the number of
        command (and hence coordinates) in a path object?

        RESOLVED:  No.  The standards for path rendering do no generally
        have limits on path command lengths.

        For extreme cases, the OUT_OF_MEMORY error would be generated but
        that is considered an exceptional case due to memory exhaustion,
        not simply the specification of a huge path.

    24. Should there be some maximum specified limit for the dash array?

        RESOLVED:  No.  The standards for path rendering do not generally
        have a limit on the dash array length.

    25. How do the client-defined clip planes and the clip volume interact
        with path rendering?

        RESOLVED:  Stenciled and covered paths are affected by both the
        clip volume and client-defined clip planes.

        Clip planes affect the set of accessible pixels for stenciling
        and covering operations (see the "ACCESSIBLE SAMPLES WITH RESPECT
        TO A TRANSFORMED PATH" subsection of section 5.X.2.1).

    26. What should the end cap style be called that adds no additional
        cap region to a stroked path?

        RESOLSVED:  FLAT.

        FLAT is already an existing OpenGL token name.  Silverlight and
        the OpenXML Paper Specification (XPS) calls this end cap style
        "flat".  However PostScript, Flash, OpenVG, SVG, Quartz 2D,
        and Cairo Graphics all call this end cap style "butt".

        Using FLAT also avoids verbalizing the awkward phrase "butt
        stroking" (not that there's anything wrong with that).

    27. Should the PostScript grammar for user-defined paths be supported?

        RESOLVED:  Yes.  PostScript has commands (arc, arcn, arct) that
        do not correspond to precisely to SVG command.  This is
        particularly true of arct.

        Applications have been generating paths according to the syntax
        of Level 2 PostScript for a long time.

        Level 2 PostScript also has support for binary encoding that
        makes it significantly more compact and less expensive to parse
        than the SVG grammar.

        The binary encoding allows precise floating-point (and compact
        fixed-point) values to be specified.

    28. Should the PostScript grammar support big-endian, little-endian,
        and native numeric encodings?

        RESOLVED:  Yes, yes, yes.

    29. Should the PostScript grammar support encoded user paths?

        RESOLVED:  Yes.

    30. How should the PostScript grammar support strings?

        UNRESOLVED:  Hexadecimal encoded data, that is strings enclosed
        in < and >, are supported.

        Strings for ASCII base-85 encoded data, that is strings enclosed
        in <~ and ~>, are supported for the data-array and operator-string
        production

        Also the short-binary-string, be-long-binary-string, and
        le-long-binary-string productions allow very compact and precise
        encoding of operator strings through binary encoding.

        Strings for literal text, that is strings enclosed in ( and ),
        are NOT supported.

        The rationale for not supporting literal text is this format
        is awkward for encoding the operator-string production (though
        PostScript does technically allow it) and is not compact.

    31. Should the PostScript grammar support Binary Object Sequences?

        RESOLVED:  No.

        Binary Object Sequences are intended to support complex
        (potentially nested) data structures and are over-kill for
        user paths.

    32. Why are the binary tokens in the PS grammar assigned the values
        they are assigned?

        RESOLVED:  These values are from the "Binary Tokens" section of
        the PostScript Language Reference Manual.

    33. Why are the binary encodings for the path commands in the PS
        grammar assigned the specified values?

        RESOLVED:  These values match PostScript's system name table
        values.  These are documented in the "System Name Encodings"
        appendix of the PostScript Language Reference Manual.
        Specifically (in decimal):

            Index  Name
            -----  ---------
            22     closepath
            99     lineto
            107    moveto
            133    rlineto
            134    rmoveto
            143    setbbox
            43     curveto
            122    rcurveto
            5      arc
            6      arcn
            7      arct
            177    ucache

    34. Why do glGetPathCommandsNV, glGetPathCoordsNV, and
        glGetPathDashArrayNV have their own queries?  Could there not
        simply be a token for glGetPathParameteriv/glGetPathParameterfvNV
        to return this state?

        RESOLVED:  These queries for path commands, coordinates, and
        the path's dash array return a variable payload of data so are
        more like glGetTexImage than glGetIntegerv/glGetFloatv which
        return a static amount of data.

        APIs that return variable amounts of data are prone to buffer
        overflows.  It is somewhat more obvious these commands return
        a variable amount of data if they have their own API calls, than
        simply having certain token values to a multi-purpose glGet* call
        that mysteriously returns varying amounts of data for these token
        values while all the other tokens return static amounts of data.

        This resolution follows the existing precedent from
        core OpenGL where glGetColorTable is distinct from
        glGetColorTableParameter{fv,iv}.  Same with glGetConvolutionFilter
        and glGetHistogram relative to glGetConvolutionParameter{fv,iv}
        and glGetHistogramParameter{fv,iv}.

        (There is a poor precedent for having an OpenGL query return both
        static and varying amounts of data based on a pname parameter.
        glGetMap{dv,fv,iv} returns varying data when GL_COEFF is queried
        while GL_ORDER and GL_DOMAIN return n and 2*n values respectively
        where n is the dimensionality of the map target.  This isn't a
        good precedent and is obscure.)

    35. How should the GL_PATH_*_BOUNDING_BOX_NV path parameters be
        returned?

        RESOLVED:  In (x1,y1,x2,y2) order where (x1,y1) is the minimum
        bounds of the bounding box and (x2,y2) is the maximum bounds.

        This is contrary to the precedent of GL_SCISSOR_BOX query
        which returns the scissor as an (x,y,width,height) 4-tuple.
        While that makes sense for a scissor box, particularly given how
        the scissor is specified with glScissor, it is not a convenient
        way to specify a bounding box.

        The (x1,y1,x2,y2) format also makes the
        glCover{Fill|Stroke}PathInstancedNV pseudo-code work nicely
        with glRectf.  See the renderBoundingBox pseudo-code.

        The (x1,y1,x2,y2) format is also consistent with the way
        FreeType 2 provides per-font face bounds information through
        the GL_FONT_X_MIN_BOUNDS_BIT_NV, GL_FONT_Y_MIN_BOUNDS_BIT_NV,
        GL_FONT_X_MAX_BOUNDS_BIT_NV, and GL_FONT_Y_MAX_BOUNDS_BIT_NV
        metric queries.

    36. Why is font loading part of this extension?  Shouldn't OpenGL
        stick with just rendering and not involved itself with fonts?

        RESOLVED:  An explicit goal of this extension is to provide
        GPU-accelerated path rendering that INCLUDES excellent support
        for glyphs and their associated metrics.

        The fact is all the major existing standards for path rendering
        (PostScript, SVG, OpenVG, Java 2D, Quartz 2D, Flash) include
        first-class font and glyph support.

        Not including font and glyph support would be a glaring omission
        that would make this extension much less useful to simple OpenGL
        applications that don't want to incorporate large font libraries.

        Additionally font loading is notoriously platform dependent.
        This extension provides a simple platform-independent mechanism to
        rendezvous with standard font names.  However an implementation of
        this extension can make use of whatever platform-specific font
        services the platform provides (such as through DirectWrite,
        etc.).

        Fonts, particularly for Asian languages or designed to support a
        large portion of Unicode, are large.  Populating their complete
        outlines can consume substantial amounts of system and video
        memory.  Many applications on a system are likely to access
        the same collections of fonts.  Having fonts loaded by name
        allows GL implementations to coordinate the efficient sharing
        of font outline data among multiple GL application instances.
        This font sharing can have a substantial reduction in the total
        system resources devoted to font data which is not possible if
        the GL is unable to be aware of duplicated font outline data
        within the system.

        Font formats change and evolve over time.  Building font format
        knowledge into applications will ultimately be limiting long-term.

        Fonts are really properly thought of as system resources.
        They represent intellectual property that is typically licensed
        on a per-system basis.  Building font access into the GL promotes
        use of the system's properly licensed fonts.  Most applications
        do not want to be encumbered by licensing issues associated with
        fonts so to the extent that the API makes access to system fonts
        easier, that promotes properly licensed use of fonts.

    37. What is the typographical philosophy for this extension?

        RESOLVED:  This extension relies on other standards to provide
        its typographic backbone and philosophy.

        The character set supported depends on the Unicode standard.

        Specific font formats supported depend on the system but the
        expectation is that standard TrueType, PostScript, and OpenType
        fonts can be used through this extension.  The metrics from such
        fonts will generally be "passed through" the glGetPathMetricsNV
        query.

        The naming of fonts is consistent with the underlying system
        with the expectation that the system's naming is consistent with
        modern web standards for identifying fonts in web content.

        While the specific set of supported fonts may vary from system to
        system based on the available installed fonts, the expectation is
        that standard TrueType fonts such as Arial, New Courier, Georgia,
        etc. will be available on systems that support this extension.

        For applications that demand a set of glyphs that are guaranteed
        to be available, the GL_STANDARD_FONT_NAME font target is
        available for the names "Sans", "Serif", and "Mono" and these
        fonts are understood to match a set of glyphs consistent with the
        DejaVu font set populated with at least the Latin-1 character set.

        The underlying font engine is likely to be FreeType 2 or the
        system's native font engine (such as DirectWrite for newer
        Windows versions).

    38. What is the path rendering philosophy for this extension?

        RESOLVED:  Two-step stencil-based GPU-acceleration + broad-tent
        support for the accepted functionality of path rendering.

        This extension assumes that the two-step "stencil, then cover"
        stencil-based approach to GPU-accelerating path rendering.

        Both stenciling and stroking are supported.  Strokes are
        first-class representations and not treated as fills that
        approximate the stroked region.  For pragmatic reasons, cubic
        Bezier segments, conic segments, and partial elliptical
        (non-circular) arcs path segments are assumed to be approximated
        by a sequence of quadratic Bezier path segments that guarantee
        G1 continuity.

        The contrapositive of this approach is an avoidance of schemes
        based on tessellation of path outlines.

        Paths are defined using both cubic and quadratic Bezier curves.
        This broadly allows path content from TrueType (based on quadratic
        Bezier curves) and PostScript and its font families (based on
        cubic Bezier curves) to be supported.

        Arcs are drawn consistent with both SVG (partial elliptical arcs)
        and PostScript (circular arcs and circular tangent arcs).

        The set of stroking options is a union of the stroking features
        of OpenVG, SVG, XML Paper Specification (XPS), PostScript, and
        other standards.  For example, XPS supports dash caps that other
        standards lack.

        The path queries support the key path queries supported by OpenVG.

    39. Should there be an API for assigning path metric information to
        a path object?

        RESOLVED:  No.

        Path metrics are available when a path object is created with
        glPathGlyphsNV or glPathGlyphRangeNV.  In these cases, the font
        supplies the metric data for these path objects.

        It might be useful to allow these metrics to be specified for an
        arbitrary path object.  This way user-defined path objects could
        appear to have metrics available as if they had been specified
        by glPathGlyphsNV or glPathGlyphRangeNV.

        Supporting the specification of path metrics would require new
        API.  Something like glPathMetricsNV perhaps?  Or having parameter
        names for the font metrics supported by glPathParameter{f,i}v?
        The later approach would probably require new tokens and would
        mean glGetPathParameter{f,i}v should support these tokens too.

        Since the metrics are for information purposes only, meaning
        the rendering functionality for paths never involves the metrics
        (unlike other path parameters), it seems odd to allow information
        to be specified just so it can be queried by the application.
        This doesn't feel like essential functionality though its
        absence may be missed by library developers that want to "fake"
        font loaders.

    40. What happens when an input path object to glWeightPathsNV,
        glInterpolatePathsNV contains an arc command when there are two
        or more path objects involved?

        RESOLVED:  An INVALID_OPERATION error is generated.

        In general, arc commands are not "closed" under linear
        combination.  Said another way, the linear combination of two
        or more arcs is not, in general, itself an arc of the same form.

        glCopyPathNV copies outlines for path objects containing any
        valid commands including arc commands.

    41. When a path object is created from other existing path objects
        through the glWeightPathsNV, glInterpolatePathsNV, or glCopyPathNV
        commands, where does the new path's parameters come from?

        RESOLVED:  While the path commands are interpolated on a
        command-by-command basis with these commands, the path parameters
        should be copied from the first path object specified.

        So for glWeightPathsNV, glInterpolatePathsNV, and glCopyPathNV,
        the path parameters from the path[0], pathA, and srcPath
        parameters respectively.

    42. How is the glyph metric and kerning information specified for
        a path object created from other existing path objects through the
        glWeightPathsNV, glInterpolatePathsNV, or glCopyPathNV commands,
        where does the new path's parameters come from?

        RESOLVED:  The path metric information is set to negative one
        for glWeightPathsNV and glInterpolatePathsNV.

        There's no reasonable way to weight the metric information.
        Metric information is tuned to a particular glyph.

        More explicitly, the path metric information from the first path
        object to be combined is NOT copied (as the parameters are).

        However glCopyPathNV does copy the glyph metric and kerning
        information (since only one path object is involved so there's
        no combination of outlines).

    43. Should there be a way to specify different stroking parameters
        (stroke width, end caps, etc.) within the command sequence of
        a path?

        RESOLVED:  No.

        Existing path rendering standards keep the stroking parameters
        constant for a given path's outline.  For example, there's not
        support for a dashed stroked segment of width 5.0 as well as a
        non-dashed stroked segment with width 9.4 in the same path.

        This wouldn't be impossible to support; commands that changed
        stroking parameters could be supported within the command
        sequence.  However it would complicate the meaning of the path
        parameters for stroking; these parameters could be considered
        defaults for stroking parameters if stroking parameters are not
        otherwise specified.  There's also the complication of when
        new stroking parameters would latch into place.  Would it be
        immediately (mid path?) or not latch until the next "moveto"
        command?  And how would such commands be weighted/interpolated?

        Attempting to support changing stroking parameters within a path
        appears to open up a complicated can of worms.

        The same rendering effect can be achieved with the
        gl{Stencil,Cover}StrokePathInstancedNV commands using multiple
        path object, each with the appropriate stroking parameters for
        the appropriate path segments.

    44. What should the query token for the path color and texture
        coordinate generation coefficients be named?

        RESOLVED:  GL_PATH_GEN_COEFF_NV.

        Alternatively this could be GL_PATH_GEN_COEFF_NV (plural),
        but that doesn't match the precedent set by GL_COEFF used by
        glGetMap{f,d}v.  These existing queries return a plurality of
        coefficients too.

    45. What should the number of coefficients returned when querying the
        path color and texture coordinate generation coefficients depend
        on the current path color or texture coordinate generation mode or
        should a fixed maximum number of coefficients always be returned?

        RESOLVED:  A fixed maximum of 16 coefficients should always
        be returned.

        It is error-prone and likely to result in obscure buffer
        overflow cases if the number of coefficients returned depends
        on the respective current path generation mode.  It is better
        to simply always return 16 values.  Unused coefficients by the
        current generation mode should always be returned as zero.

    46. How does glGetPathLengthNV compare to OpenVG's vgPathLength?

        RESOLVED:  glGetPathLengthNV and vgPathLength compute
        essentially the same result except glGetPathLengthNV returns
        0 when /numSegments/ is 0 whereas vgPathLength considers this
        case an error.

    47. Where does all the discussion of partial elliptical arc
        parameterization come from?

        RESOLVED:  This discussion is based on and fully consistent with:

            http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes

    48. Where does the parameterization of the
        GL_CIRCULAR_TANGENT_ARC_TO_NV come from?

        RESOLVED:  The GL_CIRCULAR_TANGENT_ARC_TO_NV is based on the
        PostScript arct command (which is based on arcto) for user paths.

        See the gs_arcto routine in:

            http://svn.ghostscript.com/ghostscript/trunk/gs/base/gspath1.c

    49. How should fog coordinate generation work for path rendering?

        RESOLVED:  The glPathFogGenNV command controls how generation
        of the fog coordinate operates for path rendering commands.

        The GL_FOG enable is tricky because it controls both per-vertex and
        per-fragment processing state (unlike per-vertex lighting and texture
        coordinate generation).

        Simply using the existing fixed-function fog coordinate state is
        undesirable because that 1) entangles fog coordinate generation
        with conventional vertex processing and path vertex processing,
        and 2) the NV_fog_distance extension allows a non-linear fog
        coordinate to be generated through the GL_EYE_RADIAL_NV mode.

        The fog coordinate generation for path rendering can either
        use the fog coordinate "as is" for the entire covered path or
        have the fog coordinate be the negated perspective-divided
        eye-space Z component (which can vary, but only linearly).

    50. What should glyph metrics return for path objects not specified
        by glPathGlyphsNV or glPathGlyphRangeNV?

        RESOLVED:  All queried metrics should return the value -1.

        Negative values are out-of-range for many of the metric values so
        negative values provide a reliable indicator that a path object
        was not specified from a glyph.

    51. How should the fill mode state of path objects created from
        glyphs be initialized?

        RESOLVED:  The initial GL_PATH_FILL_MODE_NV for path objects
        created from glyphs depends on the source font's convention.

        Typically TrueType and newer (all?) PostScript fonts depend on the
        non-zero fill rule.  TrueType fonts assume a clockwise outline
        winding (hence will use GL_COUNT_DOWN_NV) while PostScript
        fonts assume a counterclockwise outline winding (hence will
        use GL_COUNT_UP_NV).

        It's unlikely an actual font will use GL_INVERT as its
        GL_PATH_FILL_MODE_NV but the possibility is allowed.

    52. Should other path object parameters other than the fill mode be
        initialized specially when path objects are specified from glyphs?

        RESOLVED:  No.

        In theory, other path parameters such as stroke width, join style,
        etc. could all be specified from the font.  In practice, most
        font forms don't provide such parameters.

        At least one font format, Bitstream's PFA format, does provide
        such information though how applicable these parameters are to
        a path object is unclear.  The availability of these parameters
        appears to be intended as a way to bold or otherwise dilate the
        glyph's outline rather than being intended for stroking.

        SVG supports stroking of fonts but the stroke-width tag is
        specified in the current user coordinate system rather than
        depending on the particular font or its glyphs.

    53. How should the integers passed to glPathGlyphsNV and
        glPathGlyphRangeNV be mapped to actual glyph outlines for a font?

        RESOLVED:  The integers that come from the charcode array or
        the firstGlyph to firstGlyph+numGlyphs-1 range are treated as
        Unicode character codes if the font has a meaningful mapping of
        Unicode to its glyphs.

        The existence of a meaningful mapping from Unicode to glyph
        outlines is the expected situation.  For fonts without a
        meaningful mapping to Unicode character codes (such as custom
        symbol fonts), the font's standard mapping of character codes to
        glyphs should be used.  This situation should be rare, probably
        due to a font that is poorly authored, very old, or custom built.

    54. How are typographical situations such as ligatures, composite
        characters, glyph substitution, and language-dependent character
        sequence conversion handled?

        RESOLVED:  If a particular behavior is desired for how such
        situations are handled, that is up to the application software
        using this extension.

        For example, in the case of ligatures, multiple Unicode characters
        may map to a single ligature glyph.  Support for ligatures is
        a stylistic typographic decision and the application is free to
        handle this in any of a number of ways; this extension neither
        forces nor precludes specific approaches to handle ligatures.
        The application can overlap existing glyphs to create the
        appearance of a path object by rendering the individual multiple
        Unicode characters overlapped; a ligature character that is
        part of the Unicode character set could be selected; or the
        application could create its own custom path object in this
        situation and render it.

        For composite characters, the underlying font engine used to
        implement this extension may construct composite characters.
        Or this may be a situation where, due to limitations of the
        font or font engine, possibly in combination, this is treated as
        an unknown or missing character where implementation-dependent
        handling is possible.  Such a situation could also exist for a
        ligature character specified by Unicode.

        In general, higher level details of text presentation such
        as ligatures, composite characters, glyph substitution, and
        language-dependent character sequence conversion are beyond the
        scope of this extension.

        See the Unicode FAQ on "Ligatures, Digraphs and Presentation
        Forms":

            http://www.unicode.org/faq/ligature_digraph.html

        In complicated typographical situations, the assumption is that
        the application will construct the appropriate inter-glyph
        transformation values (the transformValues and transformType
        for glStencilFillPathInstancedNV and glCoverFillPathInstancedNV)
        and build digraphs or other presentation forms.

    55. Are relative path commands converted to absolute commands upon
        path specification?

        RESOLVED:  No, relative commands are first-class and are
        maintained as relative commands.

        This includes when relative commands are created by copying,
        interpolating, or weighting existing path objects.  Relative path
        commands must match identical relative path commands and their
        relatively control points are weighted as relative position
        offsets.

        Another implication if this is that if an application modifying
        the control points with glPathSubCoordsNV, those edits can effect
        the outline of subsequent relative commands that depend on the
        modified coordinates.

        The same applies to changing commands.  Editing commands with
        glPathSubCommandsNV can change how coordinates are interpreted
        for the edited commands and subsequent relative commands.

        In other words, if a path object is modified or edited, the
        outline of the path is the same as if the path object had been
        specified from scratch with the same command and coordinate
        sequences.

    56. What does this extension do with so-called "hinting" in outline
        font glyphs?

        RESOLVED:  When a path object is specified from the glyph of a
        font, the path object's outline is specified from the "ideal"
        resolution-independent form of the glyph.

        This is because a path object is rendered (stenciled or covered)
        from a resolution-independent form.  There is an implicit
        assumption in the specified transformation and rendering process
        that the process is unaware of the device coordinate grid.

        This means there's not the knowledge of device coordinate space
        necessary to apply hinting information.

        In TrueType terms, this amounts to the path object's outline for
        a TrueType glyph being the glyph's "master outline".  This means
        the TrueType instructions associated with the glyph are ignored
        and not executed.

        While it is beyond the scope of this extension, there's nothing
        in this extension that keeps an application in decoding itself the
        TrueType master outline of a glyph and performing the grid-fitted
        outline generation at a given arbitrary device resolution.
        Then this fitted outline could be specified for a path object.
        The key observation is that doing so makes the resulting outline
        resolution-dependent which obviates much of the advantage of
        this extension's ability to render from a resolution-independent
        outline.

        Rather than relying on hinting for legibility, applications using
        this extension are likely to rely on multisampling or multiple
        jittered rendering passes for antialiasing and assume a certain
        amount of grayscale appearance as a consequence.

    57. If a font format has bitmap font data, is that used?

        RESOLVED:  No, only resolution-independent outline data is used;
        bitmap data is ignored.  Bitmap-only font formats won't be loaded.

        In the FreeType 2 API, the information available is comparable
        to calling FT_Load_Glyph with the FT_LOAD_NO_SCALE and
        FT_LOAD_NO_BITMAP flags specified.

    58. How is antialiasing of path object rendering accomplished?

        RESOLVED:  Multisampling is the expected way that antialiasing
        will be accomplished when rendering path objects.

        Recall in multisampling that the stencil buffer is maintained
        at per-sample resolution.  This means the coverage determined
        by stenciling path objects should be accurate to the sample
        resolution.

        If a multisampled framebuffer provides N samples per pixel, that
        means that there are N+1 possible coverage weightings of a given
        path with respect to that pixel, assuming a single "stencil, then
        cover step", equal weighting of samples in the final pixel color,
        and the samples for a given pixel belonging to a single pixel.

        One explicit goal of this extension is to maintain a separation
        between coverage and opacity.  The two concepts are often
        conflated treating both as percentages and then modulating
        opacity with coverage.  Conflating the two leads to coverage
        bleeding at what should be sharp, though transparent, edges and
        corners.

        In this extension, the stencil buffer maintains coverage and
        the alpha channel for RGBA colors, which is per-sample when the
        framebuffer format supports multisampling, maintains opacity.

        Philosophically this extension provides a robust and accurate
        mechanism for determining point-sampled coverage for arbitrary
        filled and stroked paths.  The extension does not rely on, nor
        does it even attempt, to compute or approximate a path's area
        coverage with respect to a pixel.  For practical reasons, such
        analytical computations are inevitably approximations for
        arbitrary paths and are difficult to make robust.

        Point sampling of path object rasterization can offer more
        robustness and precision.  Point sampling also allows this
        extension's rendering results to seamlessly co-exist with OpenGL's
        conventional point, line, and polygon rasterization approaches
        which are point-sampled.

        The implication of this observation is path rendered content can
        be mixed with arbitrary OpenGL 3D content, whether rendered with
        depth testing or not.  This provides the very powerful ability to
        mix path rendered and 3D rendered content in the same framebuffer
        in predictable ways with negligible overhead for doing so.

        Keep in mind that 2D path rendered content is transformed by the
        projective modelview-projection transform, just like other OpenGL
        rendering primitives, so fragments generated with path rendering
        have varying depth values that can be depth tested, fogged, etc.

        Point sampling is prone to missing coverage but avoids indicating
        coverage where no actual coverage exists.

        This extension implicitly assumes that GPUs have some maximum
        sample location precision while rasterizing.  This is an artifact
        of subpixel precision.  This concept is built into OpenGL; see
        the GL_SUBPIXEL_BITS implementation-dependent limit.  Developers
        should not expect any additional sampling precision beyond this
        limit.  To get beyond this limit, applications would be expected
        to render at a larger framebuffer resolution and downsample to
        the appropriate resolution or render in some tiled fashion.

        If multisampling provides insufficient antialiasing, further
        antialiasing is possible by rendering with multiple passes.

        For example, applications can use accumulation buffer techniques
        with sub-pixel jittered re-rendering of the entire scene
        to improve the overall quality.  This provides full-scene
        antialiasing.

        Alternatively, a path object itself needing extra antialiasing,
        perhaps because the application has determined the path object
        maps to a small region of the framebuffer in window space, can
        be rendered multiple times, each time with subpixel jittering.
        By writing just into the non-visible alpha component of the
        framebuffer, a coverage percentage at each color sample can
        be accumulated.  Then a final cover operation can blend this
        coverage information into the visible RGB color channels.

        Despite the multiple passes involved, this approach can still
        be several times faster than CPU path rendering methods because
        of the rendering rate possible through GPU acceleration.

    59. How do the multisample fragment operations interact with path
        rendering?

        RESOLVED:  They are ignored for the "stencil" path rendering
        operations (since only the stencil buffer is updated), and they
        work as specified for the "cover" path rendering operation.

        The coverage determination made during the "cover" path
        rendering operation doesn't reflect the path itself but rather
        the conservative coverage provide by the covering operation.
        For this reason, the coverage mask is conservative, meaning
        samples may be covered that don't actually belong to the filled
        or stenciled region of the path being covered.  And exactly how
        conservative this coverage is depends on the implementation.

        Still the coverage is available and can be used as specified in
        section 4.1.3 ("Multisample Fragment Operations").

        The GL_SAMPLE_COVERAGE mode would be more useful if the stencil
        testing was performed prior to the shading of the covered geometry
        and the covered sample mask reflected any discards performed by
        the stencil (or depth) tests.

        The NV_explicit_multisample extension and its
        ARB_texture_multisample functionality (standard with OpenGL 3.2)
        provide explicit control of the multisample mask.  This mask is
        respected for path rendering.

    60. Does creating multiple instances of path objects from the same
        glyph in the same font face "waste memory"?  What about copies
        of objects created with glCopyPathNV?

        RESOLVED:  This is an implementation issue, but it is reasonable
        to expect that copies of path objects created with glCopyPathNV
        will share their outline data on a copy-on-write basis.  This is
        true even if a path object is copied and its path parameters
        are modified (but not the path commands and coordinates).

        It is also reasonable to expect that path objects created with
        glPathGlyphsNV may use copies if there are replicated character
        codes.  While glPathGlyphRangeNV isn't subject to replicated
        character codes, if two or more character codes share the same
        glyph, it would be reasonable to expect the implementation might
        share the outline data.

        It's always possible to use glPathSubCommandsNV or
        glPathSubCoordsNV to modify the path commands and/or coordinate
        data so then sharing will have to be broken.

    61. Why does glPathGlyphsNV (and hence glPathGlyphRangeNV as well)
        not disturb path objects that already exist in the range of path
        objects to be created?

        RESOLVED:  This facilitates a strategy for supporting multiple
        font names specified in preferential order.

        An application can do something like:

          GLint firstPathName = glGenPathsNV(256);
          const GLfloat emScale = 2048;
          glPathGlyphRangeNV(firstPathName, GL_SYSTEM_FONT_NAME_NV,
                             "Helvetica", GL_NONE, 0, 256, emScale);
          glPathGlyphRangeNV(firstPathName, GL_SYSTEM_FONT_NAME_NV,
                             "Arial", GL_NONE, 0, 256, emScale);
          glPathGlyphRangeNV(firstPathName, GL_STANDARD_FONT_NAME_NV,
                             "Sans", GL_NONE, 0, 256, emScale);

        This ensures that path object names /firstPathName/ through
        /firstPathName/+255 will be loaded with the glyphs from Helvetica,
        Arial, or the guaranteed-present Sans font face, in that order
        of preference.

        This is consistent with the CSS font-family property used in
        web standards, including SVG.

    62. Why are the angles for the arc path commands specified with
        degrees (instead of radians)?

        RESOLVED:  Using degrees is consistent with OpenGL's existing
        glRotatef, glRotated, and gluPerspective commands.

        Using degrees for angles is also consistent with the conventions
        of the PostScript, SVG, and OpenVG commands upon which the arc
        path commands are based.

        Using degrees (90 degrees, 30 degrees, 45 degrees) also allows
        important angles be represented exactly with integer values.
        This is relevant for compact coordinate formats and paths defined
        by strings.

    63. Should UTF-8 and UTF-16 be supported for arrays of path names?

        RESOLVED:  Yes.

    64. What order should the arguments be listed when a array of
        path objects with typed elements and a base are specified?

        RESOLVED:

        1) sizei count,
        2) enum pathNameType,
        3) const void *paths,
        4) uint pathBase

        The standard OpenGL parameter pattern is count/type/array.
        Examples of this are glDrawElements and glCallLists.
        (More generally the pattern is count/format/type/array.)

        Having the pathBase parameter last matches the precedent set by.
        glDrawElementsBaseVertex where the base vertex value follows
        the list of element indices.  Hence the pattern
        count/type/array/base.

        The basevertex parameter to glDrawElementsBaseVertex is typed
        GLint; the pathBase parameter is typed GLuint.  GLuint makes
        sense to avoid useless signed/unsigned mismatch warnings from
        C compilers when most values passed to pathBase parameters are
        likely to be from GLuint variables.  When GLuint and GLint are
        both 32-bit data types, the choice is not consequential.

        Commands that use this order are glStencilFillPathInstancedNV,
        glStencilStrokePathInstancedNV, glCoverFillPathInstancedNV,
        glCoverStrokePathInstancedNV, glGetPathMetricsNV, and
        glGetPathSpacingNV.

    65. What order should the arguments be listed when a range of
        path objects is specified?

        RESOLVED:

        1) uint firstPath,
        2) sizei count

        The glDeletePathsNV command and GetPathMetricRangeNV query use
        this order.

        glDeleteLists uses this same order.

    66. Where does the UTF-8 and UTF-16 specification language come from?

        See the RFC "UTF-8, a transformation format of ISO 10646":

            http://tools.ietf.org/html/rfc3629

        See the RFC "UTF-16, an encoding of ISO 10646":

            http://tools.ietf.org/html/rfc2781

        The intent of the specification language is to match these RFCs.

    67. How does the GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV cover mode
        work for glCoverFillPathInstancedNV and glCoverStrokePathInstancedNV?

        RESOLVED:  The command computes the bounding box of all the
        path's bounding boxes.  (This can be too conservative for an
        arbitrarily arranged collection of path objects but works well
        enough for glyphs in line of text.)

        This bounding box has a consistent counterclockwise winding
        order no matter what path objects are listed.  This property
        is a combination of how glRectf works and how the parameters to
        glRectf are computed.

        The object-space z (depth) is always zero.  (This behavior is
        a consequence of the primitive being emitted by glRectf.) The
        matrix elements in the Z row (if such a row exists) of the
        transforms specified for glCoverFillPathInstancedNV and
        glCoverStrokePathInstancedNV is ignored.

        Programmers are cautioned that this could result in the
        covering geometry being view-frustum culled if the programmer
        is not careful when using 3D transformTypes (GL_TRANSLATE_3D_NV,
        GL_AFFINE_3D_NV, GL_TRANSPOSE_AFFINE_3D_NV).  To guard against
        this mishap, consider something such as the following:

            glMatrixPushEXT(GL_PROJECTION);
              glScalef(1,1,0);
              glCoverFillPathInstancedNV(...);
            glMatrixPopEXT(GL_PROJECTION);

        This essentially forces the clip-space Z to be zero which will
        never be clipped by the near or far view-frustum clip planes.

        If depth testing is desired, perform the depth testing during the
        "stenciling" step so that depth testing is unnecessary during the
        "covering" step done by the glCoverFillPathInstancedNV command.

    68. What happens when the radius of a circular arc command is
        negative?

        UNRESOLVED:  The intent is to match the behavior of the PostScript
        circular arc commands (arc, arcn, arct).  Unfortunately the
        PostScript specification is not entirely clear about how negative
        radius is handled.

        Table 5.arcParameterSpecialization has absolute values (abs)
        computed for the rv and rh columns.

        However, the points A and B (used for arc and arcn) are computed
        with c[2] directly (without an absolute value).

        This computation looks consistent with Ghostscript's behavior
        for arct:

            dist = abs(c[4] * num/denom)
            l0 = dist/sqrt(dot(d0,d0)) * c[4]/abs(c[4])
            l2 = dist/sqrt(dot(d2,d2)) * c[4]/abs(c[4])

        Could this simply be:

            dist = c[4] * num/denom
            l0 = dist/sqrt(dot(d0,d0))
            l2 = dist/sqrt(dot(d2,d2))

       Probably.

       This really needs testing and comparison with a PostScript
       implementation to make sure the specified equations really match
       PostScript's implemented behavior.

    69. What happens when the two angles (c[2] and c[3]) for a circular
        arc command (GL_CIRCULAR_CCW_ARC_TO_NV or
        GL_CIRCULAR_CW_ARC_TO_NV) create 1 or more full revolutions?

        UNRESOLVED:  The intent is to match the behavior of the PostScript
        circular arc commands (arc and arcn).

        PostScript specifies that "If angle2 is less than angle1, it is
        increased by multiples of 360 [degrees] until it becomes greater
        than or equal to angle1.  No other adjustments are made to the
        two angles.  In particular, if the difference angle2-angle1
        exceeds 360 [degrees], the resulting path will trace portions
        of the circle more than once."

        The current equations based on an end-point partial elliptical arc
        parameterization achieve this.  Extra parametric behavior would be
        necessary to trace a circle multiple times.  The current equations
        in Table 5.pathEquations do not capture this (but should).

        This needs to be thought through carefully to make sure stroking,
        particularly when dashed, is handled correctly.

    70. PostScript generates a limitcheck error when numbers are
        encountered that exceed the implementation limit for real numbers.
        Should the PostScript grammar treat such situations as a parsing
        error?

        RESOLVED:  No, it's not a parsing error, but the results in
        such a situation are likely to be undefined.

        This paragraph in Section 5.X.1 ("Path Specification") applies
        which begins "If a value specified for a coordinate (however
        the coordinate is specified) or a value computed from these
        coordinates (as specified in the discussion that follows)
        exceeds the implementation's maximum representable value for a
        single-precision floating-point number, ..."

        The PostScript's notion of a limitcheck error doesn't nicely
        correspond to a parsing error.  And PostScript's notion of "the
        implementation limit for real numbers" (likely double precision)
        might not correspond to the GL's notion of floating-point
        (typically single precision).

        The PostScript notion of a limitcheck on numeric range is
        particularly hard to enforce with relative commands where the
        limitcheck might not occur until all the relative offsets are
        applied, something which isn't really part of parsing.

        What an actual implementation does may vary but a likely
        implementation approach is generate an IEEE infinity value when
        single-precision floating-point range is exceeded.  This will
        generate undefined rendering behavior.

        SVG doesn't offer guidance in its specification when coordinate
        values exceed the representable range of floating-point.
        Presumably such range overflows result in implementation-dependent
        undefined rendering behavior too.

    71. What happens when the radius of a OpenVG-style partial elliptical
        arc commands is negative?

        RESOLVED:  The absolute value of the radius is used for
        the OpenVG-style arc commands GL_SMALL_CCW_ARC_TO_NV,
        GL_RELATIVE_SMALL_CCW_ARC_TO_NV, GL_SMALL_CW_ARC_TO_NV,
        GL_RELATIVE_SMALL_CW_ARC_TO_NV, GL_LARGE_CCW_ARC_TO_NV,
        GL_RELATIVE_LARGE_CCW_ARC_TO_NV, GL_LARGE_CW_ARC_TO_NV, and
        GL_RELATIVE_SMALL_CW_ARC_TO_NV.

        Table 5.arcParameterSpecialization specifies an absolute value
        (abs) in the rh and rv entries of all these commands.

        The OpenVG specification is clear on this point in section 8.4
        ("Elliptical Arcs") saying "Negative values of [radii] rh and
        rv are replaced with their absolute values."

    72. What should happen for a stroked subpath that is zero length?

        UNRESOLVED:  Not sure yet.

        SVG gives this advice:

            http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes

        Probably need to check what other path renders, particularly
        PostScript do in this situation.  Requires testing actual
        implementations because the specifications are not clear.

    73. Why have the GL_PATH_CLIENT_LENGTH_NV path parameter?

        RESOLVED:  This supports SVG's pathLength attribute used to
        calibrate distance-along-a-path computations.

        This applies to dashing a stroked segment, but does NOT
        apply to the lengths returned by the glGetPathLengthNV and
        glPointAlongPathNV queries.

        The client length just applies to dashing because having a
        client length that is different from the GL's computed length
        for a path may greatly affect the dashing pattern.  The client
        knows the path's client length, but the GL doesn't unless the
        client state is available to the GL when dashing a stroked path.

        It's better to have the client send the client path length
        unconditionally than require the client to query the GL's computed
        path length ahead of any sending of a rescaled version of the
        dash offset or dash array.

        For the queries, presumably the client can perform the necessary
        scaling by the client length itself if that's desirable.

    74. Should there be a query for GL_PATH_END_CAPS_NV and
        GL_PATH_DASH_CAPS_NV?

        RESOLVED:  No.  You have to query GL_PATH_INTIAL_END_CAP_NV or
        GL_PATH_TERMINAL_END_CAP_NV for the each respective end cap; or
        query GL_PATH_INITIAL_DASH_CAP_NV or GL_PATH_TERMINAL_DASH_CAP_NV
        for each respective dash cap.

        GL_PATH_END_CAPS_NV and GL_PATH_DASH_CAPS_NV are convenient
        for most path rendering systems that have identical initial
        and terminal end and dash caps, but are NOT supported by
        glGetPathParameteriv or glGetPathParameterfv.

    75. What should the path format tokens for SVG and PostScript tokens
        be named?

        RESOLVED:  Use the abbreviated names SVG and PS respectively:
        GL_PATH_FORMAT_SVG_NV and GL_PATH_FORMAT_PS_NV.  These names
        are shorter and avoid putting an Adobe trademark in a token name.

        Future extensions might want to add version numbers to these
        abbreviated names (another reason to stick with short abbreviated
        names).

    76. In what content (GL client or GL server) are font file names
        and system font names interpreted?

        RESOLVED:  The GL_STANDARD_FONT_NAME_NV and GL_SYSTEM_FONT_NAME_NV
        font targets map their respective font names to a font within
        the GL server.  The GL_FILE_NAME_NV font target does the file
        reading in the GL client; for GLX, there needs to be GLX protocol
        to transfer glyphs including their kerning and metric data to
        the GL server.

    77. How can the glPathSubCommandsNV command be used to append to
        the end of an existing path object?

        RESOLVED:  If you set the /commandStart/ parameter to
        glPathSubCommandsNV to be sufficiently large (greater or equal
        to the number of path commands in the path object suffices),
        that works to append commands.

    78. Does depth offset (a.k.a. polygon offset) work when using the
        "stencil" and "cover" path operations?

        RESOLVED:  Yes with caveats.

        The "stencil" path operations use the
        GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV and
        GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV state set by
        glPathStencilDepthOffsetNV.  There is no specific enable; instead
        set the scale and units to zero if no depth offset is desired.

        The "cover" path operations use the polygon depth offset state if
        the GL_POLYGON_OFFSET_FILL enable is enabled, using the polygon
        offset factor and units specified for glPolygonOffset.  This is
        because the "cover" operation (unlike the stencil operation)
        does rasterize a polygon primitive.

        Depth offset is useful when a path rendered decal is applied
        on depth tested 3D geometry and the path rendered geometry has
        to be biased forward (negative bias) by polygon offset to avoid
        depth ambiguities.  See issue #120 for details.

        This is also useful when putting path rendered primitives into
        shadow maps with a positive depth bias to avoid shadow acne
        issues.

        There is NOT a guarantee that the depth offset computed for a
        "stencil" operation will exactly match the depth offset for a
        "cover" operation given identical path object and transformations.
        The two offsets will be close but not generally exact for all
        generated samples.

    79. Can fragment shaders access the facingness state during a cover
        operation?

        RESOLVED:  Yes, the gl_FrontFacing special variable in GLSL
        is available.  So is the fragment.facing fragment attribute
        binding in NV_fragment_program2 and subsequent NVIDIA shader
        assembly extensions.

        In cases where the path rendered primitive is "very edge" on the
        facingness fragment state may be ambiguous in extreme situations.

    80. When are various computed path parameters re-computed?

        RESOLVED:  If the computed parameter parameters
        (PATH_COMMAND_COUNT_NV, PATH_COORD_COUNT_NV,
        PATH_DASH_ARRAY_COUNT_NV, PATH_COMPUTED_LENGTH_NV,
        PATH_OBJECT_BOUNDING_BOX_NV, PATH_FILL_BOUNDING_BOX_NV, and
        PATH_STROKE_BOUNDING_BOX_NV) are queried, the values returned
        always reflect the most up-to-date state of the path object.

        This also includes when path object parameters are used in
        contexts such as instanced "cover" operations.

    81. Should projective 2D path coordinates be supported?

        RESOLVED:  No.  Major path rendering standards don't support
        projective 2D path coordinates.

        Moreover, projective 2D path coordinates create technical
        problems because the projective transformation of projective
        2D path coordinates for cubic Bezier curves do not necessarily
        retain their topology (serpentine, cusp, or loop).

    82. Should a non-dashed stroked path's coverage be the same
        independent of how its control points are specified?

        RESOLVED:  Yes, this is a symmetry rule mandated by the OpenXML
        Paper Specification.  This applies to lines and Bezier curves.

        So a cubic Bezier curve defined by control points cp0, cp1, cp2,
        and cp3 should generate the same stroked coverage (assuming the
        same stroke parameters and requiring the dash array count to be
        zero) as a cubic Bezier curve with control points cp3, cp2, cp1,
        and cp0 (so the reversed control point order).

        XXX Unresolved if it applies to arcs.

    83. Should character aliases used to specify path commands be returned
        as their character alias values or remapped to the actual token
        name of the command?

        RESOLVED:  Remapped.  Any path commands specified with a
        character alias value (from Table 5.pathCommands) is returned
        as the command's token value instead.

        This avoids applications calling glGetPathCommandsNV from having
        bugs where they handle token names but not character aliases.

        This also makes it simpler to say "identical" when saying command
        sequences must match for glWeightPathsNV.  Character aliases
        remapped to command token values makes it unambiguous that
        GL_LINE_TO and 'L" are the identical command.

    84. Is there a way to use this extension to trade-off rendering performance
        for more effective samples per pixel to improve coverage quality?

        RESOLVED:  Yes.

        This code demonstrates how multiple passes could accumulate
        coverage information in the alpha channel of the framebuffer and
        then a final cover pass could blend the incoming color with the
        accumulated coverage from the framebuffer's alpha channel.

            // INITIALIZATION
            // assume stencil is cleared to zero and framebuffer alpha is clear to zero
            const int coveragePassesToAccumulate = 4;
            glEnable(GL_STENCIL_TEST);
            glStencilFunc(GL_NOT_EQUAL, 0x80, 0x7F);
            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);  // tricky: zero 0x7F mask stencil on covers, but set 0x80
            glColorMask(0,0,0,1);  // just update alpha

            // M STENCIL+COVER PASSES to accumulate jittered path coverage into framebuffer's alpha channel
            glStencilFillPathNV(path, GL_COUNT_UP_NV, 0x7F);
            glCoverFillPathNV(path, GL_PATH_FILL_COVER_MODE_NV);
            glEnable(GL_BLEND);
            glBlendFunc(GL_ONE, GL_ONE); // sum up alpha
            glColor4f(0,0,0, 1.0/coveragePassesToAccumulate );
            static const GLfloat jitters[4][2] = {
              {0,0},  /* various small subpixel jitter X & Y values */
            };
            for (i=1; i<coveragePassesToAccumulate ; i++) {
              glMatrixPushEXT(GL_MODELVIEW); {
                glMatrixTranslatef(GL_MODELVIEW, jitters[i][0], jitters[i][1], 0);
                glStencilFillPathNV(path, GL_COUNT_UP_NV, 0x7F);
                glCoverFillPathNV(path, GL_PATH_FILL_COVER_MODE_NV);
              } glMatrixPopEXT(GL_MODELVIEW);
            }

            // FINAL COVER PASS uses accumulated coverage stashed in destination alpha
            glColorMask(1,1,1,1);
            // modulate RGB with destination alpha and then zero destination alpha
            glBlendFuncSeparate(GL_DST_ALPHA, GL_ZERO, GL_ZERO, GL_ZERO);
            glColor4f(red, green, blue, dontcare);  // some color
            glStencilFunc(GL_EQUAL, 0x80, 0xFF);  // update any sample touched in earlier passes
            glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);  // now set stencil back to zero (clearing 0x80)
            glCoverFillPathInstancedNV(coveragePassesToAccumulate,
                GL_UNSIGNED_BYTE, "\0\0\0\0",  // tricky: draw path objects path+0,path+0,path+0,path+0
                path,  // this is that path object that is added to zero four times
                GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV, GL_TRANSLATE_2D_NV, jitters);

        Assuming N passes and M samples per pixel, this approach
        accumulates coverage for N*M+1 grayscale levels doing N stencil
        operations and N+1 cover operations.

    85. Why do the commands glGenPathsNV and glDeletePathsNV allocate
        contiguous ranges of path objects instead of returning an array of
        (possibly scattered) names and deleting an array of names?

        RESOLVED:  The expectation that path objects will be arranged
        as characters mapping to glyphs warrants adopting the object
        model of display lists.

        glPathGlyphRangeNV, the instanced commands, and the metric and
        kerning queries all rely on this assumption.

    86. What do the stencil and cover commands do if the specified path
        name does not refer to an existing path object?

        RESOLVED:  Do nothing (and generate no error).

        This is useful to avoid rendering unpopulated path objects.

        This "do nothing" behavior also applies to the instanced
        stencil and cover routines that are expressed in terms of
        glStencilFillPathNV, glStencilStrokePathNV, glCoverFillPathNV,
        and glCoverStrokePathNV.

        Applications that want some "glyph is missing" for non-existent
        path objects can use glCopyPathNV to copy some existing path
        object's "glyph is missing" outline to non-existent paths.
        Alternatively, glPathGlyphRangeNV (or glPathGlyphsNV) can be used
        with the GL_STANDARD_FONT_NAME of "Missing" to populate a range
        (or sequence) of path objects with a standard missing glyph
        (typically a rectangle).  (See issue #89.)

        Queries (glGetPathParameteriv, etc.) allowing only a single path
        object to be specified, generate a GL_INVALID_OPERATION error
        if the path name does not exist.

        glWeightPaths, glInterpolatePathsNV, and glCopyPathNV generate
        a GL_INVALID_OPERATION error if any of the named source paths
        do not exist.

        Path commands that modify the commands, coordinates, or parameters
        of existing path objects (as opposed to specifying a path object
        completely) generate a GL_INVALID_OPERATION error if the path
        name does not exist.

    87. What of this extension's per-context state should apply to
        glPushAttrib and glPopAttrib?

        RESOLVED:  Apply the existing conventions; see new table 6.X,
        "Path (state per context)".

        The path fog generation mode applies to GL_FOG_BIT.

        The path color generation mode and coefficients apply to
        GL_LIGHTING_BIT.

        The path texture coordinate set generation modes and coefficients
        apply to GL_TEXTURE_BIT.

        The path error position is not pushed or popped, following the
        convention of the ARB_vertex_program extension.

    88. How should the numCoords parameter to the various path
        specification commands work?

        RESOLVED:  When there is also a /numCoords/ parameter,
        the GL_INVALID_OPERATION error is generated if the number of
        coordinates is not equal to the number of coordinates needed by
        the command's specified path command sequence.  This provides
        a sanity check.

        For the glPathSubCoordsNV command, there's no requirement that
        the range of coordinates "match up" with path command boundaries
        for coordinates.

        Some consideration was given to specifically treating a value of
        zero for /numCoords/ by allowing the number of coordinates to
        be based on the command's corresponding path command sequence.
        This would allow an application to bypass the sanity check if
        the application didn't exactly know how many coordinates a path
        command sequence required.  This was rejected because it is likely
        error-prone and it means when such commands are compiled into
        a display list or packed into GLX protocol, the path command
        sequence would then have the be scanned.  This would make the
        GL client unnecessarily knowledgeable about the supported path
        commands.  So for both "safety" and implementation reasons,
        the /numCoords/ value of zero is not specially interpreted;
        it means that the path command sequence really is expected to
        require zero coordinates (not generally the case except for the
        GL_CLOSE_PATH_NV command).

    89. How can an application guarantee that every glyph in a range
        of Unicode character codes has /some/ default outline defined?

        RESOLVED:  The "Missing" name with the GL_STANDARD_FONT_NAME_NV
        target populates the entire sequence or range of path objects
        with a default outlines.

        Example:

          const int allOfUnicode = 1<<21;  // Entire 21-bit Unicode range!
          const GLfloat emScale = 2048;
          GLuint glyphBase = glGenPathsNV(allOfUnicode);
          glPathGlyphRangeNV(glyphBase,
                             GL_STANDARD_FONT_NAME_NV, "Missing", GL_NONE,
                             0, allOfUnicode, emScale);

    90. Does the "Missing" font name used for GL_STANDARD_FONT_NAME_NV
        skip or avoid character codes that Unicode designates as white
        space, line terminators, etc.

        RESOLVED:  The "Missing" font name populates these with a path
        object with the missing outline (a box) and corresponding metrics
        for such spacing characters and all other characters.

        The assumption is that Unicode fonts will populate various
        blank space, line and paragraph terminators, and other blank
        or ignorable character points with appropriate null outlines
        and zero-width metrics.  Because glPathGlyphRangeNV and
        glPathGlyphsNV don't re-specify existing path objects, these
        will be left along if the "Missing" standard font is the last
        font used to specify a given range of path objects.  All white
        space and separator character codes less than 256 (the Latin-1)
        range will be populated by the "Serif", "Sans", and "Mono"
        standard fonts if specified because these guarantee the Latin-1
        range is populated.  These are specifically U+0009..000D, U+0020,
        U+0085, 0x00A0 but also other blank or ignorable character points
        such as control characters.

        For more information:

            http://unicode.org/faq/unsup_char.html

    91. What is the /emScale/ parameter to glPathGlyphRangeNV and
        glPathGlyphsNV for and how should it be used?

        RESOLVED:  /emScale/ exists to ensure multiple fonts, potentially
        with distinct font unit scales, can be scaled to a consistent
        scale.

        Typically TrueType fonts are authored for 2048 font units per
        Em while Type1 fonts have been historically authored to 1000
        font units per Em.

        Typically a good value for /emScale/ is 2048 to match the
        convention of TrueType.  This avoid TrueType font metrics from
        being rescaled.

        Setting /emScale/ to zero allows the native font units per Em
        to be used.  Be careful because outlines of path objects for
        glyphs from fonts with different font units per Em will have
        different scales.

    92. Should glWeightPathsNV work for a single path object?

        RESOLVED:  No, two or more paths are required to generate a
        weighted path.

        Use glCopyPathNV if copying a single path object is desired.

        glCopyPathNV copies glyph metrics and kerning information and
        allows arc commands while glWeightPathsNV does not.

        While glInterpolatePathsNV can be expressed in terms of
        glWeightPathsNV, glCopyPathNV cannot.

    94. What should the initial join style of a path object be?

        RESOLVED:  GL_MITER_REVERT_NV.  This is consistent with the join
        style used by SVG, PostScript, PDF, and Cairo.

        Note that Flash, XPS, and Qt use GL_MITER_TRUNCATE_NV instead.

        Arguably GL_MITER_TRUNCATE_NV is a "nicer" join style because
        the miter does not "pop" from miter to bevel when the miter limit
        is exceeded; instead when the miter limit is approached and then
        exceeded, the miter stops growing further and simply loses its
        sharp tip.

    95. What type of triangle should the GL_TRIANGULAR cap be?

        RESOLVED:  A right triangle.

        This is consistent with the XPS specification.  Other standards
        don't support triangular caps.

    96. Can NV_path_rendering be implemented without *any* dependencies
        on system specific fonts?

        RESOLVED:  YES.

        Say a platform had poor or unstable interfaces for accessing
        system specific fonts (e.g. Linux).  In the case of Linux,
        resolution-independent fonts are typically accessed through a
        combination of freetype2 and fontconfig.

        One or both of these standards may be missing from the platform
        or be unreliable or misconfigured.

        In such a case, NV_path_rendering could be implemented so
        that the GL_SYSTEM_FONT_NAME_NV usage for glPathGlyphsNV and
        glPathGlyphRangeNV would never populate path object names with
        glyphs.

        However the GL_STANDARD_FONT_NAME_NV usage would still be
        guaranteed.  The GL_STANDARD_FONT_NAME_NV usage by providing
        the required set of pre-compiled font outlines built-in into the
        driver directly (using IP unencumbered font outlines such as
        the DejaVu fonts).

        This design means that applications that use the approach
        (copied from the Overview) will work:

            glPathGlyphRangeNV(glyphBase,
                               GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV,
                               0, numChars, emScale);
            glPathGlyphRangeNV(glyphBase,
                               GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV,
                               0, numChars, emScale);
            glPathGlyphRangeNV(glyphBase,
                               GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV,
                               0, numChars, emScale);

        In this case, the two initial glPathGlyphRangeNV calls
        will fail to populate the range of path objects from
        [glyphBase,glyphBase+numChars-1] but the third call will populate
        the range.

        This allows NV_path_rendering to be implemented with ZERO
        dependencies on the system to provide glyphs from system fonts while
        applications can still utilize fonts in their path rendering.

        While this is an allowed implementation approach, actual
        implementations should make reasonable efforts to provide access
        to system fonts if possible.

    96. What is GL_DASH_OFFSET_RESET_NV for?

        RESOLVED:  OpenVG supports the concept of a "dash phase reset"
        (see VG_DASH_PHASE_RESET) that controls whether or not the dash
        pattern (with its offset) resets at "move to" command boundaries
        within a path's command sequence.

        Rather than use a boolean value (as OpenVG does), the
        GL_DASH_OFFSET_RESET_NV path parameter takes an enumeration
        consisting of GL_MOVE_TO_RESETS_NV and GL_MOVE_TO_CONTINUES_NV
        to be more explicit about how the dash offset reset parameter
        affects the dash pattern.

        Technically, what this specification calls the "dash offset"
        is what OpenVG calls its "dash phase".  This specification
        uses "dash phase" to mean what OpenVG calls "dash phase reset"
        because the word "reset" is built into the GL token values.

        When there is a dash phase reset, the dash offset is set to the
        value of the path's GL_DASH_OFFSET_NV parameter (consistent with
        OpenVG).

    97. What APIs say "dash offset" and what APIs say "dash phase" and
        why does this extension use "dash offset"?

        RESOLVED:  PostScript, PDF, Cairo, Qt, XPS, SVG, and Silverlight
        use the "dash offset" for the offset to the dash pattern, same
        as this extension.

        OpenVG, Quartz 2D, Java 2D, Illustrator, and Skia use the term
        "dash phase" for the identical functionality.

        OFFSET makes more sense in the OpenGL context because lots of
        OpenGL tokens already use OFFSET in their token names.  Core
        OpenGL 4.0 has 16 such tokens already.

    98. What is the motivation for glTransformPathNV?

        RESOLVED:  Sometimes a path should be stroked with a stroke width
        that is constant in a particular space (such as window space).

        Once example of this is SVG 1.2 Tiny's "non-scaling stroke"
        property.  The stroke width is supposed to be maintained after
        transformation into pixel space.

        This could be implemented with this extension by transforming
        the path object into the appropriate space so that the user-space
        stroke width will match the transformed space.

    99. Should the specification say more about how arcs are transformed?

        UNRESOLVED:  Certainly yes, but I'm not sure exactly how to
        specify how arcs are transformed with a suitable level of
        formalism.

        I'm not clear if partial elliptical arcs can be subjected to
        projective transformations and remain partial elliptical arcs.
        I believe they can.

   100. How is glTransformPathNV different from OpenVG's vgTransformPath?

        RESOLVED:  The two commands are similar.

        The OpenVG 1.1 version always converts vertical and
        horizontal line commands to generic line to commands where as
        glTransformPathNV does that only if the resulting transformed
        line segment is no longer either vertical or horizontal in the
        new coordinate system.  This allows cases such as 90 degree
        rotations or scaling without rotation to preserve the compactness
        of vertical and horizontal line segments.

        In OpenVG 1.1, the VG_MATRIX_PATH_USER_TO_SURFACE matrix
        used by vgTransformPath is a 3x3 projective matrix where as
        glTransformPathNV supports up to 4x4 projective matrices.
        Note that the z component of any transformed coordinate is
        effectively discarded by glTransformPathNV so the z row and
        column is not consequential to the resulting transformed path.
        The rationale for this is to allow the same 4x4 transform matrix
        array used by 3D to be used by glTransformPathNV.

        In OpenVG 1.1, the matrix is implicitly supplied by the
        VG_MATRIX_PATH_UER_TO_SURFACE matrix whereas in glTransformPathNV,
        the matrix is explicitly specified.

        XXX Perhaps there should be a special mode that uses the
        modelview-projection-viewport transform implicitly?

   101. Can you provide an example of non-scaling strokes implemented with
        glTransformPathNV?

        UNRESOLVED:  To be written.

   102. What happens if a command that creates a path from existing path
        objects has the result path name as one of the inputs?

        RESOLVED:  This is expected to just work.  The new path object
        is created from the existing ones, then the new path object
        replaces any path object with the resulting path object name.

   103. Should glTransformPathNV support projective transformations?

        RESOLVED:  No, such projective transformations could result
        in path commands transitioning from non-rational to rational
        boundaries.

        If points on the path boundary are generated by non-rational
        boundaries, the resulting transformation, assuming a
        non-projective transformation, also results in non-rational
        boundaries.

   104. Should there be a distinct stencil function state for path
        stenciling?

        RESOLVED:  YES.  glPathStencilFunc sets the state.  How the
        stencil state needs to be configured for path covering is
        different than how the stencil function is configured typically
        for path stenciling.

        For example, stencil covering might use
        glStencilFunc(GL_NOT_EQUAL,0,~0) while path stenciling would
        use GL_ALWAYS for the path stenciling stencil test.

        However there are other situations such as path clipping where it
        is useful to have the path stencil function configured differently
        such as glPathStencilFunc(GL_NOT_EQUAL, 0x00, 0x80) or other
        similar path clipping test.

   105. Is there back- and front-facing path stencil function state?

        RESOLVED:  NO.  There is a single stencil function, reference
        value, and read mask.  The path stenciling operation doesn't
        have a sense of front- and back-facing.

   106. Does the path stencil function state apply always or only if
        stencil testing is enabled?

        RESOLVED:  Always.  If you want to avoid discarding samples
        from this test, use the GL_ALWAYS path stencil function (which
        is the initial context state).

   107. Does the glPathStencilFuncNV state affect the operation of
        the stencil test during path cover operations?

        RESOLVED:  NO, the path stencil state updated by
        glPathStencilFuncNV only affects the path stencil (not cover)
        operations.

        For the path cover operations, the *normal* stencil test applies.
        For the stencil test to apply to path cover operations, the
        stencil test (GL_STENCIL_TEST) must be enabled.

   108. Should path objects be shared among rendering contexts in the
        same manner as display lists and texture objects?

        RESOLVED:  Yes.

        See the "Additions to the AGL/GLX/WGL Specifications" section.

        Because path objects are not "bound" there are stricter
        serialization requirements than for "bindable" objects such as
        programs and textures.

        Due to NVIDIA driver bug 1315267, path objects were not actually
        shared among contexts prior to Driver release 320.xx (July 2013).

   109. Should the kerning separations be 2D offsets or 1D horizontal
        translations?

        UNRESOLVED:  The specification is currently written for 1D
        horizontal translations.

        TrueType fonts appears to provide 1D horizontal translations
        for kerning.

        However a PostScript font can contain 2D offsets for kerning.

        Are 2D offsets really used?  2D offsets seem like an unnecessary
        complication when they are unlikely to be common.

        XXX Need to study this situation further.

        If 99.99% of fonts never use 2D offsets, it is annoying to have
        them for the ultra minority that might.  Not sure what the real
        situation is...

        Perhaps we could provide tokens to query either 1D horizontal
        translations or the more general 2D offsets.  But how would an
        application know whether a font actually specified 2D offsets
        or not??

   110. What is the initial miter limit of a path object?

        RESOLVED:  4 to match the SVG specification.  See:

            http://www.w3.org/TR/SVG/painting.html#StrokeMiterlimitProperty

        There is a lot of variability in initial miter limit values among
        path rendering APIs.  The SVG initial miter limit is chosen
        because SVG is an open, web-based standard.

        For Cairo, the initial miter limit is 10.

        For Direct2D, the initial miter limit is 10.

        For Flash, the initial miter limit is 3.

        For PostScript, the initial miter limit is 10.

        For Qt, the initial miter limit is 2 units of the stroke width.

        For Skia, the initial miter limit is 4.

   111. Should initial path object state such as miter limit, stroke width, etc.
        be determined by "latching" per-context initial value state for
        these parameters?

        UNRESOLVED

        Possibly.  That would make it easier for a particular path
        rendering API's conventions initial conventions be consistently used
        to initialize path object parameters.

   112. Should glPathFogGenNV's GL_FRAGMENT_DEPTH mode provide a
        perspective-divided value?

        RESOLVED:  No, -ze is provided rather than -ze/we.

        Providing -ze/we would not interpolate properly over the path.
        Typically the modelview matrix used to compute ze is affine so we
        will be 1.0 in such cases and the lack of division won't matter.

        If the modelview matrix is projective, the application can choose
        to interpolate we as a texture coordinate with glPathTexGenNV's
        GL_EYE_LINEAR mode and perform the division -ze/we during fragment
        coloring.

   113. How should path color and texture coordinate generation be
        disabled?

        RESOLVED:  For color:

           glPathColorGenNV(colorFormat, GL_NONE, GL_NONE/*colorFormat*/, NULL);

        For texture coordinate generation:

           glPathTexGenNV(GL_TEXTURE_0+i, GL_NONE, 0/*components*/, NULL);

        The coeffs array could be an arbitrary pointer because it will
        only be dereferenced if the genMode is GL_NONE, but NULL is a
        suitable value to document this fact.

        Querying the respective coefficients after path color or texture
        coordinate disabling commands above should return 16 zeros.

   114. How should path color and texture coordinate generation interact
        with the GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV instanced cover
        mode?

        RESOLVED:  The effective bounding box is the union of all the
        instanced bounding boxes.

        This is useful for something such as a line of text rendered as
        sequence of glyph path objects where the line of text should share
        a common gradient tied to the bounding box of the line of text.

   115. How do I ignore kerning when using glGetPathSpacingNV?

        RESOLVED:  Pass in 0.0 for the kerningScale parameter.

   116. How do I query the raw kerning parameters?

        RESOLVED:  Pass in 0.0 for the advanceScale parameter and 1.0
        for the kerningScale parameter.

   117. Do I need to use GL_TRANSLATE_2D_NV when getting spacing
        information from glGetPathSpacingNV?

        RESOLVED:  Typically GL_TRANSLATE_X_NV is fine.

        Typically most kerned fonts (particularly TrueType fonts) using
        kerning offsets that are horizontal only.  PostScript technically
        allows 2D (x,y) kerning offsets and FreeType 2's FT_Get_Kerning
        API also returns 2D kerning vectors.

        To support 2D kerning vectors, glGetPathSpacingNV accepts
        GL_TRANSLATE_2D_NV as well as GL_TRANSLATE_X_NV.

        For most fonts, the Y offset can be expected to be zero.

   118. Why have the /pathParameterTemplate/ parameter to
        glPathGlyphRangeNV and glPathGlyphsNV?

        RESOLVED:  Path object specified from glyphs often need parameters
        specified on a per-font basis that are distinct from the initial
        path object parameters in table 6.Y.

        Rather than force an application to respecify the path parameters
        of all the path objects in a range of path objects for glyphs,
        it is more efficient for such glyph-initialized path objects
        to simply use parameters from another existing path object as
        a template.

        For example, the default stroke width of 1.0 might need to be
        respecified for every path object corresponding to a range of
        glyphs for rendering stroked glyphs.  If the emScale for a glyph
        is 2048 (typical of TrueType fonts), then 1.0 is too thin to be a
        discernable stroke width.  A value such as 10% of the Em scale (so
        10% of 2048 would be 20.48) is likely to be a more useful value.

        Similarly, GL_ROUND_NV or GL_BEVEL_NV are better join styles
        for stroking glyphs than the standard join style initial value
        GL_MITER_REVERT_NV.

        A shared dash pattern for all path objects belonging to a single
        set of glyphs is much easier to specify from a template path
        object.

   119. Are system font names and file names for fonts case-sensitive?

        RESOLVED:  Standard font names (such as "Mono" and "Missing"
        are case-sensitive).  System font name names and file names for
        fonts should match the system's policy for case-sensitivity of
        font names and file names respectively.

        Linux and other Unix-like operating systems have case-sensitive
        file names.  Windows has case-insensitive file names.  Windows and
        FontConfig-based systems have case-insensitive system font names.

   120. Why have PathStencilDepthOffsetNV and PathCoverDepthFuncNV?

        RESOLVED:  These functions minimize the state changes needed
        to depth test path rendering consisting of several co-planar
        path layers (as is typical of path rendering content) against
        conventional depth-tested 3D rendering.

        To properly depth test path rendering against conventional 3D
        rendering and other path rendering, particularly when a set of
        paths layer upon themselves, it is necessary to pull forward
        slightly the depth values generated during the stenciling step.
        This avoids Z-fighting when drawing path rendered layers that
        are logically co-planar.  However when covering pixels (assuming
        the stencil test passed during covering), we unconditionally
        write un-offset depth values.

        To depth-test path rendered content in this manner, follow the
        following pattern:

        Perform the following initialization:

            // Conventional initialization for depth testing and using path rendering
            glEnable(GL_DEPTH_TEST);
            glStencilFunc(GL_NOT_EQUAL, 0, 0xFF);
            glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);

            // The additional calls for depth testing of path-rendering...
            glPathStencilDepthOffsetNV(-0.05, -1);  // push stenciled path depth values slightly closer
            glPathCoverDepthFuncNV(GL_ALWAYS);

        Clear the framebuffer, including the depth buffer:

            // Clearing
            glClear(GL_COLOR_BUFFER_BIT |
                    GL_STENCIL_BUFFER_BIT |
                    GL_DEPTH_BUFFER_BIT);

        For each rendered path object...

            0)  Make sure stencil testing is enabled (in case it was
                disabled to draw prior conventional 3D objects).

                glEnable(GL_STENCIL_TEST);

            1)  Stencil step:

                glStencilFillPathNV(pathObj, GL_COUNT_UP_NV, 0xFF);

            2)  Cover step:

                glCoverFillPathNV(pathObj, GL_COUNT_UP_NV, 0xFF);

        For conventional 3D objects...

            0)  Make sure stencil testing is disabled (in case it was
                enabled to draw prior path rendered objects).

                glDisable(GL_STENCIL_TEST);

            1)  Draw normally:

                draw_3d_object_normally();

        With this pattern, conventional and path rendered objects can
        be rendered in arbitrary order.

        The above pattern shows path filling, but path stroking works
        the same.

        Notice only the initialization calls to
        glPathStencilDepthOffsetNV and glPathCoverDepthFuncNV are
        actually "different" than conventional 3D or path rendering.

        One potential disadvantage of this approach is that other objects
        with nearly identical depth values to the depth values of the
        path rendering content may be judged to pass the depth test when
        technically the other object's depth values are slightly closer.
        This is because the path stencil depth offset is pushing path
        rendering depth values slightly closer.  While this is possible,
        this occurs in situations where the proper occlusion was nearly
        ambiguous because the depth values between the other object and
        the path rendering are so close.

   121. What if the disadvantage of depth values having to be offset closer
        is deemed unacceptable (this will be rare).

        RESOLVED: If 100% exact depth occlusion is crucial to the
        application, this can be achieved at some cost be stenciling
        a planar conservative bounding region for the path object into
        the stencil buffer, depth testing the rendering of this plane.
        This depth-tested plane region should not perform color writes
        but should set the most-significant bit of the stencil buffer
        (for an 8-bit stencil buffer, done with GL_REPLACE of 128).
        Then path rendering, with depth testing DISABLED, can use
        the glPathStencilFunc to discard stencil values without the
        most-significant bit set.  Finally the plane region must
        be redrawn again to clear any stencil values left with the
        most-significant bit set.  This approach essentially uses the
        depth plane region as a depth-tested proxy for the proper depth
        values for the path rendering.

   122. How should the path stencil depth offset be described?

        RESOLVED:  The function is named glPathStencilDepthOffsetNV and
        the query tokens are GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR and
        GL_PATH_DEPTH_OFFSET_UNITS.

        Note that "polygon offset" does not appear in the name.  Polygon
        offset isn't appropriate in the context of path rendering because
        paths aren't technically polygon primitives.  The term "depth
        offset" is the actual name of the functionality that offsets
        depth values of polygons (the name of section 3.6.4 specifying
        glPolygonOffset is actually titled "Depth Offset").

        There's no perfect attribute category of state for path stencil
        depth offset factor and units to belong so the "polygon" category
        just like the polygon offset state.

   123. Does glPointAlongPathNV have anything to do with the path's
        dashing state?

        RESOLVED:  No.

        The arc length computation necessary for glPointAlongPathNV
        computes the arc length along the path (really a subpath) but
        ignores any gaps created by the dash pattern.

        Knowing the dash count, pattern, offset, and reset state, you
        could adjust the distance passed to glPointAlongPathNV to account
        for dashing gaps, but this is something the application must do.

   124. Should PostScript user path parser enforce the same error
        conditions as PostScript?

        RESOLVED:  No.

        Section 4.6.1 (User Path Construction) in the PostScript Language
        Reference Manual explains user paths.

        The section includes some restrictions.  The "ucache" operator
        is optional but must be the first operator in a user path.
        The "setbbox" operator is required.  The next operator must be an
        "absolute positioning operator (moveto, arc, or arcn)."

        The grammar in 5.X.1.2.2 (PostScript Path Grammar) does not
        enforce these restrictions.  In particular, the operators can
        appear in any order and none are required.

        The rationale for this relaxed behavior is: 1) to make the
        parser easier to specify, 2) make the specification of a path
        object through a PostScript path grammar more consistent with
        specifying a path using glPathCommandsNV, and 3) not require
        specification of a user path bounding box that isn't relevant
        in the context of OpenGL rendering.

        If a path command is used without a prior absolute positioning
        command, the initial position is assumed to be (0,0).  So a string
        such as "40 50 lineto" would draw a line from (0,0) to (40,50).

   125. The ISO PDF 32000 standard has additional path construction
        operators for rectangles and cubic Bezier curves with duplicated
        first or last control points.  Should this extension have
        first-class path commands for these operators?

        RESOLVED:  Yes.  These PDF operators correspond
        to the path commands GL_DUP_FIRST_CUBIC_CURVE_TO_NV,
        GL_DUP_LAST_CUBIC_CURVE_TO_NV, and GL_RECT_NV, corresponding to
        the operators "v", "y", and "r" respectively.

        See Table 59 (Path Construction Operators) in the PDF 32000-1:2008
        specification (page 133).  See:

            http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf  [[ free version ]]
            http://www.iso.org/iso/iso_catalogue/catalogue_ics/catalogue_detail_ics.htm?csnumber=51502

        These additional operators make path specification and storage
        more compact, help editing, and better semantically match the
        important PDF standard.  PDF supports just absolute versions of
        these commands so relative versions are NOT provided.

        The "m", "l'", "c", and "h" operators correspond to GL_MOVE_TO_NV,
        GL_LINE_TO_NV, GL_CUBIC_CURVE_TO_NV, and GL_CLOSE_PATH_NV
        respectively.

        There is not a string grammar for glPathStringNV to encode
        PDF commands.

   126. What is the GL_RESTART_PATH_NV path command for?

        RESOLVED:  It is useful to be able to concatenate path
        command sequences as if they are independent from each other.
        The GL_RESTART_PATH_NV provides a way to reset the state of
        path command processing back to its initial state when the first
        command of a path's command sequence is processed.

        So you could use glPathSubCommandsNV to append a path sequence
        to an existing path object's sequence.  By first appending a
        GL_RESTART_PATH_NV command, you make sure the result is consistent
        with drawing the path sequences independently.

        Specifically, /sp/, /cp/ and /pep/ are re-initialized to (0,0) when
        a GL_RESTART_PATH_NV path command is encountered.

        Additionally, this restart also has the effect of causing
        CIRCULAR_TANGENT_ARC_TO_NV to NOT draw an initial tangent line
        segment.  So if you want to draw multiple independent circular
        arcs using the GL_CIRCULAR_TANGENT_ARC_TO_NV parameterization,
        you need a GL_RESTART_PATH_NV command just prior to each
        GL_CIRCULAR_TANGENT_ARC_TO_NV command.  In this respect,
        GL_RESTART_PATH_NV is different from a GL_MOVE_TO_NV command to
        (0,0).

        The GL_RESTART_PATH_NV does not by itself reset the dash
        offset, but if the path's GL_PATH_DASH_OFFSET_RESET_NV is set
        to GL_MOVE_TO_RESETS_NV, GL_RESTART_PATH_NV (as with any command
        that updates /sp/) will reset the dash offset.

   127. <<Bogus issue removed.>>

   128. How does the "stencil" and "cover" steps operate on a multisample
        framebuffer when the GL_MULTISAMPLE enabled is disabled?

        RESOLVED:  The "stencil" step respects the disabled GL_MULTISAMPLE
        enable and rendered aliased stencil coverage.

        When MULTISAMPLE is disabled, "stencil" step coverage
        determinations are made at the pixel center.  (This will result
        in an aliased appearance for the determined path coverage so
        stenciling and covering paths with GL_MULTISAMPLE disabled isn't
        recommended.)

        All the (non-masked) stencil samples for the pixel are considered
        covered or not based on the pixel center's coverage determination.
        For example, if MULTISAMPLE is disabled for a multisample
        buffer and the pixel center is determined covered during
        glStencilFillPathNV or glStencilStrokePathNV (or instanced
        versions), all the samples are updated (INCR/DECR/INVERT for
        filling or REPLACE for stroking).

        "non-masked" means that the glSampleMaskIndexedNV state applies.

        The "cover" step also respects the disabled GL_MULTISAMPLE enable.

        To maintain rendering invariances in order to guarantee
        conservative covering, both the "stencil" and "cover" step should
        be rendered with the same GL_MULTISAMPLE enable state.

   129. What happens when a command or query takes a sequence of path object
        names and a named path object does not exist?

        RESOLVED:  The non-existent path is "skipped" in instanced
        commands such as glStencilFillPathInstancedNV (and the transform
        for the particular path name is skipped over).  Notice the
        pseudo-code for these instanced path commands uses glIsPathNV
        to test if each path name exists.

        Queries cannot simply ignore the invalid name as they return
        information.  glGetPathSpacingNV treats the non-existent name as
        having zero space.  glGetPathMetricRangeNV and GetPathMetricsNV
        return metric values of -1 for the metrics of non-existent
        path objects (as also occurs if the path object lacks metrics
        information).

        No GL error is generated due to a non-existent path name.

        (Early implementation prior to NVIDIA's OpenGL 4.3 implementation
        might crash or generate a GL_INVALID_OPERATION error.
        The behavior was a bug.)

   130. Should glCallLists be extended to take the GL_UTF8_NV and
        GL_UTF16_NV date types?

        RESOLVED: No.  That might make sense in another extension since it
        would allow complex Unicode text to be rendered by glCallLists.

        (An early version of this specification did call for supporting
        UTF sequences for glCallLists, but that behavior was never
        implemented and is now purged from the specification.)

   131. Should glPathTexGenNV and glPathColorGenNV transform the plane
        equations for GL_EYE_LINEAR by the inverse transpose modelview
        matrix?

        RESOLVED:  Yes.

        This matches the way glTexGenfv operates with GL_EYE_LINEAR
        texgen planes.  This allows the eye plane equations to be
        specified in the current object-space.

        (Early specifications, prior to revision 9, incorrectly failed
        to specify this transformation.)

   132. Should new commands and queries be used to support generating
        GLSL fragment inputs?

        RESOLVED:  Add a new command to specify the path fragment
        input generation state but use the API introduced by the
        ARB_program_interface_query extension specification to query
        back the path fragment input generation state.

        The new command is glProgramPathFragmentInputGenNV.  Given a GLSL
        program object and a GL_FRAGMENT_INPUT_NV resource location,
        this command provides the linear function state with which to
        generate the specified interpolated fragment input.

        The new GL_FRAGMENT_INPUT_NV token names the path fragment input
        resource.

        The new program resource properties GL_PATH_GEN_MODE_NV,
        GL_PATH_GEN_COEFF_NV, and GL_PATH_GEN_COMPONENTS_NV name the
        path fragment input generation resources.

   133. How should this specification interact with a Core profile context?

        RESOLVED:  See "Dependencies on Core Profile and OpenGL ES"
        section.

        In summary:

        Enough modelview and projection functionality from
        EXT_direct_state_access is required to make transformations of
        paths possible.

        Fragment varyings of GLSL programs can be interrogated and these
        can be generated.

        Exclude fixed-function fragment varying commands, queries,
        and GLSL built-in variables.

   134. Existing path rendering systems typically specify 2D transforms.
        Such transforms are cheaper to load, concatenate, and render with.
        How are 2D transforms specified?

        RESOLVED:  Add new matrix commands.

        Driver implementations can exploit these more compact matrix
        representations to accelerate path rendering where often matrix
        changes are frequent relative to the amount of rendering.  The
        concatenation of two 3x2 matrices is 24 multiply-add operations;
        while the concatenation of two 4x4 matrices is 64 multiply-add
        operations, so requiring over 2.5x more math operations.

        This table shows the correspondence between other path rendering
        APIs and the corresponding matrix routine so we need only populate
        the range of matrix representations used by major path rendering
        standards.

        Standard         Type              Component order  Corresponding GL load command
        ---------------  ----------------  ---------------  -----------------------------
        Direct2D         D2D_MATRIX_3X2_F  [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]
        Cairo            cairo_matrix_t    [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]
        Skia             SkMatrix          [0,1,2]          glMatrixLoadTranspose3x3fNV
                                           [3,4,5]
                                           [6,7,8]
                         SkScalar [6]      [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]
        Qt               QMatrix           [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]
        OpenVG           VGfloat [9]       [0,3,6]          glMatrixLoad3x3fNV
                                           [1,4,7]
                                           [2,5,8]
        AGM              BRVCoordMatrix    [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]
        Ghostscript      gs_matrix         [0,2,4]          glMatrixLoad3x2fNV
                                           [1,3,5]

        Along with the glMatrixLoad*NV commands, there are corresponding
        glMatrixMult*NV commands.

        Queries should be rare so the existing queries returning all 16
        values of a current matrix are sufficient.

   135. Does the "layout(location=2)", etc. syntax work for fragment inputs?

        RESOLVED:  Yes, assuming separate shader objects support.
        The ARB_separate_shader_objects functionality (made core in
        OpenGL 4.1) supports layout qualifiers to annotate locations on
        arbitrary fragment shader inputs.

        Example: A fragment shader could include the statement:

            layout(location=4) in vec4 eye_space;

        This would ensure that the location queried with
        GetProgramResourceLocation(program, GL_FRAGMENT_INPUT_NV,
        "eye_space") will return 4.

   136. What data types work with glProgramPathFragmentInputGenNV?

        RESOLVED:  Just floating-point scalars and vectors.

        Half-precision and double-precision varyings considered
        floating-point, and hence are allowed, but implementations may
        interpolate double-precision at single-precision.

        Matrix, array, structure, boolean, and integer data types are
        not supported.

        Generated values are intrinsically floating-point (they are
        basically interpolants) hence the floating-point restriction.

        Restricting the generation to floating-point scalars and vectors
        shouldn't be a hardship.

   137. How can a fragment varying (or fragment input for GLSL) be driven
        to a constant value?

        RESOLVED:  Use the GL_CONSTANT genMode for this.

        Example:  This command:

            GLfloat float4_constant[4] = { 1, 2, 3, 4 };
            glPathTexGenNV(GL_TEXTURE0, GL_CONSTANT, 4, float4_constant);

        is equivalent to:

            GLfloat coefficients[3*4] = { 0,0,1, 0,0,2, 0,0,3, 0,0,4 };
            glPathTexGenNV(GL_TEXTURE0, GL_OBJECT_LINEAR, 4, coefficients);

        In the latter form, the zeros in the coefficients array would be
        multiplied by the object-space X and Y so would always evaluate
        (s,t,r,q) to (1,2,3,4) just as the former GL_CONSTANT version
        would.

        GL_CONSTANT also works with glPathColorGenNV and
        glProgramPathFragmentInputGenNV.

   138. What happens to fragment inputs that are not configured by
        glProgramPathFragmentInputGenNV?

        RESOLVED:  Such variables are forced to constant zero.

        The default genMode is GL_NONE and this results in a fragment
        input outputting sc, tc, rc, and qc for its first, second,
        third, and fourth components respectively.  These values
        are all zero in the case of fragment input generation with
        glProgramPathFragmentInputGenNV (whereas with glPathTexGenNV,
        they take on the value of the respective texture coordinate
        set's current values).

   139. The fragment input generation state includes floating-point coefficients
        but the ARB_program_interface_query extension provides no way
        to query floating-point state so how can this state be queried?

        RESOLVED:  This extension adds glProgramResourceIndexfvNV to
        allow floating-point program resource state to be queried.

   140. Can a program object with a vertex shader be used to cover paths?

        RESOLVED:  Yes.

   141. Is there a technical explanation of this extension beyond the
        specification itself?

        RESOLVED:  Yes, check out the SIGGRAPH Asia 2012 paper
        "GPU-accelerated Path Rendering":

           https://dl.acm.org/citation.cfm?id=2366145.2366191
           http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/opengl/gpupathrender.pdf

        There is an accompanying annex to this paper titled "Programming
        NV_path_rendering":

            http://developer.nvidia.com/sites/default/files/akamai/gamedev/files/nvpr_annex.pdf

   142. Should conic sections (rational quadratic Bezier segments) be supported?

        RESOLVED:  Yes, Skia supports these.

        The GL_CONIC_CURVE_TO_NV and GL_RELATIVE_CONIC_CURVE_TO_NV path
        commands take five path coordinates:

           x1,y1, x2,y2, w

        The first two pairs of coordinates are control points similar to
        the GL_QUADRATIC_CURVE_TO_NV and GL_RELATIVE_QUADRATIC_CURVE_TO_NV
        path commands.  The fifth coordinate "w" is a homogeneous coordinate
        that applies to the middle (extrapolating) control point.

        Skia parameterizes its SkPath::kConic_Verb conic curve path
        command in the same manner.  (See Skia's SkConic class in
        skia/include/core/SkGeometry.h for details.)

        When the "w" is 1.0, the behavior of the GL_CONIC_CURVE_TO_NV and
        GL_RELATIVE_CONIC_CURVE_TO_NV commands behave identically to the
        GL_QUADRATIC_CURVE_TO_NV and GL_RELATIVE_QUADRATIC_CURVE_TO_NV
        commands respectively; this case corresponds to a parabolic segment.

        When "w" is less than 1.0, the resulting conic is a partial
        elliptical arc.  When "w" is greater than 1.0, the resulting
        conic is a hyperbolic arc.

        See Table 5.pathEquations (Path Equations) for the specific
        rational quadratic Bezier equations for the GL_CONIC_CURVE_TO_NV
        and GL_RELATIVE_CONIC_CURVE_TO_NV path commands.

        The GL_RELATIVE_CONIC_CURVE_TO_NV path command is not supported
        by Skia but is trivial to support and maintains a symmetry that
        general-purpose path commands should have relative versions.

   143. What happens when the "w" (5th coordinate) of a conic section
        path command is non-positive?

        RESOLVED:  Match Skia's behavior and treat the path command as
        a line segment from the current control point to the interpolating
        control point (x2,y2).

        At the limit when w nears zero, partial elliptical arcs would
        become a line segment.

   144. Should "smooth" conic sections be supported similar to
        GL_SMOOTH_QUADRATIC_CURVE_TO_NV?

        RESOLVED:  No.  Conceptually, there's no problem supporting
        smooth conic sections, however no standard supports smooth conic
        sections to justify the feature.

   145. Should there be a "Character alias" for the absolute and relative
        conic curve commands?

        RESOLVED:  Yes, "W" for GL_CONIC_CURVE_TO_NV and "w" for
        GL_RELATIVE_CONIC_CURVE_TO_NV are appropriate.

   146. Should there be a rational cubic path command?

        RESOLVED:  No way!

        Rational cubic segments are subject to topological transitions
        when transformed projectively (as is possible when a path is
        transformed by the--potentially projective--modelview-projection
        transform!).

   147. Why are rounded rectangles supported?

        RESOLVED:  Rounded rectangles are popular in web content.  The W3C's
        "CSS Backgrounds and Borders Module Level 3" candidate recommendation
        specifies rounded rectangles and they are popular in web content.

            http://www.w3.org/TR/css3-background/

        Native paths commands for rounded rectangles allow such content
        to be specified and rasterized with less overhead than comparable
        specification of the same path with multiple line and arc (or
        conic) commands.

            http://www.w3.org/TR/css3-background/#corners

   148. Should multiple parameterization for rounded rectangles be
        supported?

        RESOLVED:  Yes.

        Both circular and elliptical corners are supported with either
        uniform (all corners have the same x- and y-axis radii) or
        per-corner radii.

        Also relative and absolute versions are supported (including
        adding an absolute version of GL_RECT_NV for completeness).

   149. Should negative x, y, width, height, and radii parameters be allowed
        for rectangles and rounded rectangles?

        RESOLVED:  Yes.  The formulas operate reasonably with negative values.

        Negative values allow the winding order to be reversed.

        GL_RECT_NV already allowed negative values.

   150. Should the "stencil" and "cover" path operations be combined
        into a single command?

        RESOLVED:  Yes, these commands are commonly used in sequence and
        profiling shows combining the commands can provide a small but
        measurable CPU efficiency benefit by reducing name translation,
        object locking overhead, and error checking.
        See the commands:

            glStencilThenCoverFillPathNV
            glStencilThenCoverStrokePathNV

        These commands are specified to behave like a "stencil" command
        on a path followed immediately by a "cover" command on the same
        path.

        There are also instanced versions:

            glStencilThenCoverFillPathInstancedNV
            glStencilThenCoverStrokePathInstancedNV

        These commands can be display listed.

        Indeed, one advantage of the Instanced versions of the
        glStencilThenCover* commands is the instanced array can be copied
        into the display list once.  While a display list optimizer
        could recognize this same benefit, it is simpler to be explicit
        that there is a single set of transform values used by both the
        instanced "stencil" and "cover" operations.

   151. Should there be a way to get glyph indices for a particular font face
        to perform advanced text shaping?

        RESOLVED:  Yes, see glPathGlyphIndexArrayNV,
        glPathMemoryGlyphIndexArrayNV, and glPathGlyphIndexRangeNV.

        Advanced text shaping APIs such as HarfBuzz and Pango generate
        combine text with a font face and provide a sequence of glyph
        indices with corresponding positions to render the text.

        Mozilla and Google have both confirmed the requirement for this.

        Advanced text shaping requires more knowledge of scripts and
        font metrics than can be expressed through NV_path_rendering.
        There is no interest to attempt, or even try to attempt, exposing
        sufficient font metrics for advanced text shaping.  Instead
        the presumption is that one or more higher-level libraries
        (e.g. HarfBuzz + FreeType 2) are used to perform text shaping.

        While glGetPathSpacingNV is useful and sufficient for providing
        basic kerning of Latin and other common scripts, but is
        well-understood to be insufficient for advanced text shaping.

   152. Should glPathGlyphIndexRangeNV take the range of path objects
        as a parameter or return the base & count of path names created
        from the specified font's glyph indices?

        RESOLVED:  glPathGlyphIndexRangeNV operates like glGenPathsNV
        to first get an unassigned range of path object names based on
        the number of glyph indices in the font face.  Then specifies
        the path object for every glyph index.

        This requires returning a pair of GLuint values for the base
        and count.  Additionally there is a return value to indicate
        whether and, if not why not, the path objects for the glyphs
        are assigned and specified.

   153. Why were glPathGlyphIndexArrayNV and glPathMemoryGlyphIndexArrayNV
        added?

        RESOLVED:  Web browsers such as Chrome and other applications
        relying on glyph indices rely on arranging glyph indices of
        several fonts together so controlling the order of glyph index
        arrangement proves important.  glPathGlyphIndexRangeNV returns
        a dynamically allocated range (implicitly using glGenPathsNV)
        and this proved not well-suited for actual use of glyph indices.

   154. Why glPathMemoryGlyphIndexArrayNV added?

        RESOLVED: Also web sites today very often provide server-supplied
        fonts via the Web Open Font Format (WOFF) standard.  This means
        fonts are provided by font representations in system memory
        rather than accessed by file name or system font name.

   155. Why is GL_FONT_NUM_GLYPH_INDICES_NV added?

        RESOLVED:  This is a relevant per-font parameter that is useful
        to ensure that glyphs used by glyph index know the proper bounds
        on the glyph indices.

        This per-font parameter is an integer so is not scaled by the
        emScale.

   156. Why does glPathMemoryGlyphIndexArrayNV take a face index?

        RESOLVED:  Implementations are likely to use FreeType 2's
        FT_New_Memory_Face to implement this functionality.  The first
        face index is zero so normally zero should be passed for the
        face index.

   157. If a face index for glPathMemoryGlyphIndexArrayNV corresponds to
        a bitmap font or otherwise isn't suitable for providing path
        objects, what happens?

        UNRESOLVED:  Probably GL_FONT_UNINTELLIGIBLE_NV should be
        returned.

   158. Is glyph index zero special?

        RESOLVED:  According to SNFT conventions, glyph index zero
        corresponds to the font face's missing glyph.  Therefore at
        least once glyph outline should always exist.

   159. Why as GL_FONT_CORRUPT_NV renamed to GL_FONT_UNINTELLIGIBLE_NV?

        RESOLVED:  Because it is hard to distinguish between a font being
        corrupt and simply not being supported by the implementation.
        Unintelligible is less misleading and more honest about the
        situation.

   160. Are there alternatives to STANDARD_FONT_FORMAT_NV?

        RESOLVED:  Not currently.  There might be a need in the future
        to identify fonts or glyph outlines with some other token if
        the font does use the SNFT format.  PostScript, TrueType, and
        OpenType font formats are all SNFT formats.  The Web Open Font
        Format should be supportable too because it contains a magic
        number with which to identify the format of the binary data.

   161. Is the memory provided by glPathMemoryGlyphIndexArrayNV referenced
        after the command is issued?

        RESOLVED:  No.  The GL implementation is responsible for copying
        from the system memory buffer provided.  This likely requires
        copying the entire buffer.

        (Perhaps another font target to allowed referenced access to the
        font data may be a good idea though it would likely require all
        path objects specified by glPathMemoryGlyphIndexArrayNV to be
        deleted before freeing the memory.  Referencing client system
        memory is generally considered taboo for GL implementations
        beyond the duration of a GL command or query's execution however.
        Copying the buffer avoids any ambiguity and provides for reliable
        operation, tracing, and network extensibility.)

   162. What if glPathGlyphIndexArrayNV or glPathMemoryGlyphIndexArrayNV
        attempt to specify more path objects than the font supports
        glyph indices?

        RESOLVED:  Path objects that would correspond to glyph indices
        that are beyond the maximum glyph index in the font face are
        not disturbed.

        For example, if a font face contains 258 glyph indices, but
        the numGlyphs parameter to glPathGlyphIndexArrayNV is 300, the
        command silently acts as if 258 glyph indices were requested.
        No GL error is generated in this case.  Also the path objects
        named firstPathName+258 and beyond are not disturbed.

        The rationale for this behavior is to avoid needless errors or
        complexity if an application overestimates the number of glyph
        indices a font has.

   163. What concrete reasons might GL_FONT_TARGET_UNAVAILABLE_NV be
        generated?

        RESOLVED:  Here are some situations...

        The Win32 API lacks a way to load a font from a file name.
        If FreeType 2 is unavailable (say its DLL is missing or
        the GL implementation simply does not support it), this
        would cause use of the GL_FILE_NAME_NV target to return
        GL_FONT_TARGET_UNAVAILABLE_NV.

        Linux implementations for the X Window System are likely to use
        FontConfig to map system font names (such as "Arial") to some
        font file.  If the FontConfig shared library is unavailable,
        cannot be initialized, is a very old version, or its configuration
        files are missing or corrupt, the GL_SYSTEM_FONT_NAME_NV font
        target could return GL_FONT_TARGET_UNAVAILABLE_NV.

        These situations are possible and so applications should
        anticipate that GL_FONT_TARGET_UNAVAILABLE_NV might be returned
        but properly configured systems should not be returning this
        value.  Developers debugging this condition should check
        ARB_debug_output messages for an explanation.

   164. What path glyph specification commands support which font targets?

        RESOLVED:

        The FILE_NAME_NV, SYSTEM_FONT_NAME_NV, and STANDARD_FONT_NAME_NV
        font targets are for glPathGlyphsNV and glPathGlyphRangeNV.

        The FILE_NAME_NV and SYSTEM_FONT_NAME_NV font targets are for
        glPathGlyphsNV, glPathGlyphRangeNV, glPathGlyphIndexArrayNV,
        and glPathGlyphIndexRangeNV.  STANARD_FONT_NAME_NV does not
        apply to these commands because standard font name support
        Unicode character point access to glyphs but not glyph indices.

        The STANDARD_FONT_FORMAT_NV font target is just for the
        glPathMemoryGlyphIndexArrayNV command.

   165. Why is the GL_PATH_STROKE_BOUND_NV parameter supported?

        RESOLVED:  The path's stroke approximation bound helps the
        GL implementation and an application bound the amount of
        approximation error allowed when cubic Bezier path segments or
        partial elliptical arcs are stenciled.

        Theory for offset curves indicates determining if a point is
        within a given offset of a cubic Bezier curve (the generating
        curve for the offset curve) amounts to solving a 5th degree
        polynomial equation.  That is not tractable in real-time graphics
        so some approximation of the actual offset curve is assumed.

        By comparison solve the point containment problem for a sample
        position with respect to the offset curve of a quadratic Bezier
        segment requires solving only a 3rd degree polynomial which is
        tractable for modern GPUs.  The assumption here is that stroke
        point containment with respect to quadratic Bezier segments
        and linear segments, as well as capping and join geometry, can
        be tractably solved without analytical approximation (though
        numerical issues may still limit the accuracy at the limits of
        available numerical precision).

        With this in mind, there should be some intuitive bound on
        the approximation error allowed.  The GL_PATH_STROKE_BOUND_NV
        path parameter provides such an intuitive limit expressed as a
        percentage of the path's stroke width.

   166. Should the radii passed to the GL_ROUNDED_RECT*_NV and
        GL_RELATIVE_ROUNDED_RECT*_NV support negative values?

        RESOLVED:  Yes.

        However, the x or y radii are negated if the width or height
        respectively is negative.  This behavior ensures that a rectangle
        with reversed winding can be specified (useful for cutting out
        rounded rectangular "holes" in paths) by simply flipping the
        width or height sign while leaving the radii values positive.

        The use of the /sign/ function in the specification of the /rrect/
        function enforces this behavior.

        This is important because the GL_ROUNDED_RECT_NV and
        GL_ROUNDED_RECT4_NV (and relative versions) specify a single
        circular radius per-rectangle or per-corner respectively without
        providing an x & y radii.  Without the /sign/ terms, it would
        not be possible to use the these commands and specify a reverse
        winding rounded rectangle.

        Still negative values are allowed for the radii and the formula
        should be applied as specified.  Negative radii permit "fins"
        and "crossed roundings" to be added rounded rectangles.

   167. Should CLOSE_PATH_NV count as specifying the start position
        (sp) for the purposes of determining if the PostScript path
        commands CIRCULAR_CCW_ARC_TO_NV or CIRCULAR_CW_ARC_TO_NV should
        change sp to ncp?

        RESOLVED:  No.  The PostScript semantic appears to be that
        a CLOSE_PATH_NV does not set the "current point" to valid.
        This is based on inspection of Ghostscript behavior.

        For this reason, the "other than CLOSE_PATH_NV" phrase is placed
        in the paragraph describing how when these PostScript arc commands
        change sp.

   168. What is the initial glProgramPathFragmentInputGenNV state for all
        fragment inputs?

        RESOLVED:  See the "Program Object Resource State" table.

        The GL_PATH_GEN_MODE_NV initial state for every fragment program
        resource is GL_NONE.

        The GL_PATH_GEN_COMPONENTS_NV initial state is zero for the
        number of path fragment input components.

        The sixteen PATH_GEN_COEFF_NV coefficient values are initially
        all zero.

   169. If glGetProgramResourceiv or glGetProgramResourcefvNV are used on
        fragment program resources that are not floating-point scalars
        are vectors, what happens?

        RESOLVED:  While glProgramPathFragmentInputGenNV cannot be used to
        change such program resources, their state can be queried but
        simply always returns the intial values.

        The rationale for this is that implementations already have
        to return the initial state for fragment inputs that have
        not yet been specified.  Also the ARB_program_interface_query
        specification specifies returning innocuous or invalid
        information in preference to generating errors when the query
        does not apply to the program resource.

        Always writing back some data in the absence of an error also
        makes it easier to notice buffer overflow errors since they are
        not skipped when GL errors are generated.

        Note that an error *should* be generated by
        glGetProgramResourceiv and glGetProgramResourcefvNV if
        GL_PATH_GEN_*_NV queries are performed on a programInterface
        other than GL_FRAGMENT_INPUT_NV.

   170. Should we allow fragment input generation on half and double
        precision GLSL attributes?

        RESOLVED:  No, just single-precision fragment inputs can be
        generated.

        Double-precision attributes only support flat interpolation and
        that makes no sense for paths.

        Half-precision attributes could be supported but have
        no particular advantage on NVIDIA GPUs as half-precision
        interpolation actually happens in single-precision anyway.

        glProgramPathFragmentInputGenNV generates GL_INVALID_OPERATION when
        passed a double-precision or half-precision fragment input
        (just as it does for any other inappropriate program resource
        such as a matrix).

   171. With glProgramPathFragmentInputGenNV, what fragment input values are
        generated when the component would normally be the texture
        coordinate set component for glPathTexGenNV?

        RESOLVED:  Zero.

        glProgramPathFragmentInputGenNV is specified in terms of PathTexGenNV
        but there are no fixed-function way to drive varyings.  But
        this specification language says such under-specified varyings
        will be zero: "Because there is no associated texture coordinate
        set, the sc, tc, rc, and qc values when discussing PathTexGenNV
        are always zero when generating fragment input variables."

   172. Should glProgramPathFragmentInputGenNV be able to control the
        path generation of "gl_" prefixed built-in variables?

        RESOLVED:  No.

        glProgramPathFragmentInputGenNV operates on only fragment inputs
        that are user-defined, scalar/vector (not matrices, structures,
        arrays, or opaque types such as samplers), and single-precsion.

        Built-ins such as gl_TexCoord[0], gl_Color, gl_FogFragCoord
        are generated with glPathTexGenNV, glPathColorGenNV, and
        glPathFogGenNV respectively.

   173. How does this extension interact with OpenGL ES 2 and 3?

        RESOLVED:  Same as the Core Profile in complete OpenGL.  See Issue
        133 and the "Dependencies on Core Profile and OpenGL ES" section.

Revision History

    Rev.    Date    Author     Changes
    ----  -------- ---------  --------------------------------------------
      2   08/26/11 mjk        Initial version
      3   05/31/12 mjk        Fix glPathStencilDepthOffsetNV to accept
                              a GLfloat second parameter; add _BIT to the
                              FONT_*_NV metric token names
      4   07/06/12 mjk        Issue #128
      5   07/27/12 mjk        Fix getPathName return value sense;
                              Issue #129 and #130; UTF-8 and UTF-16
                              decoding fixes.
      6   05/23/13 mjk        Fix typo in Table 5.pathEquations
      7   06/25/13 mjk        Fix token names missing _BIT_NV suffix
      8   08/01/13 mjk        Bad argument order in instanced example
      9   08/22/13 mjk        Fix GL_EYE_LINEAR behavior
      10  09/09/13 mjk        Add core profile + smaller matrix support
      11  09/10/13 mjk        Add conic segment path commands
      12  09/18/13 mjk        Add rounded rectangles, GL_RELATIVE_RECT_NV,
                              missing new matrix language, fix typos
      13  10/21/13 mjk        <fontStyle> parameter for PathGlyphsNV
                              and PathGlyphRangeNV
      14  11/05/13 dsn        Use consistent argument names
      15  11/08/13 mjk        Add StencilThenCover* commands
      16  11/11/13 mjk        Add PathGlyphIndexRange command
      17  01/07/14 mjk        Fix typos
      18  01/07/14 mjk        Add PathGlyphIndexArray and
                              PathMemoryGlyphIndexArray commands and
                              FONT_NUM_GLYPH_INDICES_NV path query;
                              renamed FONT_CORRUPT_NV to FONT_UNINTELLIGIBLE_NV
      19  02/12/14 mjk        Document GL_PATH_STROKE_BOUND_NV
      20  02/14/14 mjk        Fix rounded rectangle radii sign behavior
                              (see issue 166)
      21  02/19/14 mjk        Refashion the rrect function
      22  02/22/14 mjk        PostScript arc behavior; see issue 167
      23  03/06/14 mjk        Document FONT_NUM_GLYPH_INDICES_BIT_NV
                              interactions; STANDARD_FONT_FORMAT_NV only
                              for glPathMemoryGlyphIndexArrayNV
      24  03/18/14 mjk        Update glPathFragmentInputGenNV state
                              and query specification; issues 168-171
      25  03/19/14 mjk        Better NVpr 1.3 explanation
      26  03/20/14 mjk        Issue 172
      27  04/15/14 mjk        ES interactions same as Core Profile
      28  05/02/14 mjk        Updated status
      29  05/15/14 mjk        Matrix*Tranpose to Matrix*Transpose
      30  05/29/14 mjk        Release 1.3 driver details
      31  07/02/14 dkoch      Fix a variety of typos and inconsistencies
                              Update ES interactions
                              Fix pseudocode (float vs double, renderBoundingBox)
      32  07/24/14 mjk        Fix Equation 5.generalParametricArc typos,
                              thanks to Chris Hebert
      33  08/19/14 mjk        Add missing 1.3 additions to revisions section
      34  08/27/14 mjk        Remove bogus polygon offset issue 127; my mistake
      35  09/09/14 mjk        Intro: fix translate mode, add StencilThenCover
