blob: d6373522e023a768def81b547da59b5f193ece22 [file] [log] [blame]
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