skia / external / github.com / KhronosGroup / OpenGL-Registry / 0dc24166d162723781f1bf9fe433f71fa03a7aa0 / . / extensions / NV / NV_path_rendering.txt

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 | |