| Name |
| |
| NV_path_rendering |
| |
| Name Strings |
| |
| GL_NV_path_rendering |
| |
| Contact |
| |
| Mark Kilgard, NVIDIA (mjk 'at' nvidia.com) |
| |
| Contributors |
| |
| Roger Allen, NVIDIA |
| Jeff Bolz, NVIDIA |
| Chris Dalton, NVIDIA |
| Pierre-Loup Griffais, NVIDIA |
| Chris Hebert, Samsung |
| Scott Nations, NVIDIA |
| David Chait, NVIDIA |
| Daniel Koch, NVIDIA |
| Bas Schouten, Mozilla |
| Sandeep Shinde, NVIDIA |
| |
| Status |
| |
| Released in NVIDIA Driver Release 275.33 (June 2011). |
| |
| Substantially optimized in NVIDIA Driver Release 301.42 (May 2012). |
| |
| Further optimized in NVIDIA Driver Release 314.xx (February 2013). |
| |
| Version 1.3 functionality shipping in NVIDIA Driver Release 337.88 |
| and on (May, 27 2014). |
| |
| Version |
| |
| Last Modified Date: September 9, 2014 |
| Version: 35 |
| |
| Number |
| |
| OpenGL Extension #410 |
| OpenGL ES Extension #199 |
| |
| Dependencies |
| |
| This extension is written against the OpenGL 3.2 Specification with |
| Compatibility Profile but can apply to OpenGL 1.1 and up. |
| |
| When used with a Core profile or OpenGL ES context, certain |
| functionality is unavailable (see "Dependencies on Core Profile and |
| OpenGL ES" section). |
| |
| This extension depends on ARB_program_interface_query. |
| |
| EXT_direct_state_access commands are used in specifying portions |
| of this extension but EXT_direct_state_access is not required to |
| implement this extension as long as the functionality implemented |
| is equivalent to the EXT_direct_state_access commands. |
| |
| EXT_separate_shader_objects is recommended. |
| |
| ARB_program_interface_query is recommended. |
| |
| Overview |
| |
| Conventional OpenGL supports rendering images (pixel rectangles and |
| bitmaps) and simple geometric primitives (points, lines, polygons). |
| |
| This extension adds a new rendering paradigm, known as path rendering, |
| for rendering filled and stroked paths. Path rendering is not novel |
| but rather a standard part of most resolution-independent 2D rendering |
| systems such as Flash, PDF, Silverlight, SVG, Java 2D, Office |
| drawings, TrueType fonts, PostScript and its fonts, Quartz 2D, XML |
| Paper Specification (XPS), and OpenVG. What is novel is the ability |
| to mix path rendering with arbitrary OpenGL 3D rendering and imaging. |
| |
| With this extension, path rendering becomes a first-class rendering |
| mode within the OpenGL graphics system that can be arbitrarily mixed |
| with existing OpenGL rendering and can take advantage of OpenGL's |
| existing mechanisms for texturing, programmability, and per-fragment |
| operations. |
| |
| Unlike geometric primitive rendering, paths are specified on a 2D |
| (non-projective) plane rather than in 3D (projective) space. |
| Even though the path is defined in a 2D plane, every path can |
| be transformed into 3D clip space allowing for 3D view frustum & |
| user-defined clipping, depth offset, and depth testing in the same |
| manner as geometric primitive rendering. |
| |
| Both geometric primitive rendering and path rendering support |
| rasterization of edges defined by line segments; however, path |
| rendering also allows path segments to be specified by Bezier (cubic |
| or quadratic) curves or partial elliptical arcs. This allows path |
| rendering to define truly curved primitive boundaries unlike the |
| straight edges of line and polygon primitives. Whereas geometric |
| primitive rendering requires convex polygons for well-defined |
| rendering results, path rendering allows (and encourages!) concave |
| and curved outlines to be specified. These paths are even allowed |
| to self-intersect. |
| |
| When filling closed paths, the winding of paths (counterclockwise |
| or clockwise) determines whether pixels are inside or outside of |
| the path. |
| |
| Paths can also be stroked whereby, conceptually, a fixed-width "brush" |
| is pulled along the path such that the brush remains orthogonal to |
| the gradient of each path segment. Samples within the sweep of this |
| brush are considered inside the stroke of the path. |
| |
| This extension supports path rendering through a sequence of three |
| operations: |
| |
| 1. Path specification is the process of creating and updating |
| a path object consisting of a set of path commands and a |
| corresponding set of 2D vertices. |
| |
| Path commands can be specified explicitly from path command |
| and coordinate data, parsed from a string based on standard |
| grammars for representing paths, or specified by a particular |
| glyph of standard font representations. Also new paths can |
| be specified by weighting one or more existing paths so long |
| as all the weighted paths have consistent command sequences. |
| |
| Each path object contains zero or more subpaths specified |
| by a sequence of line segments, partial elliptical arcs, |
| and (cubic or quadratic) Bezier curve segments. Each path |
| may contain multiple subpaths that can be closed (forming |
| a contour) or open. |
| |
| 2. Path stenciling is the process of updating the stencil buffer |
| based on a path's coverage transformed into window space. |
| |
| Path stenciling can determine either the filled or stroked |
| coverage of a path. |
| |
| The details of path stenciling are explained within the core |
| of the specification. |
| |
| Stenciling a stroked path supports all the standard |
| embellishments for path stroking such as end caps, join |
| styles, miter limits, dashing, and dash caps. These stroking |
| properties specified are parameters of path objects. |
| |
| 3. Path covering is the process of emitting simple (convex & |
| planar) geometry that (conservatively) "covers" the path's |
| sample coverage in the stencil buffer. During path covering, |
| stencil testing can be configured to discard fragments not |
| within the actual coverage of the path as determined by |
| prior path stenciling. |
| |
| Path covering can cover either the filled or stroked coverage |
| of a path. |
| |
| The details of path covering are explained within the core |
| of the specification. |
| |
| To render a path object into the color buffer, an application specifies |
| a path object and then uses a two-step rendering process. First, the |
| path object is stenciled whereby the path object's stroked or filled |
| coverage is rasterized into the stencil buffer. Second, the path object |
| is covered whereby conservative bounding geometry for the path is |
| transformed and rasterized with stencil testing configured to test against |
| the coverage information written to the stencil buffer in the first step |
| so that only fragments covered by the path are written during this second |
| step. Also during this second step written pixels typically have |
| their stencil value reset (so there's no need for clearing the |
| stencil buffer between rendering each path). |
| |
| Here is an example of specifying and then rendering a five-point |
| star and a heart as a path using Scalable Vector Graphics (SVG) |
| path description syntax: |
| |
| GLuint pathObj = 42; |
| const char *svgPathString = |
| // star |
| "M100,180 L40,10 L190,120 L10,120 L160,10 z" |
| // heart |
| "M300 300 C 100 400,100 200,300 100,500 200,500 400,300 300Z"; |
| glPathStringNV(pathObj, GL_PATH_FORMAT_SVG_NV, |
| (GLsizei)strlen(svgPathString), svgPathString); |
| |
| Alternatively applications oriented around the PostScript imaging |
| model can use the PostScript user path syntax instead: |
| |
| const char *psPathString = |
| // star |
| "100 180 moveto" |
| " 40 10 lineto 190 120 lineto 10 120 lineto 160 10 lineto closepath" |
| // heart |
| " 300 300 moveto" |
| " 100 400 100 200 300 100 curveto" |
| " 500 200 500 400 300 300 curveto closepath"; |
| glPathStringNV(pathObj, GL_PATH_FORMAT_PS_NV, |
| (GLsizei)strlen(psPathString), psPathString); |
| |
| The PostScript path syntax also supports compact and precise binary |
| encoding and includes PostScript-style circular arcs. |
| |
| Or the path's command and coordinates can be specified explicitly: |
| |
| static const GLubyte pathCommands[10] = |
| { GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, |
| GL_LINE_TO_NV, GL_CLOSE_PATH_NV, |
| 'M', 'C', 'C', 'Z' }; // character aliases |
| static const GLshort pathCoords[12][2] = |
| { {100, 180}, {40, 10}, {190, 120}, {10, 120}, {160, 10}, |
| {300,300}, {100,400}, {100,200}, {300,100}, |
| {500,200}, {500,400}, {300,300} }; |
| glPathCommandsNV(pathObj, 10, pathCommands, 24, GL_SHORT, pathCoords); |
| |
| Before rendering to a window with a stencil buffer, clear the stencil |
| buffer to zero and the color buffer to black: |
| |
| glClearStencil(0); |
| glClearColor(0,0,0,0); |
| glStencilMask(~0); |
| glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| |
| Use an orthographic path-to-clip-space transform to map the |
| [0..500]x[0..400] range of the star's path coordinates to the [-1..1] |
| clip space cube: |
| |
| glMatrixLoadIdentityEXT(GL_PROJECTION); |
| glMatrixLoadIdentityEXT(GL_MODELVIEW); |
| glMatrixOrthoEXT(GL_MODELVIEW, 0, 500, 0, 400, -1, 1); |
| |
| Stencil the path: |
| |
| glStencilFillPathNV(pathObj, GL_COUNT_UP_NV, 0x1F); |
| |
| The 0x1F mask means the counting uses modulo-32 arithmetic. In |
| principle the star's path is simple enough (having a maximum winding |
| number of 2) that modulo-4 arithmetic would be sufficient so the mask |
| could be 0x3. Or a mask of all 1's (~0) could be used to count with |
| all available stencil bits. |
| |
| Now that the coverage of the star and the heart have been rasterized |
| into the stencil buffer, cover the path with a non-zero fill style |
| (indicated by the GL_NOTEQUAL stencil function with a zero reference |
| value): |
| |
| glEnable(GL_STENCIL_TEST); |
| glStencilFunc(GL_NOTEQUAL, 0, 0x1F); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); |
| glColor3f(1,1,0); // yellow |
| glCoverFillPathNV(pathObj, GL_BOUNDING_BOX_NV); |
| |
| The result is a yellow star (with a filled center) to the left of |
| a yellow heart. |
| |
| The GL_ZERO stencil operation ensures that any covered samples |
| (meaning those with non-zero stencil values) are zero'ed when |
| the path cover is rasterized. This allows subsequent paths to be |
| rendered without clearing the stencil buffer again. |
| |
| A similar two-step rendering process can draw a white outline |
| over the star and heart. |
| |
| Before rendering, configure the path object with desirable path |
| parameters for stroking. Specify a wider 6.5-unit stroke and |
| the round join style: |
| |
| glPathParameteriNV(pathObj, GL_PATH_JOIN_STYLE_NV, GL_ROUND_NV); |
| glPathParameterfNV(pathObj, GL_PATH_STROKE_WIDTH_NV, 6.5); |
| |
| Now stencil the path's stroked coverage into the stencil buffer, |
| setting the stencil to 0x1 for all stencil samples within the |
| transformed path. |
| |
| glStencilStrokePathNV(pathObj, 0x1, ~0); |
| |
| Cover the path's stroked coverage (with a hull this time instead |
| of a bounding box; the choice doesn't really matter here) while |
| stencil testing that writes white to the color buffer and again |
| zero the stencil buffer. |
| |
| glColor3f(1,1,1); // white |
| glCoverStrokePathNV(pathObj, GL_CONVEX_HULL_NV); |
| |
| In this example, constant color shading is used but the application |
| can specify their own arbitrary shading and/or blending operations, |
| whether with Cg compiled to fragment program assembly, GLSL, or |
| fixed-function fragment processing. |
| |
| More complex path rendering is possible such as clipping one path to |
| another arbitrary path. This is because stencil testing (as well |
| as depth testing, depth bound test, clip planes, and scissoring) |
| can restrict path stenciling. |
| |
| Now let's render the word "OpenGL" atop the star and heart. |
| |
| First create a sequence of path objects for the glyphs for the |
| characters in "OpenGL": |
| |
| GLuint glyphBase = glGenPathsNV(6); |
| const unsigned char *word = "OpenGL"; |
| const GLsizei wordLen = (GLsizei)strlen(word); |
| const GLfloat emScale = 2048; // match TrueType convention |
| GLuint templatePathObject = ~0; // Non-existent path object |
| glPathGlyphsNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV, |
| wordLen, GL_UNSIGNED_BYTE, word, |
| GL_SKIP_MISSING_GLYPH_NV, ~0, emScale); |
| glPathGlyphsNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV, |
| wordLen, GL_UNSIGNED_BYTE, word, |
| GL_SKIP_MISSING_GLYPH_NV, ~0, emScale); |
| glPathGlyphsNV(glyphBase, |
| GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV, |
| wordLen, GL_UNSIGNED_BYTE, word, |
| GL_USE_MISSING_GLYPH_NV, ~0, emScale); |
| |
| Glyphs are loaded for three different fonts in priority order: |
| Helvetica first, then Arial, and if neither of those loads, use the |
| standard sans-serif font. If a prior glPathGlyphsNV is successful |
| and specifies the path object range, the subsequent glPathGlyphsNV |
| commands silently avoid re-specifying the already existent path |
| objects. |
| |
| Now query the (kerned) separations for the word "OpenGL" and build |
| a set of horizontal translations advancing each successive glyph by |
| its kerning distance with the following glyph. |
| |
| GLfloat xtranslate[6+1]; // wordLen+1 |
| glGetPathSpacingNV(GL_ACCUM_ADJACENT_PAIRS_NV, |
| wordLen+1, GL_UNSIGNED_BYTE, |
| "\000\001\002\003\004\005\005", // repeat last letter twice |
| glyphBase, |
| 1.0f, 1.0f, |
| GL_TRANSLATE_X_NV, |
| xtranslate); |
| |
| Next determine the font-wide vertical minimum and maximum for the |
| font face by querying the per-font metrics of any one of the glyphs |
| from the font face. |
| |
| GLfloat yMinMax[2]; |
| glGetPathMetricRangeNV(GL_FONT_Y_MIN_BOUNDS_BIT_NV|GL_FONT_Y_MAX_BOUNDS_BIT_NV, |
| glyphBase, /*count*/1, |
| 2*sizeof(GLfloat), |
| yMinMax); |
| |
| Use an orthographic path-to-clip-space transform to map the |
| word's bounds to the [-1..1] clip space cube: |
| |
| glMatrixLoadIdentityEXT(GL_PROJECTION); |
| glMatrixOrthoEXT(GL_MODELVIEW, |
| 0, xtranslate[6], yMinMax[0], yMinMax[1], |
| -1, 1); |
| |
| Stencil the filled paths of the sequence of glyphs for "OpenGL", |
| each transformed by the appropriate 2D translations for spacing. |
| |
| glStencilFillPathInstancedNV(6, GL_UNSIGNED_BYTE, |
| "\000\001\002\003\004\005", |
| glyphBase, |
| GL_PATH_FILL_MODE_NV, 0xFF, |
| GL_TRANSLATE_X_NV, xtranslate); |
| |
| Cover the bounding box union of the glyphs with 50% gray. |
| |
| glEnable(GL_STENCIL_TEST); |
| glStencilFunc(GL_NOTEQUAL, 0, 0xFF); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); |
| glColor3f(0.5,0.5,0.5); // 50% gray |
| glCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE, |
| "\000\001\002\003\004\005", |
| glyphBase, |
| GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV, |
| GL_TRANSLATE_X_NV, xtranslate); |
| |
| Voila, the word "OpenGL" in gray is now stenciled into the framebuffer. |
| |
| Instead of solid 50% gray, the cover operation can apply a linear |
| gradient that changes from green (RGB=0,1,0) at the top of the word |
| "OpenGL" to blue (RGB=0,0,1) at the bottom of "OpenGL": |
| |
| GLfloat rgbGen[3][3] = { |
| 0, 0, 0, // red = constant zero |
| 0, 1, 0, // green = varies with y from bottom (0) to top (1) |
| 0, -1, 1 // blue = varies with y from bottom (1) to top (0) |
| }; |
| glPathColorGenNV(GL_PRIMARY_COLOR, GL_PATH_OBJECT_BOUNDING_BOX_NV, |
| GL_RGB, &rgbGen[0][0]); |
| |
| Instead of loading just the glyphs for the characters in "OpenGL", |
| the entire character set could be loaded. This allows the characters |
| of the string to be mapped (offset by the glyphBase) to path object names. |
| A range of glyphs can be loaded like this: |
| |
| const int numChars = 256; // ISO/IEC 8859-1 8-bit character range |
| GLuint glyphBase = glGenPathsNV(numChars); |
| glPathGlyphRangeNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV, |
| 0, numChars, |
| GL_SKIP_MISSING_GLYPH_NV, ~0, emScale); |
| glPathGlyphRangeNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV, |
| 0, numChars, |
| GL_SKIP_MISSING_GLYPH_NV, ~0, emScale); |
| glPathGlyphRangeNV(glyphBase, |
| GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV, |
| 0, numChars, |
| GL_USE_MISSING_GLYPH_NV, ~0, emScale); |
| |
| Given a range of glyphs loaded as path objects, (kerned) spacing |
| information can now be queried for the string: |
| |
| glGetPathSpacingNV(GL_ACCUM_ADJACENT_PAIRS_NV, |
| 7, GL_UNSIGNED_BYTE, "OpenGLL", // repeat L to get final spacing |
| glyphBase, |
| 1.0f, 1.0f, |
| GL_TRANSLATE_X_NV, |
| kerning); |
| |
| Using the range of glyphs, stenciling and covering the instanced |
| paths for "OpenGL" can be done this way: |
| |
| glStencilFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL", |
| glyphBase, |
| GL_PATH_FILL_MODE_NV, 0xFF, |
| GL_TRANSLATE_X_NV, xtranslate); |
| |
| glCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL", |
| glyphBase, |
| GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV, |
| GL_TRANSLATE_X_NV, xtranslate); |
| |
| The "stencil" and "cover" steps can be combined in a single command: |
| |
| glStencilThenCoverFillPathInstancedNV(6, GL_UNSIGNED_BYTE, "OpenGL", |
| glyphBase, |
| GL_PATH_FILL_MODE_NV, 0xFF, |
| GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV |
| GL_TRANSLATE_X_NV, xtranslate); |
| |
| XXX add path clipping example to demonstrate glPathStencilFuncNV. |
| |
| New Procedures and Functions |
| |
| PATH SPECIFICATION COMMANDS |
| |
| EXPLICIT PATH DATA |
| |
| void PathCommandsNV(uint path, |
| sizei numCommands, const ubyte *commands, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| void PathCoordsNV(uint path, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| void PathSubCommandsNV(uint path, |
| sizei commandStart, sizei commandsToDelete, |
| sizei numCommands, const ubyte *commands, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| void PathSubCoordsNV(uint path, |
| sizei coordStart, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| STRING PATH DESCRIPTION |
| |
| void PathStringNV(uint path, enum format, |
| sizei length, const void *pathString); |
| |
| PATHS FROM FONT GLYPHS BY UNICODE CHARACTER POINT |
| |
| void PathGlyphsNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| sizei numGlyphs, enum type, |
| const void *charcodes, |
| enum handleMissingGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| void PathGlyphRangeNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint firstGlyph, |
| sizei numGlyphs, |
| enum handleMissingGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| |
| PATHS FROM FONT GLYPHS BY PER-FONT GLYPH INDEX |
| |
| enum PathGlyphIndexArrayNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint firstGlyphIndex, |
| sizei numGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| enum PathMemoryGlyphIndexArrayNV(uint firstPathName, |
| enum fontTarget, |
| sizeiptr fontSize, |
| const void *fontData, |
| sizei faceIndex, |
| uint firstGlyphIndex, |
| sizei numGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| enum PathGlyphIndexRangeNV(enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint pathParameterTemplate, |
| float emScale, |
| uint baseAndCount[2]); |
| |
| PATH SPECIFICATION WITH EXISTING PATHS |
| |
| void WeightPathsNV(uint resultPath, |
| sizei numPaths, |
| const uint paths[], const float weights[]); |
| void CopyPathNV(uint resultPath, uint srcPath); |
| void InterpolatePathsNV(uint resultPath, |
| uint pathA, uint pathB, |
| float weight); |
| void TransformPathNV(uint resultPath, |
| uint srcPath, |
| enum transformType, |
| const float *transformValues); |
| |
| PATH PARAMETER SPECIFICATION COMMANDS |
| |
| void PathParameterivNV(uint path, enum pname, const int *value); |
| void PathParameteriNV(uint path, enum pname, int value); |
| void PathParameterfvNV(uint path, enum pname, const float *value); |
| void PathParameterfNV(uint path, enum pname, float value); |
| |
| void PathDashArrayNV(uint path, |
| sizei dashCount, const float *dashArray); |
| |
| PATH NAME MANAGEMENT |
| |
| uint GenPathsNV(sizei range); |
| void DeletePathsNV(uint path, sizei range); |
| boolean IsPathNV(uint path); |
| |
| PATH STENCILING |
| |
| void PathStencilFuncNV(enum func, int ref, uint mask); |
| void PathStencilDepthOffsetNV(float factor, float units); |
| |
| void StencilFillPathNV(uint path, |
| enum fillMode, uint mask); |
| |
| void StencilStrokePathNV(uint path, |
| int reference, uint mask); |
| |
| void StencilFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum transformType, |
| const float *transformValues); |
| |
| void StencilStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| int reference, uint mask, |
| enum transformType, |
| const float *transformValues); |
| |
| PATH COVERING |
| |
| void PathCoverDepthFuncNV(enum zfunc); |
| |
| void PathColorGenNV(enum color, |
| enum genMode, |
| enum colorFormat, const float *coeffs); |
| void PathTexGenNV(enum texCoordSet, |
| enum genMode, |
| int components, const float *coeffs); |
| void PathFogGenNV(enum genMode); |
| |
| void CoverFillPathNV(uint path, enum coverMode); |
| |
| void CoverStrokePathNV(uint path, enum coverMode); |
| |
| void CoverFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| void CoverStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| PATH STENCILING THEN COVERING |
| |
| void StencilThenCoverFillPathNV(uint path, enum fillMode, |
| uint mask, enum coverMode); |
| void StencilThenCoverStrokePathNV(uint path, int reference, |
| uint mask, enum coverMode); |
| void StencilThenCoverFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, |
| const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| void StencilThenCoverStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, |
| const void *paths, |
| uint pathBase, |
| int reference, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| PATH COVERING OF GLSL FRAGMENT INPUTS |
| |
| void ProgramPathFragmentInputGenNV(uint program, |
| int location, |
| enum genMode, |
| int components, |
| const float *coeffs); |
| |
| PATH QUERIES |
| |
| void GetPathParameterivNV(uint path, enum pname, int *value); |
| void GetPathParameterfvNV(uint path, enum pname, float *value); |
| |
| void GetPathCommandsNV(uint path, ubyte *commands); |
| void GetPathCoordsNV(uint path, float *coords); |
| void GetPathDashArrayNV(uint path, float *dashArray); |
| |
| void GetPathMetricsNV(bitfield metricQueryMask, |
| sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| sizei stride, |
| float *metrics); |
| void GetPathMetricRangeNV(bitfield metricQueryMask, |
| uint firstPathName, |
| sizei numPaths, |
| sizei stride, |
| float *metrics); |
| |
| void GetPathSpacingNV(enum pathListMode, |
| sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| float advanceScale, |
| float kerningScale, |
| enum transformType, |
| float *returnedSpacing); |
| |
| void GetPathColorGenivNV(enum color, enum pname, int *value); |
| void GetPathColorGenfvNV(enum color, enum pname, float *value); |
| void GetPathTexGenivNV(enum texCoordSet, enum pname, int *value); |
| void GetPathTexGenfvNV(enum texCoordSet, enum pname, float *value); |
| |
| boolean IsPointInFillPathNV(uint path, |
| uint mask, float x, float y); |
| boolean IsPointInStrokePathNV(uint path, |
| float x, float y); |
| |
| float GetPathLengthNV(uint path, |
| sizei startSegment, sizei numSegments); |
| |
| boolean PointAlongPathNV(uint path, |
| sizei startSegment, sizei numSegments, |
| float distance, |
| float *x, float *y, |
| float *tangentX, float *tangentY); |
| |
| MATRIX SPECIFICATION |
| |
| void MatrixLoad3x2fNV(enum matrixMode, const float *m); |
| void MatrixLoad3x3fNV(enum matrixMode, const float *m); |
| void MatrixLoadTranspose3x3fNV(enum matrixMode, const float *m); |
| |
| void MatrixMult3x2fNV(enum matrixMode, const float *m); |
| void MatrixMult3x3fNV(enum matrixMode, const float *m); |
| void MatrixMultTranspose3x3fNV(enum matrixMode, const float *m); |
| |
| FLOATING-POINT PROGRAM RESOURCE QUERY |
| |
| void GetProgramResourcefvNV(uint program, enum programInterface, |
| uint index, sizei propCount, |
| const enum *props, sizei bufSize, |
| sizei *length, float *params); |
| |
| New Tokens |
| |
| Accepted in elements of the <commands> array parameter of |
| PathCommandsNV and PathSubCommandsNV: |
| |
| CLOSE_PATH_NV 0x00 |
| MOVE_TO_NV 0x02 |
| RELATIVE_MOVE_TO_NV 0x03 |
| LINE_TO_NV 0x04 |
| RELATIVE_LINE_TO_NV 0x05 |
| HORIZONTAL_LINE_TO_NV 0x06 |
| RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 |
| VERTICAL_LINE_TO_NV 0x08 |
| RELATIVE_VERTICAL_LINE_TO_NV 0x09 |
| QUADRATIC_CURVE_TO_NV 0x0A |
| RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B |
| CUBIC_CURVE_TO_NV 0x0C |
| RELATIVE_CUBIC_CURVE_TO_NV 0x0D |
| SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E |
| RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F |
| SMOOTH_CUBIC_CURVE_TO_NV 0x10 |
| RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 |
| SMALL_CCW_ARC_TO_NV 0x12 |
| RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 |
| SMALL_CW_ARC_TO_NV 0x14 |
| RELATIVE_SMALL_CW_ARC_TO_NV 0x15 |
| LARGE_CCW_ARC_TO_NV 0x16 |
| RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 |
| LARGE_CW_ARC_TO_NV 0x18 |
| RELATIVE_LARGE_CW_ARC_TO_NV 0x19 |
| CONIC_CURVE_TO_NV 0x1A |
| RELATIVE_CONIC_CURVE_TO_NV 0x1B |
| ROUNDED_RECT_NV 0xE8 |
| RELATIVE_ROUNDED_RECT_NV 0xE9 |
| ROUNDED_RECT2_NV 0xEA |
| RELATIVE_ROUNDED_RECT2_NV 0xEB |
| ROUNDED_RECT4_NV 0xEC |
| RELATIVE_ROUNDED_RECT4_NV 0xED |
| ROUNDED_RECT8_NV 0xEE |
| RELATIVE_ROUNDED_RECT8_NV 0xEF |
| RESTART_PATH_NV 0xF0 |
| DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 |
| DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 |
| RECT_NV 0xF6 |
| RELATIVE_RECT_NV 0xF7 |
| CIRCULAR_CCW_ARC_TO_NV 0xF8 |
| CIRCULAR_CW_ARC_TO_NV 0xFA |
| CIRCULAR_TANGENT_ARC_TO_NV 0xFC |
| ARC_TO_NV 0xFE |
| RELATIVE_ARC_TO_NV 0xFF |
| |
| Accepted by the <format> parameter of PathStringNV: |
| |
| PATH_FORMAT_SVG_NV 0x9070 |
| PATH_FORMAT_PS_NV 0x9071 |
| |
| Accepted by the <fontTarget> parameter of PathGlyphsNV, |
| PathGlyphRangeNV, and PathGlyphIndexRangeNV: |
| |
| STANDARD_FONT_NAME_NV 0x9072 |
| SYSTEM_FONT_NAME_NV 0x9073 |
| FILE_NAME_NV 0x9074 |
| |
| Accepted by the <fontTarget> parameter of PathMemoryGlyphIndexArrayNV: |
| |
| STANDARD_FONT_FORMAT_NV 0x936C |
| |
| Accepted by the <handleMissingGlyph> parameter of PathGlyphsNV and |
| PathGlyphRangeNV: |
| |
| SKIP_MISSING_GLYPH_NV 0x90A9 |
| USE_MISSING_GLYPH_NV 0x90AA |
| |
| Returned by PathGlyphIndexRangeNV: |
| |
| FONT_GLYPHS_AVAILABLE_NV 0x9368 |
| FONT_TARGET_UNAVAILABLE_NV 0x9369 |
| FONT_UNAVAILABLE_NV 0x936A |
| FONT_UNINTELLIGIBLE_NV 0x936B // once was FONT_CORRUPT_NV |
| INVALID_ENUM |
| INVALID_VALUE |
| OUT_OF_MEMORY |
| |
| Accepted by the <pname> parameter of PathParameterfNV, |
| PathParameterfvNV, GetPathParameterfvNV, PathParameteriNV, |
| PathParameterivNV, and GetPathParameterivNV: |
| |
| PATH_STROKE_WIDTH_NV 0x9075 |
| PATH_INITIAL_END_CAP_NV 0x9077 |
| PATH_TERMINAL_END_CAP_NV 0x9078 |
| PATH_JOIN_STYLE_NV 0x9079 |
| PATH_MITER_LIMIT_NV 0x907A |
| PATH_INITIAL_DASH_CAP_NV 0x907C |
| PATH_TERMINAL_DASH_CAP_NV 0x907D |
| PATH_DASH_OFFSET_NV 0x907E |
| PATH_CLIENT_LENGTH_NV 0x907F |
| PATH_DASH_OFFSET_RESET_NV 0x90B4 |
| |
| PATH_FILL_MODE_NV 0x9080 |
| PATH_FILL_MASK_NV 0x9081 |
| PATH_FILL_COVER_MODE_NV 0x9082 |
| PATH_STROKE_COVER_MODE_NV 0x9083 |
| PATH_STROKE_MASK_NV 0x9084 |
| PATH_STROKE_BOUND_NV 0x9086 |
| |
| Accepted by the <pname> parameter of PathParameterfNV and |
| PathParameterfvNV: |
| |
| PATH_END_CAPS_NV 0x9076 |
| PATH_DASH_CAPS_NV 0x907B |
| |
| Accepted by the <fillMode> parameter of StencilFillPathNV and |
| StencilFillPathInstancedNV: |
| |
| INVERT |
| COUNT_UP_NV 0x9088 |
| COUNT_DOWN_NV 0x9089 |
| PATH_FILL_MODE_NV see above |
| |
| Accepted by the <color> parameter of PathColorGenNV, |
| GetPathColorGenivNV, and GetPathColorGenfvNV: |
| |
| PRIMARY_COLOR 0x8577 // from OpenGL 1.3 |
| PRIMARY_COLOR_NV 0x852C // from NV_register_combiners |
| SECONDARY_COLOR_NV 0x852D // from NV_register_combiners |
| |
| Accepted by the <genMode> parameter of PathColorGenNV, PathTexGenNV, |
| ProgramPathFragmentInputGenNV: |
| |
| NONE |
| EYE_LINEAR |
| OBJECT_LINEAR |
| PATH_OBJECT_BOUNDING_BOX_NV 0x908A |
| CONSTANT |
| |
| Accepted by the <coverMode> parameter of CoverFillPathNV and |
| CoverFillPathInstancedNV: |
| |
| CONVEX_HULL_NV 0x908B |
| BOUNDING_BOX_NV 0x908D |
| PATH_FILL_COVER_MODE_NV see above |
| |
| Accepted by the <coverMode> parameter of CoverStrokePathNV and |
| CoverStrokePathInstancedNV: |
| |
| CONVEX_HULL_NV see above |
| BOUNDING_BOX_NV see above |
| PATH_STROKE_COVER_MODE_NV see above |
| |
| Accepted by the <transformType> parameter of |
| StencilFillPathInstancedNV, StencilStrokePathInstancedNV, |
| CoverFillPathInstancedNV, and CoverStrokePathInstancedNV: |
| |
| NONE |
| TRANSLATE_X_NV 0x908E |
| TRANSLATE_Y_NV 0x908F |
| TRANSLATE_2D_NV 0x9090 |
| TRANSLATE_3D_NV 0x9091 |
| AFFINE_2D_NV 0x9092 |
| AFFINE_3D_NV 0x9094 |
| TRANSPOSE_AFFINE_2D_NV 0x9096 |
| TRANSPOSE_AFFINE_3D_NV 0x9098 |
| |
| Accepted by the <transformType> parameter of TransformPathNV: |
| |
| NONE |
| TRANSLATE_X_NV see above |
| TRANSLATE_Y_NV see above |
| TRANSLATE_2D_NV see above |
| TRANSLATE_3D_NV see above |
| AFFINE_2D_NV see above |
| AFFINE_3D_NV see above |
| TRANSPOSE_AFFINE_2D_NV see above |
| TRANSPOSE_AFFINE_3D_NV see above |
| |
| Accepted by the <type> or <pathNameType> parameter of |
| StencilFillPathInstancedNV, StencilStrokePathInstancedNV, |
| CoverFillPathInstancedNV, CoverStrokePathInstancedNV, |
| GetPathMetricsNV, and GetPathSpacingNV: |
| |
| UTF8_NV 0x909A |
| UTF16_NV 0x909B |
| |
| Accepted by the <coverMode> parameter of CoverFillPathInstancedNV: |
| |
| CONVEX_HULL_NV see above |
| BOUNDING_BOX_NV see above |
| BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C |
| PATH_FILL_COVER_MODE_NV see above |
| |
| Accepted by the <coverMode> parameter of CoverStrokePathInstancedNV: |
| |
| CONVEX_HULL_NV see above |
| BOUNDING_BOX_NV see above |
| BOUNDING_BOX_OF_BOUNDING_BOXES_NV see above |
| PATH_STROKE_COVER_MODE_NV see above |
| |
| Accepted by the <pname> parameter of GetPathParameterfvNV and |
| GetPathParameterivNV: |
| |
| PATH_COMMAND_COUNT_NV 0x909D |
| PATH_COORD_COUNT_NV 0x909E |
| PATH_DASH_ARRAY_COUNT_NV 0x909F |
| |
| PATH_COMPUTED_LENGTH_NV 0x90A0 |
| |
| PATH_OBJECT_BOUNDING_BOX_NV see above |
| PATH_FILL_BOUNDING_BOX_NV 0x90A1 |
| PATH_STROKE_BOUNDING_BOX_NV 0x90A2 |
| |
| Accepted by the <value> parameter of PathParameterfNV, |
| PathParameterfvNV, PathParameteriNV, and PathParameterivNV |
| when <pname> is one of PATH_END_CAPS_NV, PATH_INTIAL_END_CAP_NV, |
| PATH_TERMINAL_END_CAP_NV, PATH_DASH_CAPS_NV, PATH_INITIAL_DASH_CAP_NV, |
| and PATH_TERMINAL_DASH_CAP_NV: |
| |
| FLAT |
| SQUARE_NV 0x90A3 |
| ROUND_NV 0x90A4 |
| TRIANGULAR_NV 0x90A5 |
| |
| Accepted by the <value> parameter of PathParameterfNV, |
| PathParameterfvNV, PathParameteriNV, and PathParameterivNV |
| when <pname> is PATH_JOIN_STYLE_NV: |
| |
| NONE |
| ROUND_NV see above |
| BEVEL_NV 0x90A6 |
| MITER_REVERT_NV 0x90A7 |
| MITER_TRUNCATE_NV 0x90A8 |
| |
| Accepted by the <value> parameter of PathParameterfNV, |
| PathParameterfvNV, PathParameteriNV, and PathParameterivNV when |
| <pname> is PATH_DASH_OFFSET_RESET_NV: |
| |
| MOVE_TO_RESETS_NV 0x90B5 |
| MOVE_TO_CONTINUES_NV 0x90B6 |
| |
| Accepted by the <fontStyle> parameter of PathGlyphsNV, |
| PathGlyphRangeNV, and PathGlyphIndexRangeNV: |
| |
| NONE |
| BOLD_BIT_NV 0x01 |
| ITALIC_BIT_NV 0x02 |
| |
| Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, |
| GetInteger64v, GetFloatv, and GetDoublev: |
| |
| PATH_ERROR_POSITION_NV 0x90AB |
| |
| PATH_FOG_GEN_MODE_NV 0x90AC |
| |
| PATH_STENCIL_FUNC_NV 0x90B7 |
| PATH_STENCIL_REF_NV 0x90B8 |
| PATH_STENCIL_VALUE_MASK_NV 0x90B9 |
| |
| PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD |
| PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE |
| |
| PATH_COVER_DEPTH_FUNC_NV 0x90BF |
| |
| Accepted as a bit within the <metricQueryMask> parameter of |
| GetPathMetricRangeNV or GetPathMetricsNV: |
| |
| // per-glyph metrics |
| GLYPH_WIDTH_BIT_NV 0x01 |
| GLYPH_HEIGHT_BIT_NV 0x02 |
| GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 |
| GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 |
| GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 |
| GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 |
| GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 |
| GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 |
| GLYPH_HAS_KERNING_BIT_NV 0x100 |
| |
| // per-font face metrics |
| FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 |
| FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 |
| FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 |
| FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 |
| FONT_UNITS_PER_EM_BIT_NV 0x00100000 |
| FONT_ASCENDER_BIT_NV 0x00200000 |
| FONT_DESCENDER_BIT_NV 0x00400000 |
| FONT_HEIGHT_BIT_NV 0x00800000 |
| FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 |
| FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 |
| FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 |
| FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 |
| FONT_HAS_KERNING_BIT_NV 0x10000000 |
| FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000 |
| |
| Accepted by the <pathListMode> parameter of GetPathSpacingNV: |
| |
| ACCUM_ADJACENT_PAIRS_NV 0x90AD |
| ADJACENT_PAIRS_NV 0x90AE |
| FIRST_TO_REST_NV 0x90AF |
| |
| Accepted by the <pname> parameter of GetPathColorGenivNV, |
| GetPathColorGenfvNV, GetPathTexGenivNV and GetPathTexGenfvNV: |
| |
| PATH_GEN_MODE_NV 0x90B0 |
| PATH_GEN_COEFF_NV 0x90B1 |
| |
| Accepted by the <pname> parameter of GetPathColorGenivNV and |
| GetPathColorGenfvNV: |
| |
| PATH_GEN_COLOR_FORMAT_NV 0x90B2 |
| |
| Accepted by the <pname> parameter of GetPathTexGenivNV and |
| GetPathTexGenfvNV: |
| |
| PATH_GEN_COMPONENTS_NV 0x90B3 |
| |
| Accepted by the <programInterface> parameter of GetProgramInterfaceiv, |
| GetProgramResourceIndex, GetProgramResourceName, GetProgramResourceiv, |
| GetProgramResourcefvNV, and GetProgramResourceLocation: |
| |
| FRAGMENT_INPUT_NV 0x936D |
| |
| Accepted in the <props> array of GetProgramResourceiv: |
| |
| PATH_GEN_MODE_NV see above |
| PATH_GEN_COMPONENTS_NV see above |
| |
| Accepted in the <props> array of GetProgramResourcefvNV: |
| |
| PATH_GEN_COEFF_NV see above |
| |
| Additions to Chapter 2 of the OpenGL 3.2 (unabridged) Specification |
| (OpenGL Operation) |
| |
| Add to the end of Section 2.12.1 (Matrices) with |
| EXT_direct_state_access language applied... |
| |
| "The command |
| |
| void MatrixLoad3x2fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x2matrix[16] = { |
| m[0], m[2], 0, m[4], |
| m[1], m[3], 0, m[5], |
| 0, 0, 1, 0, |
| 0, 0, 0, 1 |
| }; |
| MatrixLoadTransposefEXT(matrixMode, equiv_3x2matrix); |
| |
| The command |
| |
| void MatrixLoad3x3fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x3matrix[16] = { |
| m[0], m[3], 0, m[6], |
| m[1], m[4], 0, m[7], |
| 0, 0, 1, 0, |
| m[2], m[5], 0, m[8], |
| }; |
| MatrixLoadTransposefEXT(matrixMode, equiv_3x3matrix); |
| |
| The command |
| |
| void MatrixLoadTranspose3x3fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x3matrix[16] = { |
| m[0], m[1], 0, m[2], |
| m[3], m[4], 0, m[5], |
| 0, 0, 1, 0, |
| m[6], m[7], 0, m[8], |
| }; |
| MatrixLoadTransposefEXT(matrixMode, equiv_3x3matrix); |
| |
| The command |
| |
| void MatrixMult3x2fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x2matrix[16] = { |
| m[0], m[2], 0, m[4], |
| m[1], m[3], 0, m[5], |
| 0, 0, 1, 0, |
| 0, 0, 0, 1 |
| }; |
| MatrixMultTransposefEXT(matrixMode, equiv_3x2matrix); |
| |
| The command |
| |
| void MatrixMult3x3fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x3matrix[16] = { |
| m[0], m[3], 0, m[6], |
| m[1], m[4], 0, m[7], |
| 0, 0, 1, 0, |
| m[2], m[5], 0, m[8], |
| }; |
| MatrixMultTransposefEXT(matrixMode, equiv_3x3matrix); |
| |
| The command |
| |
| void MatrixMultTranspose3x3fNV(enum matrixMode, const float *m); |
| |
| is equivalent to: |
| |
| const float equiv_3x3matrix[16] = { |
| m[0], m[1], 0, m[2], |
| m[3], m[4], 0, m[5], |
| 0, 0, 1, 0, |
| m[6], m[7], 0, m[8], |
| }; |
| MatrixMultTransposefEXT(matrixMode, equiv_3x3matrix);" |
| |
| Modify the ARB_program_interface_query language as follows... |
| |
| Add to the "query properties of the interfaces of a program object" |
| paragraph, so the "supported values of <programInterface>" includes: |
| |
| * FRAGMENT_INPUT_NV corresponds to the set of active input variables |
| used by the fragment shader stage of <program> (if a fragment |
| stage exists). (This may be different from PROGRAM_INPUT except |
| when the first shader stage is the fragment stage when they will |
| be identical.) |
| |
| Change this sentence about when locations are assigned to include |
| FRAGMENT_INPUT_NV so it reads: |
| |
| "When a program is linked successfully, active variables in the |
| UNIFORM, PROGRAM_INPUT, FRAGMENT_INPUT_NV, PROGRAM_OUTPUT interface, |
| or in any of the subroutine uniform interfaces, are assigned one or |
| more signed integer /locations/." |
| |
| Amend Table X.1 "GetProgramResourceiv properties and supported |
| interfaces" to add FRAGMENT_INPUT_NV to all the properties that |
| allow PROGRAM_INPUT. Specifically: |
| |
| * NAME_LENGTH |
| * TYPE |
| * ARRAY_SIZE |
| * REFERENCED_BY_*_SHADER |
| * LOCATION |
| * IS_PER_PATCH (will always be false for FRAGMENT_INPUT_NV) |
| |
| Further amend Table X.1 "GetProgramResourceiv properties with two |
| more properties for fragment input path generation state: |
| |
| Property Supported Interfaces |
| --------------------------- ---------------------------------------- |
| PATH_GEN_MODE_NV FRAGMENT_INPUT_NV |
| PATH_GEN_COMPONENTS_NV FRAGMENT_INPUT_NV |
| |
| Amend the discussion of GetProgramResourceiv properties, adding: |
| |
| "For the property PATH_GEN_MODE_NV, a single integer identifying |
| the path generation mode of an active variable is written to |
| <params>. The integer returned is one of NONE, OBJECT_LINEAR, |
| PATH_OBJECT_BOUNDING_BOX_NV, or EYE_LINEAR based on how |
| ProgramPathFragmentInputGenNV last specified the program resource's |
| path generation mode. The initial state is NONE. |
| |
| For the property PATH_GEN_COMPONENTS_NV, a single integer identifying |
| the number of generated path components an active variable is written |
| to <params>. The integer returned is between 0 and 4 based on how |
| ProgramPathFragmentInputGenNV last specified the program resource's |
| path generation number of components. The initial state is 0." |
| |
| Amend the list of tokens supported for the <programInterface> parameter of |
| GetProgramResourceLocation to include FRAGMENT_INPUT_NV so the relevant |
| sentence reads: |
| |
| "For GetProgramResourceLocation, <programInterface> must be one |
| of UNIFORM, PROGRAM_INPUT, FRAGMENT_INPUT_NV, PROGRAM_OUTPUT, |
| VERTEX_SUBROUTINE_UNIFORM, TESS_CONTROL_SUBROUTINE_UNIFORM, |
| TESS_EVALUATION_SUBROUTINE_UNIFORM, GEOMETRY_SUBROUTINE_UNIFORM, |
| FRAGMENT_SUBROUTINE_UNIFORM, or COMPUTE_SUBROUTINE_UNIFORM." |
| |
| After the discussion of GetProgramResourceiv, add: |
| |
| "The command |
| |
| void GetProgramResourcefvNV(uint program, enum programInterface, |
| uint index, sizei propCount, |
| const enum *props, sizei bufSize, |
| sizei *length, float *params); |
| |
| operates in the same manner as GetProgramResourceiv expect the |
| returned parameters values are floating-point and the only valid |
| value of <programInterface> is FRAGMENT_INPUT_NV and the only valid value |
| for the elements of the <props> array is PATH_GEN_COEFF_NV; otherwise |
| INVALID_ENUM is generated. |
| |
| For the property PATH_GEN_COEFF_NV, sixteen floating-point values |
| are written to <params> (limited to writing <bufSize> floating-point |
| values)." |
| |
| Additions to Chapter 3 of the OpenGL 3.2 (unabridged) Specification |
| (Rasterization) |
| |
| Append to the end of the "Shader Inputs" subsection of Section 3.12.2 |
| "Shader Execution": |
| |
| The command |
| |
| void ProgramPathFragmentInputGenNV(uint program, |
| int location, |
| enum genMode, |
| int components, |
| const float *coeffs); |
| |
| controls how a user-defined (non-built-in) fragment input of a |
| GLSL program object is computed for fragment shading operations that |
| occur as a result of CoverFillPathNV or CoverStrokePathNV. |
| |
| /program/ names a GLSL program object. If /program/ has not been |
| successfully linked, the error INVALID_OPERATION is generated. |
| |
| The given fragment input generation state is loaded into the fragment |
| input variable location identified by /location/. This location |
| is a value returned either by GetProgramResourceLocation with a |
| /programInterface/ of FRAGMENT_INPUT_NV and a given fragment shader |
| input variable name or by GetProgramResourceiv with FRAGMENT_INPUT_NV |
| for the /programInterface/ and LOCATION for the property for a given |
| fragment input resource index. |
| |
| If the value of location is -1, the ProgramPathFragmentInputGenNV command |
| will silently ignore the command, and the program's path fragment input |
| generation state will not be changed. |
| |
| If any of the following conditions occur, an INVALID_OPERATION error |
| is generated by the ProgramPathFragmentInputGenNV, and no state is changed: |
| |
| * if the size indicated in the /components/ of the |
| ProgramPathFragmentInputGenNV command used does not match the |
| size of the fragment input scalar or vector declared in the |
| shader, |
| |
| * if the fragment input declared in the shader is not |
| single-precision floating-point, or |
| |
| * if no fragment input variable with a location of /location/ |
| exists in the program object named by /program/ and location |
| is not -1, or |
| |
| * if the fragment input declared in the shader is a built-in |
| variables (i.e. prefixed by "gl_"). |
| |
| When covering paths, fragment input variables are interpolated at |
| each shaded fragment based on the corresponding fragment input |
| generation state specified by ProgramPathFragmentInputGenNV for |
| each respective fragment input. |
| |
| The /genMode/, /components/, and /coeffs/ parameters are used to |
| generate the fragment input variable values identically as the |
| PathTexGenNV command's corresponding parameters except it is a |
| fragment input that is generated rather than a texture coordinate set |
| (see the "TEXTURE COORDINATE SET GENERATION FOR PATH COVER COMMANDS" |
| discussion in section 5.X.2.2 "Path Covering"). Because there is |
| no associated texture coordinate set, the sc, tc, rc, and qc values |
| when discussing PathTexGenNV are always zero when generating fragment |
| input variables. |
| |
| When covering paths, if a fragment input variable has not had its |
| path fragment input generation state successfully generated, it as |
| if the values of this variable are always initialized to zero when |
| the fragment shader is executing. |
| |
| Also when covering paths, GLSL fragment shaders support the following |
| built-in fragment input variables: |
| |
| in vec4 gl_TexCoord[gl_MaxTextureCoords]; |
| in vec4 gl_Color |
| in vec4 gl_FrontColor; |
| in vec4 gl_BackColor; |
| in vec4 gl_SecondaryColor; |
| in vec4 gl_FrontSecondaryColor; |
| in vec4 gl_BackSecondaryColor; |
| in float gl_FogFragCoord; |
| |
| These respectively are initialized to the fragment input generated |
| coordinates of PathTexGenNV, PathColorGenNV for GL_PRIMARY_COLOR_NV |
| (front or back), PathColorGenNV for GL_SECONDARY_COLOR_NV (front or |
| back), and glPathFogGenNV." |
| |
| Additions to Chapter 4 of the OpenGL 3.2 (unabridged) Specification |
| (Per-Fragment Operations and the Frame Buffer) |
| |
| None |
| |
| Additions to Chapter 5 of the OpenGL 3.2 (unabridged) Specification |
| (Special Functions) |
| |
| -- Insert section 5.X "Path Rendering" after 5.3 "Feedback" |
| |
| 5.X Path Rendering |
| |
| 5.X.1 Path Specification |
| |
| PATH COMMANDS |
| |
| Paths are specified as a sequence of path commands; each path command |
| has an associated sequence of floating-point coordinates with the |
| number of such coordinates depending on the specific path command. |
| Coordinates are specified in a sequence independent from the path |
| command sequence; coordinates from the coordinate sequence are matched |
| up with (associated with) commands, in the order of the command, |
| with coordinates extracted from the front of the coordinate sequence. |
| |
| Valid path commands are listed in table 5.pathCommands. Each path |
| command is listed with its associated token, description, character |
| alias, count of associated coordinates. |
| |
| As an example of how path commands associated with path coordinates, |
| if the command sequence was MOVE_TO_NV, LINE_TO_NV, CUBIC_CURVE_TO_NV, |
| CLOSE_PATH_NV and the coordinates were 1, 2, 3, 4, 5, 6, 7, 8, 9, |
| 10, the MOVE_TO_NV command would be matched to coordinates 1 and 2, |
| LINE_TO_NV would be matched to 3 and 4, CUBIC_CURVE_TO_NV would be |
| matched to 5, 6, 7, 8, 9, 10, and CLOSE_PATH_NV would be matched to |
| no coordinates. |
| |
| Path commands are processed in their sequence order to generate the |
| path's outline. The outline generation process maintains three 2D |
| (x,y) state variables for each path processed: the start position |
| (sp), the current position (cp), and the prior end point (pep); |
| /sp/, /cp/ and /pep/ are initially (0,0) when a path starts being |
| processed. |
| |
| Table 5.pathCommands: Path Commands |
| |
| Character Coordinate |
| Token Description alias count |
| ========================== ===================== ========== ========== |
| MOVE_TO_NV Absolute move 'M' 2 |
| current point |
| RELATIVE_MOVE_TO_NV Relative move 'm' 2 |
| current point |
| -------------------------- --------------------- ---------- ---------- |
| CLOSE_PATH_NV Close path 'Z' or 'z' 0 |
| RESTART_PATH_NV Reset the path - 0 |
| -------------------------- --------------------- ---------- ---------- |
| LINE_TO_NV Absolute line 'L' 2 |
| RELATIVE_LINE_TO_NV Relative line 'l' 2 |
| -------------------------- --------------------- ---------- ---------- |
| HORIZONTAL_LINE_TO_NV Absolute horizontal 'H' 1 |
| line |
| RELATIVE_HORIZONTAL- Relative horizontal 'h' 1 |
| _LINE_TO_NV line |
| VERTICAL_LINE_TO_NV Absolute vertical 'V' 1 |
| line |
| RELATIVE_VERTICAL- Relative vertical 'v' 1 |
| _LINE_TO_NV line |
| -------------------------- --------------------- ---------- ---------- |
| QUADRATIC_CURVE_TO_NV Absolute quadratic 'Q' 4 |
| Bezier segment |
| RELATIVE- Relative quadratic 'q' 4 |
| _QUADRATIC_CURVE_TO_NV Bezier segment |
| -------------------------- --------------------- ---------- ---------- |
| CUBIC_CURVE_TO_NV Absolute cubic 'C' 6 |
| Bezier segment |
| RELATIVE_CUBIC_CURVE_TO_NV Relative cubic 'c' 6 |
| Bezier segment |
| -------------------------- --------------------- ---------- ---------- |
| SMOOTH- Absolute smooth 'T' 2 |
| _QUADRATIC_CURVE_TO_NV quadratic Bezier |
| segment |
| RELATIVE_SMOOTH- Relative smooth 't' 2 |
| _QUADRATIC_CURVE_TO_NV quadratic Bezier |
| segment |
| -------------------------- --------------------- ---------- ---------- |
| SMOOTH- Absolute smooth 'S' 4 |
| _CUBIC_CURVE_TO_NV cubic Bezier segment |
| RELATIVE_SMOOTH- Relative smooth 's' 4 |
| _CUBIC_CURVE_TO_NV cubic Bezier segment |
| -------------------------- --------------------- ---------- ---------- |
| SMALL_CCW_ARC_TO_NV Absolute small-sweep - 5 |
| counterclockwise |
| partial elliptical |
| arc segment |
| RELATIVE- Relative small-sweep - 5 |
| _SMALL_CCW_ARC_TO_NV counterclockwise |
| partial elliptical |
| arc segment |
| SMALL_CW_ARC_TO_NV Absolute small-sweep - 5 |
| clockwise partial |
| elliptical arc |
| segment |
| RELATIVE- Relative small-sweep - 5 |
| _SMALL_CW_ARC_TO_NV clockwise partial |
| elliptical arc |
| segment |
| LARGE_CCW_ARC_TO_NV Absolute large-sweep - 5 |
| counterclockwise |
| partial elliptical |
| arc segment |
| RELATIVE- Relative large-sweep - 5 |
| _LARGE_CCW_ARC_TO_NV counterclockwise |
| partial elliptical |
| arc segment |
| LARGE_CW_ARC_TO_NV Absolute large-sweep - 5 |
| clockwise partial |
| elliptical arc |
| segment |
| RELATIVE- Relative large-sweep - 5 |
| _LARGE_CW_ARC_TO_NV clockwise partial |
| elliptical arc |
| segment |
| -------------------------- --------------------- ---------- ---------- |
| CONIC_CURVE_TO_NV Absolute conic 'W' 5 |
| (rational Bezier) |
| segment |
| RELATIVE- Relative conic 'w' 5 |
| _CONIC_CURVE_TO_NV (rational Bezier) |
| segment |
| -------------------------- --------------------- ---------- ---------- |
| ROUNDED_RECT_NV Absolute rounded - 5 |
| rectangle with |
| uniform circular |
| corners (1 radius) |
| RELATIVE_ROUNDED_RECT_NV Relative rounded - 5 |
| rectangle with |
| uniform circular |
| corners (1 radius) |
| ROUNDED_RECT2_NV Absolute rounded - 6 |
| rectangle with |
| uniform elliptical |
| corners (2 x&y radii) |
| RELATIVE_ROUNDED_RECT2_NV Relative rounded - 6 |
| rectangle with |
| uniform elliptical |
| corners (2 x&y radii) |
| ROUNDED_RECT4_NV Absolute rounded - 8 |
| rectangle with |
| varying circular |
| corners (4 radii) |
| RELATIVE_ROUNDED_RECT4_NV Relative rounded - 8 |
| rectangle with |
| varying circular |
| corners (4 radii) |
| ROUNDED_RECT8_NV Absolute rounded - 12 |
| rectangle with |
| varying elliptical |
| corners (8 radii) |
| RELATIVE_ROUNDED_RECT8_NV Relative rounded - 12 |
| rectangle with |
| varying elliptical |
| corners (8 radii) |
| -------------------------- --------------------- ---------- ---------- |
| DUP_FIRST_- Absolute cubic Bezier - 4 |
| CUBIC_CURVE_TO_NV segment, duplicating |
| first control point |
| DUP_LAST_CUBIC_CURVE_TO_NV Absolute cubic Bezier - 4 |
| segment, duplicating |
| last control point |
| RECT_NV Closed absolute - 4 |
| rectangle |
| RELATIVE_RECT_NV Closed relative - 4 |
| rectangle |
| -------------------------- --------------------- ---------- ---------- |
| CIRCULAR_CCW_ARC_TO_NV Absolute - 5 |
| counterclockwise |
| circular arc segment |
| CIRCULAR_CW_ARC_TO_NV Absolute clockwise - 5 |
| circular arc segment |
| CIRCULAR_TANGENT_ARC_TO_NV Absolute circular - 5 |
| tangential |
| arc segment |
| -------------------------- --------------------- ---------- ---------- |
| ARC_TO_NV Absolute general 'A' 7 |
| elliptical arc |
| RELATIVE_ARC_TO_NV Relative general 'a' 7 |
| elliptical arc |
| -------------------------- --------------------- ---------- ---------- |
| |
| Table 5.pathEquations provides for each path command, as relevant, |
| the command's path segment parametric equation, equations for the |
| updated current point (ncp) and equations for the updated prior |
| end point (npep). After each command in a path is processed in the |
| sequence, the new current point, prior end point, and start point |
| (if changed) update the current point, prior end point, and start |
| point for the next path command to be processed in the sequence. So: |
| |
| cp = ncp |
| pep = npep |
| |
| Each path segment parametric equation is parameterized by a variable |
| /t/ ranging from 0.0 to 1.0. So the outline is traced by evaluating |
| each path command's path segment parametric equation continuously |
| as /t/ varies from 0.0 to 1.0. |
| |
| With the exception of the MOVE_TO_NV, RELATIVE_MOVE_TO_NV, |
| RESTART_PATH_NV, RECT_NV, RELATIVE_RECT_NV, ROUNDED_RECT_NV, |
| RELATIVE_ROUNDED_RECT_NV, ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV, |
| ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV, |
| RELATIVE_ROUNDED_RECT8_NV, CIRCULAR_CCW_ARC_TO_NV, and |
| CIRCULAR_CW_ARC_TO_NV commands, the commands are specified such that |
| C0 continuity of the outline is guaranteed at path command segment |
| end-points. |
| |
| The MOVE_TO_NV, RELATIVE_MOVE_TO_NV, RESTART_PATH_NV, RECT_NV, |
| RELATIVE_RECT_NV, ROUNDED_RECT_NV, RELATIVE_ROUNDED_RECT_NV, |
| ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV, |
| ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV, |
| RELATIVE_ROUNDED_RECT8_NV, CIRCULAR_CCW_ARC_TO_NV, and |
| CIRCULAR_CW_ARC_TO_NV commands update the start position (sp) to |
| the value of these command's new current point (ncp). |
| |
| The MOVE_TO_NV, RELATIVE_MOVE_TO_NV, RECT_NV, |
| RELATIVE_RECT_NV, ROUNDED_RECT_NV, RELATIVE_ROUNDED_RECT_NV, |
| ROUNDED_RECT2_NV, RELATIVE_ROUNDED_RECT2_NV, |
| ROUNDED_RECT4_NV, RELATIVE_ROUNDED_RECT4_NV, ROUNDED_RECT8_NV, |
| RELATIVE_ROUNDED_RECT8_NV, commands unconditionally change the start |
| position (sp) to value of these command's new current point (ncp) so: |
| |
| sp = ncp |
| |
| The CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV commands |
| conditionally change sp to the command's ncp but only the sp has not |
| been specified by any prior command other than CLOSE_PATH_NV in the |
| path's command sequence since the beginning of the path's command |
| sequence or last RESTART_PATH_NV. When these circular arc commands |
| change the sp to the command's ncp, it implies the initial implicit |
| line these commands generate from sp to ncp will be zero length. |
| (This behavior is to match the semantics of PostScript.) |
| |
| Moving of the start position creates a discontinuity in the outline |
| so starts a new subpath within the path. |
| |
| Table 5.pathEquations: Path Equations |
| |
| Path segment new current new prior end |
| Token parametric equation point equation point equation |
| ========================== ====================================== ================== ======================= |
| MOVE_TO_NV - ncp.x = c[0] npep.x = c[0] |
| ncp.y = c[1] npep.y = c[1] |
| RELATIVE_MOVE_TO_NV - ncp.x = cp.x+c[0] npep.x = cp.x+c[0] |
| ncp.y = cp.y+c[1] npep.y = cp.y+c[1] |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| CLOSE_PATH_NV x = (1-t)*cp.x + t*sp.x ncp.x = sp.x npep.x = sp.x |
| y = (1-t)*cp.y + t*sp.y ncp.y = sp.y npep.y = sp.y |
| RESTART_PATH_NV - ncp.x = 0 npep.x = 0 |
| ncp.y = 0 npep.y = 0 |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| LINE_TO_NV x = (1-t)*cp.x + t*c[0] ncp.x = c[0] npep.x = c[0] |
| y = (1-t)*cp.y + t*c[1] ncp.y = c[1] npep.y = c[1] |
| RELATIVE_LINE_TO_NV x = (1-t)*cp.x + t*(c[0]+cp.x) ncp.x = cp.x+c[0] npep.x = cp.x+c[0] |
| y = (1-t)*cp.y + t*(c[1]+cp.y) ncp.y = cp.y+c[1] npep.y = cp.y+c[1] |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| HORIZONTAL_LINE_TO_NV x = (1-t)*cp.x + t*sp.x ncp.x = c[0] npep.x = c[0] |
| y = cp.y ncp.y = cp.y npep.y = cp.y |
| RELATIVE_HORIZONTAL- x = (1-t)*cp.x + t*(c[0]+cp.x) ncp.x = cp.x+c[0] npep.x = cp.x+c[0] |
| _LINE_TO_NV y = cp.y ncp.y = cp.y npep.y = cp.y |
| VERTICAL_LINE_TO_NV x = cp.x ncp.x = cp.x npep.x = cp.x |
| y = (1-t)*cp.y + t*sp.y ncp.y = c[0] npep.y = c[0] |
| RELATIVE_VERTICAL- x = cp.x ncp.x = cp.x npep.x = cp.x |
| _LINE_TO_NV y = (1-t)*cp.y + t*(c[0]+cp.y) ncp.y = cp.y+c[0] npep.y = cp.y+c[0] |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| QUADRATIC_CURVE_TO_NV x = (1-t)^2*cp.x + ncp.x = c[2] npep.x = c[0] |
| 2*(1-t)*t*c[0] + ncp.y = c[3] npep.y = c[1] |
| t^2*c[2] |
| y = (1-t)^2*cp.y + |
| 2*(1-t)*t*c[1] + |
| t^2*c[3] |
| RELATIVE- x = (1-t)^2*cp.x + ncp.x = cp.x+c[2] npep.x = cp.x+c[0] |
| _QUADRATIC_CURVE_TO_NV 2*(1-t)*t*(c[0]+cp.x) + ncp.y = cp.x+c[3] npep.y = cp.y+c[1] |
| t^2*(c[2]+cp.x) |
| y = (1-t)^2*cp.y + |
| 2*(1-t)*t*(c[1]+cp.y) + |
| t^2*(c[3]+cp.y) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| CUBIC_CURVE_TO_NV x = (1-t)^3*cp.x + ncp.x = c[4] npep.x = c[2] |
| 3*(1-t)^2*t*c[0] + ncp.y = c[5] npep.y = c[3] |
| 3*(1-t)*t^2*c[2] + |
| t^3*c[4] |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*c[1] + |
| 3*(1-t)*t^2*c[3] + |
| t^3*c[5] |
| RELATIVE_CUBIC_CURVE_TO_NV x = (1-t)^3*cp.x + ncp.x = cp.x+c[4] npep.x = cp.x+c[2] |
| 3*(1-t)^2*t*(c[0]+cp.x) + ncp.y = cp.y+c[5] npep.y = cp.y+c[3] |
| 3*(1-t)*t^2*(c[2]+cp.x) + |
| t^3*(c[4]+cp.x) |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*(c[1]+cp.y) + |
| 3*(1-t)*t^2*(c[3]+cp.y) + |
| t^3*(c[5]+cp.y) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| SMOOTH- x = (1-t)^2*cp.x + ncp.x = c[0] npep.x = 2*cp.x-pep.x |
| _QUADRATIC_CURVE_TO_NV 2*(1-t)*t*(2*cp.x-pep.x) + ncp.y = c[1] npep.y = 2*cp.y-pep.y |
| t^2*c[0] |
| y = (1-t)^2*cp.y + |
| 2*(1-t)*t*(2*cp.y-pep.y) + |
| t^2*c[1] |
| RELATIVE_SMOOTH- x = (1-t)^2*cp.x + ncp.x = cp.x+c[0] npep.x = 2*cp.x-pep.x |
| QUADRATIC_CURVE_TO_NV 2*(1-t)*t*(2*cp.x-pep.x) + ncp.y = cp.y+c[1] npep.y = 2*cp.y-pep.y |
| t^2*(c[0]+cp.x) |
| y = (1-t)^2*cp.y + |
| 2*(1-t)*t*(2*cp.y-pep.y) + |
| t^2*(c[1]+cp.y) |
| |
| SMOOTH- x = (1-t)^3*cp.x + ncp.x = c[2] npep.x = c[0] |
| _CUBIC_CURVE_TO_NV 3*(1-t)^2*t*(2*cp.x-pep.x) + ncp.y = c[3] npep.y = c[1] |
| 3*(1-t)*t^2*c[0] + |
| t^3*c[2] |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*(2*cp.y-pep.y) + |
| 3*(1-t)*t^2*c[1] + |
| t^3*c[3] |
| RELATIVE_SMOOTH- x = (1-t)^3*cp.x + ncp.x = cp.x+c[2] npep.x = cp.x+c[0] |
| _CUBIC_CURVE_TO_NV 3*(1-t)^2*t*(2*cp.x-pep.x) + ncp.y = cp.y+c[3] npep.y = cp.y+c[1] |
| 3*(1-t)*t^2*(c[0]+cp.x) + |
| t^3*(c[2]+cp.x) |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*(2*cp.y-pep.y) + |
| 3*(1-t)*t^2*(c[1]+cp.y) + |
| t^3*(c[3]+cp.y) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| SMALL_CCW_ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = c[3] |
| theta1,dtheta,t) ncp.y = c[4] npep.y = c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| RELATIVE- x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = cp.x+c[3] |
| _SMALL_CCW_ARC_TO_NV theta1,dtheta,t) ncp.y = c[4] npep.y = cp.y+c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| SMALL_CW_ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = c[3] |
| theta1,dtheta,t) ncp.y = c[4] npep.y = c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| RELATIVE- x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = cp.x+c[3] |
| _SMALL_CW_ARC_TO_NV theta1,dtheta,t) ncp.y = c[4] npep.y = cp.y+c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| LARGE_CCW_ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = c[3] |
| theta1,dtheta,t) ncp.y = c[4] npep.y = c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| RELATIVE- x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = cp.x+c[3] |
| _LARGE_CCW_ARC_TO_NV theta1,dtheta,t) ncp.y = c[4] npep.y = cp.y+c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| LARGE_CW_ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = c[3] |
| theta1,dtheta,t) ncp.y = c[4] npep.y = c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| RELATIVE- x = arc_x(c,rv,rh,phi, ncp.x = c[3] npep.x = cp.x+c[3] |
| _SMALL_CW_ARC_TO_NV theta1,dtheta,t) ncp.y = c[4] npep.y = cp.y+c[4] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| CONIC_CURVE_TO_NV WHEN c[4] > 0: ncp.x = c[2] npep.x = c[0] |
| x = ( (1-t)^2*cp.x + ncp.y = c[3] npep.y = c[1] |
| 2*(1-t)*t*c[0]*c[4] + |
| t^2*c[2] ) / |
| ( (1-t)^2 + |
| 2*(1-t)*t*c[4] + |
| t^2*c[2] ) |
| y = ( 1-t)^2*cp.y + |
| 2*(1-t)*t*c[1]*w + |
| t^2*c[3] ) / |
| ( (1-t)^2 + |
| 2*(1-t)*t*c[4] + |
| t^2*c[2] ), |
| OTHERWISE: |
| x = (1-t)*cp.x + t*c[2] |
| y = (1-t)*cp.y + t*c[3] |
| RELATIVE- WHEN c[4] > 0: ncp.x = cp.x+c[2] npep.x = cp.x+c[0] |
| _CONIC_CURVE_TO_NV x = ( (1-t)^2*cp.x + ncp.y = cp.y+c[3] npep.y = cp.y+c[1] |
| 2*(1-t)*t*(c[0]+cp.x)*c[4] + |
| t^2*(c[2]+cp.x) ) / |
| ( (1-t)^2 + |
| 2*(1-t)*t*c[4] + |
| t^2*c[2] ) |
| y = ( 1-t)^2*cp.y + |
| 2*(1-t)*t*c[1]*w + |
| t^2*c[3] ) / |
| ( (1-t)^2 + |
| 2*(1-t)*t*c[4] + |
| t^2*c[2] ), |
| OTHERWISE: |
| x = (1-t)*cp.x + t*(c[2]+cp.x) |
| y = (1-t)*cp.y + t*(c[3]+cp.y) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| ROUNDED_RECT_NV x = rrect(c[0], c[1], c[2], c[3], ncp.x = C_ll.x npep.x = C_ll.x |
| c[4], c[4], c[4], c[4], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[4], c[4], c[4], t).x |
| y = rrect(c[0], c[1], c[2], c[3], |
| c[4], c[4], c[4], c[4], |
| c[4], c[4], c[4], c[4], t).y |
| RELATIVE_ROUNDED_RECT_NV x = rrect(c[0]+cp.x, c[1]+cp.y, ncp.x = C_ll.x npep.x = C_ll.x |
| c[2], c[3], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[4], c[4], c[4], |
| c[4], c[4], c[4], c[4], t).x |
| y = rrect(c[0]+cp.x, c[1]+cp.y, |
| c[2], c[3], |
| c[4], c[4], c[4], c[4], |
| c[4], c[4], c[4], c[4], t).y |
| ROUNDED_RECT2_NV x = rrect(c[0], c[1], c[2], c[3], ncp.x = C_ll.x npep.x = C_ll.x |
| c[4], c[5], c[4], c[5], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[5], c[4], c[5], t).x |
| y = rrect(c[0], c[1], c[2], c[3], |
| c[4], c[5], c[4], c[5], |
| c[4], c[5], c[4], c[5], t).y |
| RELATIVE_ROUNDED_RECT2_NV x = rrect(c[0]+cp.x, c[1]+cp.y, ncp.x = C_ll.x npep.x = C_ll.x |
| c[2], c[3], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[5], c[4], c[5], |
| c[4], c[5], c[4], c[5], t).x |
| y = rrect(c[0]+cp.x, c[1]+cp.y, |
| c[2], c[3], |
| c[4], c[5], c[4], c[5], |
| c[4], c[5], c[4], c[5], t).y |
| ROUNDED_RECT4_NV x = rrect(c[0], c[1], c[2], c[3], ncp.x = C_ll.x npep.x = C_ll.x |
| c[4], c[4], c[5], c[5], ncp.y = C_ll.y npep.y = C_ll.y |
| c[6], c[6], c[7], c[7], t).x |
| y = rrect(c[0], c[1], c[2], c[3], |
| c[4], c[4], c[5], c[5], |
| c[6], c[6], c[7], c[7], t).y |
| RELATIVE_ROUNDED_RECT4_NV x = rrect(c[0]+cp.x, c[1]+cp.y, ncp.x = C_ll.x npep.x = C_ll.x |
| c[2], c[3], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[4], c[5], c[5], |
| c[6], c[6], c[7], c[7], t).x |
| y = rrect(c[0]+cp.x, c[1]+cp.y, |
| c[2], c[3], |
| c[4], c[4], c[5], c[5], |
| c[6], c[6], c[7], c[7], t).y |
| ROUNDED_RECT8_NV x = rrect(c[0], c[1], c[2], c[3], ncp.x = C_ll.x npep.x = C_ll.x |
| c[4], c[5], c[6], c[7], ncp.y = C_ll.y npep.y = C_ll.y |
| c[8], c[9], |
| c[10], c[11], t).x |
| y = rrect(c[0], c[1], c[2], c[3], |
| c[4], c[5], c[6], c[7], |
| c[8], c[9], |
| c[10], c[11], t).y |
| RELATIVE_ROUNDED_RECT8_NV x = rrect(c[0]+cp.x, c[1]+cp.y, ncp.x = C_ll.x npep.x = C_ll.x |
| c[2], c[3], ncp.y = C_ll.y npep.y = C_ll.y |
| c[4], c[5], c[6], c[7], |
| c[8], c[9], |
| c[10], c[11], t).x |
| y = rrect(c[0]+cp.x, c[1]+cp.y, |
| c[2], c[3], |
| c[4], c[5], c[6], c[7], |
| c[8], c[9], |
| c[10], c[11], t).y |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| DUP_FIRST- x = (1-t)^3*cp.x + ncp.x = c[2] npep.x = c[0] |
| CUBIC_CURVE_TO_NV 3*(1-t)^2*t*cp.x + ncp.y = c[3] npep.y = c[1] |
| 3*(1-t)*t^2*c[0] + |
| t^3*c[2] |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*cp.y + |
| 3*(1-t)*t^2*c[1] + |
| t^3*c[3] |
| DUP_LAST_CUBIC_CURVE_TO_NV x = (1-t)^3*cp.x + ncp.x = c[2] npep.x = c[2] |
| 3*(1-t)^2*t*c[0] + ncp.y = c[3] npep.y = c[3] |
| 3*(1-t)*t^2*c[2] + |
| t^3*c[2] |
| y = (1-t)^3*cp.y + |
| 3*(1-t)^2*t*c[1] + |
| 3*(1-t)*t^2*c[3] + |
| t^3*c[3] |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| RECT_NV / (1-4*t)*c[0] + ncp.x = c[0] npep.x = c[0] |
| | 4*t*(c[0]+c[2]), t<=0.25 ncp.y = c[1] npep.y = c[1] |
| x = < c[0]+c[2], 0.25<t<=0.5 |
| | (1-4*t-2)*(c[0]+c[2]) + |
| | (4*t-2)*c[0], 0.5 <t<=0.75 |
| \ c[0], 0.75<t |
| / c[1], t<=0.25 |
| | (1-4*t-1)*c[1] + |
| y = < (4*t-1)*(c[1]+c[3]), 0.25<t<=0.5 |
| | c[1]+c[3], 0.5 <t<=0.75 |
| | (1-4*t-3)*(c[1]+c[3]) + |
| \ (4*t-3)*c[1], 0.75<t |
| RELATIVE_RECT_NV / (1-4*t)*(c[0]+cp.x) + ncp.x = cp.x+c[0] npep.x = cp.x+c[0] |
| | 4*t*(c[0]+c[2]+cp.x), t<=0.25 ncp.y = cp.y+c[1] npep.y = cp.y+c[1] |
| x = < c[0]+c[2]+cp.x, 0.25<t<=0.5 |
| | (1-4*t-2)*(c[0]+c[2]+cp.x) + |
| | (4*t-2)*(c[0]+cp.x), 0.5<t<=0.75 |
| \ c[0]+cp.x, 0.75<t |
| / c[1]+cp.y, t<=0.25 |
| | (1-4*t-1)*(c[1]+cp.y) + |
| y = < (4*t-1)*(c[1]+c[3]+cp.y), |
| | 0.25<t<=0.5 |
| | c[1]+c[3]+cp.y, 0.5<t<=0.75 |
| | (1-4*t-3)*(c[1]+c[3]+cp.y) + |
| \ (4*t-3)*(c[1]+cp.y), 0.75<t |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| CIRCULAR_CCW_ARC_TO_NV / (1-2*t)*cp.x + 2*t*A.x, t<=0.5 ncp.x = B.x npep.x = B.x |
| x = { ncp.y = B.y npep.x = B.y |
| \ arc_x(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1) t>=0.5 |
| / (1-2*t)*cp.y + 2*t*A.y, t<=0.5 |
| y = { |
| \ arc_y(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1), t>=0.5 |
| CIRCULAR_CW_ARC_TO_NV / (1-2*t)*cp.x + 2*t*A.x, t<=0.5 ncp.x = B.x npep.x = B.x |
| x = { ncp.y = B.y npep.x = B.y |
| \ arc_x(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1) t>=0.5 |
| / (1-2*t)*cp.y + 2*t*A.y, t<=0.5 |
| y = { |
| \ arc_y(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1), t>=0.5 |
| CIRCULAR_TANGENT_ARC_TO_NV / (1-2*t)*cp.x + 2*t*C.x, t<=0.5 ncp.x = D.x npep.x = D.x |
| x = { ncp.y = D.y npep.x = D.y |
| \ arc_x(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1), t>=0.5 |
| / (1-2*t)*cp.y + 2*t*C.y, t<=0.5 |
| y = { |
| \ arc_y(c,rv,rh,phi,theta1, |
| \ dtheta,t*2-1), t>=0.5 |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = c[5] npep.x = c[5] |
| theta1,dtheta,t) ncp.y = c[6] npep.y = c[6] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| RELATIVE_ARC_TO_NV x = arc_x(c,rv,rh,phi, ncp.x = cp.x+c[5] npep.x = cp.x+c[5] |
| theta1,dtheta,t) ncp.y = cp.y+c[6] npep.y = cp.y+c[6] |
| y = arc_y(c,rv,rh,phi, |
| theta1,dtheta,t) |
| -------------------------- -------------------------------------- ------------------ ----------------------- |
| |
| In the equations in Table 5.pathEquations, c[i] is the /i/th (base |
| zero) coordinate of the coordinate sequence for the command; /cp/ |
| is the 2D (x,y) current position from the prior command (for the |
| first command of a path object, /cp/ is (0,0)); /sp/ is the 2D (x,y) |
| start position for the current contour (for the first command of a |
| path object, /sp/ is (0,0)); /pep/ is the 2D (x,y) prior end position |
| from the prior end position (for the first command of a path object, |
| /pep/ is (0,0)); and /ncp/ is the 2D (x,y) "new" current position |
| that will become the current position for the subsequent command; |
| /npep/ is the 2D (x,y) "new" prior end position for the subsequent |
| command. The values /c/, /theta1/, /dtheta/ are explained in the |
| discussion of partial elliptical arc commands below. The values |
| of /rv/, /rh/, /phi/ come from Table 5.arcParameterSpecialization. |
| The values of /A/, /B/, /C/, and /D/ are discussed in the context |
| of Table 5.arcParameterSpecialization. /C_ll/ is the lower-left |
| end-point defined for Equation 5.roundedRectangleContour. |
| |
| If a value specified for a coordinate (however the coordinate is |
| specified) or a value computed from these coordinates (as specified |
| in the discussion that follows) exceeds the implementation's maximum |
| representable value for a single-precision floating-point number, |
| the rendering behavior (discussed in section 5.X.2) of the specified |
| path and the value of said coordinate if queried (section 6.X.2) |
| is undefined. This is relevant because coordinates can be specified |
| explicitly but also relatively (by RELATIVE_* path commands) or |
| encoded in a string of otherwise arbitrary precision and range or |
| computed by weighting. |
| |
| ROUNDED RECTANGLE COMMAND DETAILS |
| |
| In all the rounded-rectangle path commands, the parametric segment |
| path equations in Table 5.pathEquations are expressed in terms of |
| the function /rrect/ that returns an (x,y) position on the rounded |
| rectangle when evaluated over the parametric range t=0..1. /rrect/ |
| is a spline of alternating rational quadratic Bezier segments and |
| linear segments that forms a closed contour. |
| |
| In addition to its parametric variable /t/, /rrect/ has 12 |
| parameters to which geometric properties can be ascribed when these |
| values are positive. (No restriction precludes these parameters |
| to be non-positive; negative and zero values are allowed and |
| supported.) (x,y) is the 2D location of the lower-left corner of the |
| rectangle tightly bounding the rounded rectangle contour; /w/ and /h/ |
| are the respective width and height of the same bounding rectangle. |
| /r_llx/, /r_lrx/, /r_urx/, and /r_ulx/ are the elliptical x-axis |
| radii corresponding to the lower-left, lower-right, upper-right, |
| and upper-left corners of the rounded rectangle; likewise /r_lly/, |
| /r_lry/, /r_ury/, and /r_uly/ are the elliptical y-axis for the |
| same corners. |
| |
| Equation 5.roundedRectangleContour |
| |
| rrect(x,y, / (1-t_0)*C_ll + t_0*A_lr, t=0/8..1/8 |
| w,h, | |
| r_llx,r_lly, | (1-t_1)^2*A_lr + (1-t_1)*t_1*B_lr*sqrt(2) + t_1^2*C_lr)/ |
| r_lrx,r_lry, = < ((1-t_1)^2 + (1-t_1)*t_1*sqrt(2) + t_1^2), t=1/8..2/8 |
| r_urx,r_ury, | |
| r_ulx,r_uly, | (1-t_2)*C_lr + t_2*A_ur, t=2/8..3/8 |
| t) | |
| | (1-t_3)^2*A_ur + (1-t_3)*t_3*B_ur*sqrt(2) + t_3^2*C_ur)/ |
| | ((1-t_3)^2 + (1-t_3)*t_3*sqrt(2) + t_3^2), t=3/8..4/8 |
| | |
| | (1-t_4)*C_ur + t_4*A_ul, t=4/8..5/8 |
| | |
| | (1-t_5)^2*A_ul + (1-t_5)*t_5*B_ul*sqrt(2) + t_5^2*C_ul)/ |
| | ((1-t_5)^2 + (1-t_5)*t_5*sqrt(2) + t_5^2), t=5/8..6/8 |
| | |
| | (1-t_6)*C_ul + t_6*A_ll, t=6/8..7/8 |
| | |
| | (1-t_7)^2*A_ll + (1-t_7)*t_7*B_ll*sqrt(2) + t_7^2*C_ll)/ |
| \ ((1-t_7)^2 + (1-t_7)*t_7*sqrt(2) + t_7^2), t=7/8..1 |
| |
| where |
| |
| t_i = 8*t - i |
| |
| A_ll = (x,y-r_lly), h<0 |
| (x,y+r_lly), otherwise |
| B_ll = (x,y) |
| C_ll = (x-r_llx,y), w<0 |
| (x+r_llx,y), otherwise |
| |
| A_lr = (x+w+r_lrx,y), w<0 |
| (x+w-r_lrx,y), otherwise |
| B_lr = (x+w,y) |
| C_lr = (x+w,y-r_lry), h<0 |
| (x+w,y+r_lry), otherwise |
| |
| A_ur = (x+w,y+h-r_ury*sign(h)), h<0 |
| (x+w,y+h-r_ury*sign(h)), otherwise |
| B_ur = (x+w,y+h) |
| C_ur = (x+w+r_urx,y+h), w<0 |
| (x+w-r_urx,y+h), otherwise |
| |
| A_ul = (x-r_ulx,y+h), w<0 |
| (x+r_ulx,y+h), otherwise |
| B_ul = (x,y+h) |
| C_ul = (x,y+h+r_uly), h<0 |
| (x,y+h-r_uly), otherwise |
| |
| Consider /t_i/ to be a subparmetric range within /t/ where /t_i/ |
| ranges over 0..1 for each spline segment of /rrect/. The 2D control |
| points /A_ll/ through /C_ul/ are shown in Figure 5.roundedRectangle, |
| where /ll/, /lr/, /ur/, and /ul/ correspond to lower-left, |
| lower-right, upper-right, and upper-left respectively. |
| |
| Figure 5.roundedRectangle: Geometric interpretation of Equation |
| 5.roundedRectangleContour parameters. |
| |
| _ r_ulx _ r_urx |
| / \ / \ |
| / \C_ul A_ur / \ |
| B_ul .-----.-----------------------.-----. B_ur \ |
| /| |\ | |
| r_uly < | | > r_ury | |
| \| |/ | |
| A_ul . . C_ur | |
| | | \ |
| | | > h |
| | | / |
| | | | |
| A_ll . . C_rl | |
| /| |\ | |
| r_lly < | | > r_rly | |
| \| |/ | |
| B_ll .-----.-----------------------.-----. B_rl / |
| & (x,y) \ /C_ll A_rl \ / |
| \_/ \_/ |
| r_llx r_rlx |
| \______________ __________________/ |
| \/ |
| w |
| |
| Note that the ROUNDED_RECT*_NV commands degenerate to the RECT_NV |
| command when all the radii are zero. |
| |
| PARTIAL ELLIPTICAL ARC COMMAND DETAILS |
| |
| In all the arc-based path commands, the parametric segment path |
| equations in Table 5.pathEquations are expressed in terms of the |
| functions /arc_x/ and /arc_y/. |
| |
| Equation 5.generalParametricArc |
| |
| arc_x(c,rv,rh,phi,theta1,dtheta,t) = cos(phi)*rh*cos(theta1+t*dtheta) - |
| sin(phi)*rv*sin(theta1+t*dtheta) + c.x |
| arc_y(c,rv,rh,phi,theta1,dtheta,t) = sin(phi)*rh*cos(theta1+t*dtheta) + |
| cos(phi)*rv*sin(theta1+t*dtheta) + c.y |
| |
| This general form of a parametric partial elliptical arc computes |
| (x,y) 2D positions on the arc as /t/ ranges from 0.0 to 1.0 inclusive. |
| |
| In addition to the varying /t/ parameter, these functions depend on |
| a 2D (x,y) center position /c/, a horizontal ellipse radius /rh/, |
| a vertical ellipse radius /rv/, a counterclockwise angle (in radians) |
| of an ellipse with respect to the x-axis /phi/, /theta1/ is the angle |
| (in radians) of the initial point on the partial arc, and /dtheta/ |
| is the difference between the angle (in radians) of the terminal |
| point on the partial arc and /theta1/. The larger of /rh/ and /rv/ |
| is the complete ellipse's major axis while the smaller of the two |
| is the complete ellipse's minor axis. |
| |
| How these additional dependent parameters for /arc_x/ and /arc_y/ |
| are determined depends on the specific arc path command as |
| detailed in Table 5.arcParameterSpecialization. Before explaining |
| how specific arc commands determine these dependent parameters, |
| the following discussion develops a general scheme for converting |
| general end-point representations of arcs to the partial elliptical |
| arc segment representation of Equation 5.generalParametricArc. |
| All the arc commands supported are specializations of this general |
| end-point representation. The general scheme is developed, specific |
| arc commands are specified as special cases of the general end-point |
| representation scheme for arcs. |
| |
| In general, consider seven scalar values (/x1/, /y1/, /x2/, |
| /y2/, /phi/, /fA/, and /fS/) fully parameterizing a given partial |
| elliptical arc: |
| |
| * a 2D position (x1,y1) at the start of a partial elliptical |
| arc segment |
| |
| * a 2D position (x2,y2) at the end of a partial elliptical |
| arc segment |
| |
| * /phi/ is the angle (in radians) from the x-axis of the path |
| space coordinate system to the x-axis of the axis-aligned ellipse |
| |
| * /fA/ is a boolean (the "large arc" flag) that is true when |
| the arc spans greater than 180 degrees; and otherwise false |
| if the arc sweeps 180 degrees or less |
| |
| * /fS/ is a boolean (the "sweep" flag) that is true when the |
| arc sweeps in a counterclockwise direction in path space |
| (so sweeps with increasing angles); and otherwise false |
| when the arc sweeps in a clockwise direction (so sweeps with |
| decreasing angles) |
| |
| Given this parameterization, the procedure below computes the /c/, |
| /rv/, /rh/, /phi/, /theta1/, and /dtheta/ parameters to represent |
| this same arc in the general parametric form of Equation |
| 5.generalParametricArc. |
| |
| Step 1: |
| |
| x1p = cos(phi)*(x1-x2)/2 + sin(phi)*(y1-y2)/2 |
| y1p = -sin(phi)*(x1-x2)/2 + cos(phi)*(y1-y2)/2 |
| |
| If /rh/, /rv/, and /phi/ are such that there is no solution |
| (basically, the ellipse is not big enough to reach from (x1,y1) |
| to (x2,y2), then the ellipse is scaled up uniformly until there |
| is exactly one solution (until the ellipse is just big enough) |
| in this manner: |
| |
| lambda = (x1p/rh)^2 + (y1p/rv)^2 |
| |
| / rh, lambda<=1 |
| rp.x = { |
| \ rh*sqrt(lambda), lambda>1 |
| |
| / rv, lambda<=1 |
| rp.y = { |
| \ rv*sqrt(lambda), lambda>1 |
| |
| Step 2: |
| |
| cp.x = fsgn*sqrt((rp.x^2*rp.y^2 - rp.x^2*y1p^2 - rp.y^2*x1p^2) / |
| (rp.x^2*y1p^2 + rp.y^2*x1p^2) |
| ) * rp.x*y1p/rp.y |
| cp.y = fsgn*sqrt((rp.x^2*rp.y^2 - rp.x^2*y1p^2 - rp.y^2*x1p^2) / |
| (rp.x^2*y1p^2 + rp.y^2*x1p^2) |
| ) * -rp.y*x1p/rp.x |
| |
| where |
| |
| / +1, fA != fS |
| fsgn = { |
| \ -1, fA = fS |
| |
| Step 3: |
| |
| c.x = cos(phi)*cp.x - sin(phi)*cyp + (x1+x2)/2 |
| c.y = sin(phi)*cp.x + cos(phi)*cyp + (y1+y2)/2 |
| |
| In general, the angle between two vectors (u.x, u.y) and (v.x, v.y) |
| can be computed as |
| |
| / arcos(dot(u,v)/sqrt(dot(u,u))*sqrt(dot(v,v))), u.x*v.y-u.y*v.x>=0 |
| angle(u,v) = { |
| \ -arcos(dot(u,v)/sqrt(dot(u,u))*sqrt(dot(v,v))), u.x*v.y-u.y*v.x<0 |
| |
| Step 4: |
| |
| theta1 = angle([1,0], |
| [(x1p-cp.x)/r.x,(y1p-cp.y)/r.y]) |
| dangle = angle([(x1p-cp.x)/r.x,(y1p-cp.y)/r.y], |
| [(-x1p-cp.x)/r.x,(-y1p-cp.y)/r.y]) |
| |
| / dangle - 2*Pi, fS=false AND d>0 |
| / |
| / dangle, fS=false AND d<=0 |
| dtheta = { |
| \ dangle, fS=true AND d>=0 |
| \ |
| \ dangle + 2*Pi, fS=true AND d<0 |
| |
| The arc path commands allow arbitrary numeric values so when these |
| values result in invalid or out-of-range parameters when the above |
| steps are applied, the following further steps are taken to ensure |
| well-defined behavior. |
| |
| If (x1,y1) and (x2,y2) are identical, then this is equivalent to |
| omitting the arc segment entirely. |
| |
| If either of /rh/ or /rv/ is zero, the arc is treated as a straight |
| line segment from (x1,y1) to (x2,y2). |
| |
| Table 5.arcParameterSpecialization now maps the coordinate values |
| for each arc path command to the parameters of the arc end-point |
| parameterization above from which the arc's parametric representation |
| can be obtained. |
| |
| Table 5.arcParameterSpecialization: Arc Path Command |
| |
| Token (x1,y1) rh rv phi (x2,y2) fA fS |
| ---------------------------- ---------- --------- --------- ----------- ------------------- --------------- ------- |
| SMALL_CCW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 c[3],c[4] false true |
| RELATIVE_SMALL_CCW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 cp.x+c[3],cp.y+c[4] false true |
| SMALL_CW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 c[3],c[4] false false |
| RELATIVE_SMALL_CW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 cp.x+c[3],cp.y+c[4] false false |
| LARGE_CCW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 c[3],c[4] true true |
| RELATIVE_LARGE_CCW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 cp.x+c[3],cp.y+c[4] true true |
| LARGE_CW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 c[3],c[4] true false |
| RELATIVE_SMALL_CW_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 cp.x+c[3],cp.y+c[4] true false |
| CIRCULAR_CCW_ARC_TO_NV A.x,A.y abs(c[2]) abs(c[2]) 0 B.x,B.y (c[4]-c[3])>180 true |
| CIRCULAR_CW_ARC_TO_NV A.x,A.y abs(c[2]) abs(c[2]) 0 B.x,B.y (c[4]-c[3])>180 false |
| CIRCULAR_TANGENT_ARC_TO_NV C.x,C.y abs(c[4]) abs(c[4]) 0 D.x,D.y false num>=0 |
| ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 c[5],c[6] c[3]!=0 c[4]!=0 |
| RELATIVE_ARC_TO_NV cp.x,cp.y abs(c[0]) abs(c[1]) c[2]*Pi/180 cp.x+c[5],cp.y+c[6] c[3]!=0 c[4]!=0 |
| |
| where, for CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV, |
| |
| A = (c[0]+c[2]*cos(c[3]*Pi/180), |
| c[1]+c[2]*sin(c[3]*Pi/180)) |
| |
| B = (c[0]+c[2]*cos(c[4]*Pi/180), |
| c[1]+c[2]*sin(c[4]*Pi/180)) |
| |
| and C, D, and num, for CIRCULAR_TANGENT_ARC_TO_NV, are computed |
| through the following steps: |
| |
| Step 1: Compute two tangent vectors: |
| |
| d0.x = cp.x - c[0] |
| d0.y = cp.y - c[1] |
| d2.x = c[2] - c[0] |
| d2.y = c[3] - c[1] |
| |
| Step 2: Compute scaling factors for tangent vectors: |
| |
| num = d0.y*d2.x - d2.y*d0.x |
| denom = sqrt(dot(d0,d0)*dot(d2,d2)) - dot(d0,d2) |
| |
| dist = abs(c[4] * num/denom) |
| |
| l0 = dist/sqrt(dot(d0,d0)) * c[4]/abs(c[4]) |
| l2 = dist/sqrt(dot(d2,d2)) * c[4]/abs(c[4]) |
| |
| Step 3: Add scaled directions to the tangent vector intersection |
| point: |
| |
| / (c[0],c[1]) + d0 * l0, denom!=0 AND c[4]!=0 |
| C = { |
| \ (c[0],c[1]), denom==0 OR c[4]==0 |
| |
| / (c[0],c[1]) + d2 * l2, denom!=0 AND c[4]!=0 |
| D = { |
| \ (c[0],c[1]), denom==0 OR c[4]==0 |
| |
| PATH OBJECT SPECIFICATION |
| |
| Path objects can be specified in one of four ways: |
| |
| 1) explicitly from an array of commands and corresponding |
| coordinates, |
| |
| 2) from a string conforming to one of two supported grammars to |
| specify a string, |
| |
| 3) from a glyph within a font face from a system font or font file, |
| or |
| |
| 4) by linearly combining one or more existing path objects with |
| mutually consistent command sequences to form a new path. |
| |
| In any situation where a path object is specified or re-specified, |
| the command's parameters are re-initialized as discussed in section |
| 5.X.1.5 unless otherwise specified. However modification of path |
| commands and coordinates (section 5.X.1.4) does not modify path |
| parameters. |
| |
| 5.X.1.1 Explicit Path Specification |
| |
| The command |
| |
| void PathCommandsNV(uint path, |
| sizei numCommands, const ubyte *commands, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| specifies a new path object named /path/ where /numCommands/ |
| indicates the number of path commands, read from the array |
| /commands/, with which to initialize that path's command sequence. |
| These path commands reference coordinates read sequentially from the |
| /coords/ array. The type of the coordinates read from the /coords/ |
| array is determined by the /coordType/ parameter which must be |
| one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT, |
| otherwise the INVALID_ENUM error is generated. |
| |
| The /numCommands/ elements of the /commands/ array must be tokens |
| or character in Table 5.pathCommands. The command sequence matches |
| the element order of the /commands/ array. Each command references |
| a number of coordinates specified by "Coordinate count" column of |
| Table 5.pathCommands, starting with the first (zero) element of |
| the /coords/ array and advancing by the coordinate count for each |
| command. If any of these /numCommands/ command values are not |
| listed in the "Token" or "Character aliases" columns of Table |
| 5.pathCommands, the INVALID_ENUM error is generated. |
| |
| The INVALID_OPERATION error is generated if /numCoords/ does not |
| equal the number of coordinates referenced by the command sequence |
| specified by /numCommands/ and /commands/ (so /numCoords/ provides a |
| sanity check that the /coords/ array is being interpreted properly). |
| The error INVALID_VALUE is generated if either /numCommands/ or |
| /numCoords/ is negative. |
| |
| If the PathCommandsNV command results in an error, the path object |
| named /path/ is not changed; if there is no error, the prior contents |
| of /path/, if /path/ was an existent path object, are lost and the |
| path object name /path/ becomes used. |
| |
| 5.X.1.2 String Path Specification |
| |
| The command |
| |
| void PathStringNV(uint path, enum format, |
| sizei length, const void *pathString); |
| |
| specifies a new path object named /path/ where /format/ must be |
| either PATH_FORMAT_SVG_NV or PATH_FORMAT_PS_NV, in which case the |
| /length/ and /pathString/ are interpreted according to grammars |
| specified in sections 5.X.1.2.1 and 5.X.1.2.2 respectively. |
| The INVALID_VALUE error is generated if /length/ is negative. |
| |
| If the PathStringNV command results in an error, the path object |
| named /path/ is not changed; if there is no error, the prior contents |
| of /path/, if /path/ was an existent path object, are lost and the |
| path object name /path/ becomes used. |
| |
| 5.X.1.2.1 Scalable Vector Graphics Path Grammar |
| |
| If the /format/ parameter of PathStringNV is PATH_FORMAT_SVG_NV, |
| the /pathString/ parameter is interpreted as a string of ubyte ASCII |
| characters with /length/ elements. |
| |
| This string must satisfy the "svg-path" production in the path |
| grammar below. This grammar is taken directly from the Scalable |
| Vector Graphics (SVG) 1.1 (April 30, 2009) specification. |
| |
| The following notation is used in the Backus-Naur Form (BNF) |
| description of the grammar for an SVG path string: |
| |
| * *: 0 or more |
| * +: 1 or more |
| * ?: 0 or 1 |
| * (): grouping |
| * ()^n: grouping with n repetitions where n is explained subsequently |
| * |: separates alternatives |
| * double quotes surround literals |
| * #x: prefixes an ASCII character value followed by hexadecimal |
| digits |
| * ..: means any of an inclusive range of ASCII characters, so |
| '0'..'9' means any digit character |
| |
| The following is the grammar for SVG paths. |
| |
| svg-path: |
| wsp* moveto-drawto-command-groups? wsp* |
| moveto-drawto-command-groups: |
| moveto-drawto-command-group |
| | moveto-drawto-command-group wsp* moveto-drawto-command-groups |
| moveto-drawto-command-group: |
| moveto wsp* drawto-commands? |
| drawto-commands: |
| drawto-command |
| | drawto-command wsp* drawto-commands |
| drawto-command: |
| closepath |
| | lineto |
| | horizontal-lineto |
| | vertical-lineto |
| | curveto |
| | smooth-curveto |
| | quadratic-bezier-curveto |
| | smooth-quadratic-bezier-curveto |
| | elliptical-arc |
| moveto: |
| ( "M" | "m" ) wsp* moveto-argument-sequence |
| moveto-argument-sequence: |
| coordinate-pair |
| | coordinate-pair comma-wsp? lineto-argument-sequence |
| closepath: |
| ("Z" | "z") |
| lineto: |
| ( "L" | "l" ) wsp* lineto-argument-sequence |
| lineto-argument-sequence: |
| coordinate-pair |
| | coordinate-pair comma-wsp? lineto-argument-sequence |
| horizontal-lineto: |
| ( "H" | "h" ) wsp* horizontal-lineto-argument-sequence |
| horizontal-lineto-argument-sequence: |
| coordinate |
| | coordinate comma-wsp? horizontal-lineto-argument-sequence |
| vertical-lineto: |
| ( "V" | "v" ) wsp* vertical-lineto-argument-sequence |
| vertical-lineto-argument-sequence: |
| coordinate |
| | coordinate comma-wsp? vertical-lineto-argument-sequence |
| curveto: |
| ( "C" | "c" ) wsp* curveto-argument-sequence |
| curveto-argument-sequence: |
| curveto-argument |
| | curveto-argument comma-wsp? curveto-argument-sequence |
| curveto-argument: |
| coordinate-pair comma-wsp? coordinate-pair comma-wsp? coordinate-pair |
| smooth-curveto: |
| ( "S" | "s" ) wsp* smooth-curveto-argument-sequence |
| smooth-curveto-argument-sequence: |
| smooth-curveto-argument |
| | smooth-curveto-argument comma-wsp? smooth-curveto-argument-sequence |
| smooth-curveto-argument: |
| coordinate-pair comma-wsp? coordinate-pair |
| quadratic-bezier-curveto: |
| ( "Q" | "q" ) wsp* quadratic-bezier-curveto-argument-sequence |
| quadratic-bezier-curveto-argument-sequence: |
| quadratic-bezier-curveto-argument |
| | quadratic-bezier-curveto-argument comma-wsp? |
| quadratic-bezier-curveto-argument-sequence |
| quadratic-bezier-curveto-argument: |
| coordinate-pair comma-wsp? coordinate-pair |
| smooth-quadratic-bezier-curveto: |
| ( "T" | "t" ) wsp* smooth-quadratic-bezier-curveto-argument-sequence |
| smooth-quadratic-bezier-curveto-argument-sequence: |
| coordinate-pair |
| | coordinate-pair comma-wsp? smooth-quadratic-bezier-curveto-argument-sequence |
| elliptical-arc: |
| ( "A" | "a" ) wsp* elliptical-arc-argument-sequence |
| elliptical-arc-argument-sequence: |
| elliptical-arc-argument |
| | elliptical-arc-argument comma-wsp? elliptical-arc-argument-sequence |
| elliptical-arc-argument: |
| nonnegative-number comma-wsp? nonnegative-number comma-wsp? |
| number comma-wsp flag comma-wsp flag comma-wsp coordinate-pair |
| coordinate-pair: |
| coordinate comma-wsp? coordinate |
| coordinate: |
| number |
| nonnegative-number: |
| integer-constant |
| | floating-point-constant |
| number: |
| sign? integer-constant |
| | sign? floating-point-constant |
| flag: |
| "0" | "1" |
| comma-wsp: |
| (wsp+ comma? wsp*) | (comma wsp*) |
| comma: |
| "," |
| integer-constant: |
| digit-sequence |
| floating-point-constant: |
| fractional-constant exponent? |
| | digit-sequence exponent |
| fractional-constant: |
| digit-sequence? "." digit-sequence |
| | digit-sequence "." |
| exponent: |
| ( "e" | "E" ) sign? digit-sequence |
| sign: |
| "+" | "-" |
| digit-sequence: |
| digit |
| | digit digit-sequence |
| digit: |
| "0".."9" |
| wsp: |
| (#x20 | #x9 | #xD | #xA) |
| |
| The processing of the BNF must consume as much of a given BNF |
| production as possible, stopping at the point when a character |
| is encountered which no longer satisfies the production. Thus, |
| in the string "M 100-200", the first coordinate for the "moveto" |
| consumes the characters "100" and stops upon encountering the minus |
| sign because the minus sign cannot follow a digit in the production |
| of a "coordinate". The result is that the first coordinate will be |
| "100" and the second coordinate will be "-200". |
| |
| Similarly, for the string "M 0.6.5", the first coordinate of the |
| "moveto" consumes the characters "0.6" and stops upon encountering |
| the second decimal point because the production of a "coordinate" |
| only allows one decimal point. The result is that the first coordinate |
| will be "0.6" and the second coordinate will be ".5". |
| |
| The grammar allows the string to be empty (zero length). This is |
| not an error, instead specifies a path with no commands. |
| |
| Table 5.svgCommands maps productions in the grammar above to the |
| path commands in Table 5.pathCommands; each such path command, with |
| its corresponding coordinates, is added to the path command sequence |
| of the path object. Each production listed in Table 5.svgCommands |
| consumes a number of coordinates consistent with the path command |
| token's coordinate count listed in Table 5.pathCommands. The |
| "coordinate" and "nonnegative-number" productions convert to a numeric |
| coordinate value in the obvious way. The "flag" production converts |
| "0" and "1" to numeric coordinate values zero and one respectively. |
| |
| Table 5.svgCommands: SVG Grammar Commands to Path Command Tokens |
| |
| Grammar's prior |
| Production command character Path command token |
| ------------------------------------------------- ----------------- ------------------------------------- |
| moveto-argument-sequence "M" MOVE_TO_NV |
| "m" RELATIVE_MOVE_TO_NV |
| closepath "Z" or "z" CLOSE_PATH_NV |
| lineto-argument-sequence "L" LINE_TO_NV |
| "l" RELATIVE_LINE_TO_NV |
| horizontal-lineto-argument-sequence "H" HORIZONTAL_LINE_TO_NV |
| "h" RELATIVE_HORIZONTAL_LINE_TO_NV |
| vertical-lineto-argument-sequence "V" VERTICAL_LINE_TO_NV |
| "v" RELATIVE_VERTICAL_LINE_TO_NV |
| quadratic-bezier-curveto-argument "Q" QUADRATIC_CURVE_TO_NV |
| "q" RELATIVE_QUADRATIC_CURVE_TO_NV |
| smooth-quadratic-bezier-curveto-argument-sequence "T" SMOOTH_QUADRATIC_CURVE_TO_NV |
| "t" RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV |
| curveto-argument "C" CUBIC_CURVE_TO_NV |
| "c" RELATIVE_CUBIC_CURVE_TO_NV |
| smooth-curveto-argument "S" SMOOTH_CUBIC_CURVE_TO_NV |
| "s" RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV |
| elliptical-arc-argument "A" ARC_TO_NV |
| "a" RELATIVE_ARC_TO_NV |
| |
| If the string fails to satisfy the svg-path production, the path |
| object named /path/ is not changed. The production may not be |
| satisfied for one of two reasons: either the grammar cannot be not |
| satisfied by the string, or the grammar is satisfied but there still |
| remain a non-zero number of characters in the string. Neither |
| failure to satisfy the production generates an error; instead the |
| PATH_ERROR_POSITION_NV state is set to the character offset where the |
| grammar was first not satisfied or where the grammar was exhausted. |
| If the string was parsed successfully and the command did not generate |
| an error, the PATH_ERROR_POSITION_NV state is set to negative one |
| to indicate success. |
| |
| 5.X.1.2.2 PostScript Path Grammar |
| |
| If the /format/ parameter of PathStringNV is PATH_FORMAT_PS_NV, |
| the /pathString/ parameter is interpreted as a string of ubyte ASCII |
| characters with /length/ elements. |
| |
| This string must satisfy the "ps-path" production in the path |
| grammar below. This grammar is parses path specified in PostScript's |
| subgrammar for user paths specified by "PostScript Language Reference |
| Manual" 3rd edition. |
| |
| The following is the grammar (using the same notation as section |
| 5.X.1.2.1) for PS paths with special support for binary encoding modes |
| (as explained below): |
| |
| ps-path: |
| ps-wsp* user-path? ps-wsp* |
| | ps-wsp* encoded-path ps-wsp* |
| user-path: |
| user-path-cmd |
| | user-path-cmd ps-wsp+ user-path |
| user-path-cmd: |
| setbbox |
| | ps-moveto |
| | rmoveto |
| | ps-lineto |
| | rlineto |
| | ps-curveto |
| | rcurveto |
| | arc |
| | arcn |
| | arct |
| | ps-closepath |
| | ucache |
| setbbox: |
| numeric-value numeric-value numeric-value numeric-value setbbox-cmd |
| setbbox-cmd: |
| "setbbox" |
| | #x92 #x8F |
| ps-moveto: |
| numeric-value numeric-value moveto-cmd |
| moveto-cmd: |
| "moveto" |
| | #x92 #x6B |
| rmoveto: |
| numeric-value numeric-value rmoveto-cmd |
| rmoveto-cmd: |
| "rmoveto" |
| | #x92 #x86 |
| ps-lineto: |
| numeric-value numeric-value lineto-cmd |
| lineto-cmd: |
| "lineto" |
| | #x92 #x63 |
| rlineto: |
| numeric-value numeric-value rlineto-cmd |
| rlineto-cmd: |
| "rlineto" |
| | #x92 #x85 |
| ps-curveto: |
| numeric-value numeric-value numeric-value numeric-value numeric-value numeric-value curveto-cmd |
| curveto-cmd: |
| "curveto" |
| | #x92 #x2B |
| rcurveto: |
| numeric-value numeric-value numeric-value numeric-value numeric-value numeric-value rcurveto-cmd |
| rcurveto-cmd: |
| "rcurveto" |
| | #x92 #x7A |
| arc: |
| numeric-value numeric-value numeric-value numeric-value numeric-value arc-cmd |
| arc-cmd: |
| "arc" |
| | #x92 #x05 |
| arcn: |
| numeric-value numeric-value numeric-value numeric-value numeric-value arcn-cmd |
| arcn-cmd: |
| "arcn" |
| | #x92 #x06 |
| arct: |
| numeric-value numeric-value numeric-value numeric-value numeric-value arct-cmd |
| arct-cmd: |
| "arct" |
| | #x92 #x07 |
| ps-closepath: |
| "closepath" |
| | #x92 #x16 |
| ucache: |
| "ucache" |
| | #x92 #xB1 |
| encoded-path: |
| data-array ps-wsp* operator-string |
| data-array: |
| "{" ps-wsp* numeric-value-sequence? "}" |
| | homogeneous-number-array |
| | ascii85-homogeneous-number-array |
| operator-string: |
| hexadecimal-binary-string |
| | ascii85-string |
| | short-binary-string |
| | be-long-binary-string |
| | le-long-binary-string |
| hexadecimal-binary-string: |
| "<" ps-wsp-chars* hexadecimal-sequence ps-wsp-chars* ">" |
| hexadecimal-sequence: |
| hexadecimal-digit |
| | hexadecimal-digit ps-wsp-chars* hexadecimal-sequence |
| hexadecimal-digit: |
| digit |
| | "a".."f" | |
| | "A".."F" |
| short-binary-string: |
| #x8E one-byte ( one-byte )^n |
| /where n is the value of the one-byte production decoded |
| as an unsigned integer, 0 through 255/ |
| be-long-binary-string: |
| #x8F two-bytes ( one-byte )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| big-endian byte order/ |
| le-long-binary-string: |
| #x90 two-bytes ( one-byte )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| little-endian byte order/ |
| numeric-value-sequence: |
| numeric-value: |
| | numeric-value numeric-value-sequence |
| numeric-value: |
| number ps-wsp+ |
| | radix-number ps-wsp+ |
| | be-integer-32bit |
| | le-integer-32bit |
| | be-integer-16bit |
| | le-integer-16bit |
| | le-integer-8bit |
| | be-fixed-16bit |
| | le-fixed-16bit |
| | be-fixed-32bit |
| | le-fixed-32bit |
| | be-float-ieee |
| | le-float-ieee |
| | native-float-ieee |
| be-integer-32bit: |
| #x84 four-bytes |
| le-integer-32bit: |
| #x85 four-bytes |
| be-integer-16bit: |
| #x86 two-bytes |
| le-integer-16bit: |
| #x87 two-bytes |
| le-integer-8bit: |
| #x88 one-byte |
| be-fixed-32bit: |
| #x89 #x0..#x1F four-bytes |
| le-fixed-32bit: |
| #x89 #x80..#x9F four-bytes |
| be-fixed-16bit: |
| #x89 #x20..#x2F two-bytes |
| le-fixed-16bit: |
| #x89 #xA0..#xAF two-bytes |
| be-float-ieee: |
| #x8A four-bytes |
| le-float-ieee: |
| #x8B four-bytes |
| native-float-ieee: |
| #x8C four-bytes |
| radix-number: |
| base "#" base-number |
| base: |
| digit-sequence |
| base-number: |
| base-digit-sequence |
| base-digit-sequence: |
| base-digit |
| | base-digit base-digit-sequence |
| base-digit: |
| digit |
| | "a".."z" |
| | "A".."Z" |
| homogeneous-number-array: |
| be-fixed-32bit-array |
| | be-fixed-16bit-array |
| | be-float-ieee-array |
| | native-float-ieee-array |
| | le-fixed-32bit-array |
| | le-fixed-16bit-array |
| | le-float-ieee-array |
| be-fixed-32bit-array: |
| #x95 #x0..#x1F two-bytes ( four-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| big-endian byte order/ |
| be-fixed-16bit-array: |
| #x95 #x20..#x2F two-bytes ( two-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| big-endian byte order/ |
| be-float-ieee-array: |
| #x95 #x30 two-bytes ( four-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| big-endian byte order/ |
| le-fixed-32bit-array: |
| #x95 #x80..#x9F two-bytes ( four-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| little-endian byte order/ |
| le-fixed-16bit-array: |
| #x95 #xA0..#xAF two-bytes ( two-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| little-endian byte order/ |
| le-float-ieee-array: |
| #x95 #xB0 two-bytes ( four-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| little-endian byte order/ |
| native-float-ieee-array: |
| #x95 ( #x31 | #xB1 ) two-bytes ( four-bytes )^n |
| /where n is the value of the two-bytes production decoded |
| as an unsigned integer, 0 through 65535, decoded in |
| the native byte order/ |
| ascii85-string: |
| "<~" (#x21..#x75 | "z" | psp-wsp )* "~>" |
| ascii85-homogeneous-number-array: |
| "<~" (#x21..#x75 | "z" | psp-wsp )* "~>" |
| one-byte: |
| #x0..#xFF |
| two-bytes: |
| #x0..#xFF #x0..#xFF |
| four-bytes: |
| #x0..#xFF #x0..#xFF #x0..#xFF #x0..#xFF |
| ps-wsp: |
| ps-wsp-chars |
| | ps-comment |
| ps-wsp-chars: |
| ( #x20 | #x9 | #xA | #xC | #xD | #x0 ) |
| ps-comment: |
| "%" ( #0..#9 | #xB..#xC | #xE..#xFF )* ( #xD | #xA ) |
| |
| This grammar is not technically a pure BNF because it uses binary |
| encoded data to encode how many characters should be as part of |
| several productions (short-binary-string, native-float-ieee-array, |
| etc.). |
| |
| The processing of the BNF must consume as much of a given BNF |
| production as possible, stopping at the point when a character |
| is encountered which no longer satisfies the production. |
| |
| The grammar allows the string to be empty (zero length). This |
| is not an error, instead specifies a path with no commands. |
| |
| Table 5.psCommands maps productions in the grammar above to the path |
| commands in Table 5.pathCommands; each such path command, with its |
| corresponding coordinates, is added to the path command sequence |
| of the path object. Each production listed in Table 5.svgCommands |
| consumes a quantity of values, matched by the "number" production, |
| consistent with the path command token's coordinate count listed |
| in Table 5.pathCommands. The "setbbox" and "ucache" products are |
| matched but do not result in path commands. |
| |
| Table 5.psCommands: PS Grammar Commands to Path Command Tokens |
| |
| Production Path command token |
| ------------ -------------------------- |
| arc CIRCULAR_CCW_ARC_TO_NV |
| arcn CIRCULAR_CW_ARC_TO_NV |
| arct CIRCULAR_TANGENT_ARC_TO_NV |
| ps-closepath CLOSE_PATH_NV |
| ps-curveto CUBIC_CURVE_TO_NV |
| ps-lineto LINE_TO_NV |
| ps-moveto MOVE_TO_NV |
| rcurveto RELATIVE_CUBIC_CURVE_TO_NV |
| rlineto RELATIVE_LINE_TO_NV |
| rmoveto RELATIVE_MOVE_TO_NV |
| setbbox - |
| ucache - |
| |
| The "number" production converts to a numeric coordinate value |
| in the obvious way. The "radix-number" production converts the |
| base-n integer conversion of its "base-number" production using |
| the base indicated by the base-10 integer conversion of its "base" |
| production where the base /n/ must be within the range 2 to 26. |
| The "base-number" is interpreted in base /n/; the "base-number" |
| production must contain digits ranging from 0 to /n/-1; digits greater |
| than 9 are represented by the letters A through Z (or a through z) |
| for the values 10 through 35 respectively. |
| |
| The "encoded-path" production provides a compact and precise way |
| to encode paths with the commands and coordinates decoupled. |
| |
| The "data-array" subproductions provide a sequence of coordinate |
| values for the encoded path's commands. The "data-array" |
| subproduction provides a sequence of numbers that is used by the |
| following "operator-string" production. |
| |
| The "operator-string" subproduction is interpreted as a sequence |
| of encoded path commands, one command per byte generated by |
| "operator-string"'s "binary-string" production. |
| |
| Each hexadecimal character in the "hexadecimal-binary-string" |
| production is a nibble (a 4-bit quantity). Each pair of characters |
| is two nibbles and they form a byte with the first nibble |
| representing the most signification bits of the byte. If the |
| "hexadecimal-binary-string" production contains an odd number of |
| hexadecimal characters, "0" is assumed to be suffixed to make an |
| even number of characters (so "A7C" would encode the bytes 167 for |
| "A7" followed by 192 for "C" which is treated as "C0" for 192). |
| Table 5.encodedPathOpcodes maps the values contained in the operator |
| string to path commands. Each command consumes from the coordinate |
| array supplied by the "data-array" production a number of values |
| for the command's coordinates equal to the path command token's |
| coordinate count listed in Table 5.pathCommands. If the value for |
| an element of the operator string is between 12 and 32 inclusive, |
| the grammar fails to parse at this point. If the value /n/ of an |
| element of the operator string is between 32 and 255, then this value |
| /n/-32 is treated as a repetition count and is treated as if /n/-32 |
| repetitions of the next command are contained in the operator string |
| instead and the appropriate number of coordinates are consumed from |
| the associated sequence of coordinate values. |
| |
| Table 5.encodedPathOpcodes |
| |
| Opcode Name |
| ------ --------- |
| 0 setbbox |
| 1 moveto |
| 2 rmoveto |
| 3 lineto |
| 4 rlineto |
| 5 curveto |
| 6 rcurveto |
| 7 arc |
| 8 arcn |
| 9 arct |
| 10 closepath |
| 11 ucache |
| |
| The ASCII characters in the "ascii85-binary-string" production |
| consists of a sequence of printable ASCII characters between the "<~" |
| and "~>" delimiters. This represents arbitrary binary data using |
| an encoding technique that products a 4:5 expansion as opposed to |
| the 1:2 expansion for the "hexadecimal-binary-string" production. |
| This encoding is known as ASCII base-85. |
| |
| Binary data in the ASCII base-85 encoding are encoded in 4-tuples |
| (groups of 4) each 4-tuple is used to produce a 5-type of ASCII |
| characters. If the binary 4-tuple is (b1,b2,b3,b4) and the encoded |
| 5-tuple is (c1,c2,c3,c4,c5), then the relation between them is: |
| |
| (b1 * 256^3) + (b2 * 256^2) + (b3 * 256^1) + b4 = |
| (c1 * 256^4) + (c2 * 256^3) + (c3 * 256^2) + (c4 * 256^3) + c5 |
| |
| The four bytes of binary data are interpreted as a base-256 number and |
| then converted into a base-85 number. The five "digits" of this number, |
| (c1,c2,c3,c4,c5), are then converted into ASCII characters by adding 33, |
| which is the ASCII code for '!', to each. ASCII characters in the |
| range '!' to 'u' are used, where '!' represented the value 0 and 'u' |
| represents the value 84. As a special case, if all five digits are |
| zero, they must be represented by either a single 'z' instead of by |
| '!!!!'. |
| |
| If the encoded sequence ends with a sequence of characters that is |
| not an even multiple of 4, the last 1, 2, or 3 characters to produce |
| a special final partial 5-tuple. Given n (1, 2, or 3) bytes of final |
| binary data, an encoder must first append 4-n zero bytes to make |
| a complete 4-tuple. Then, the encoder must encode the 4-tuple in |
| the usual way, but without applying the 'z' special case. Finally, |
| the encoder must write the first n+1 bytes of the resulting 5-tuple. |
| Those bytes are immediately followed by the "~>" terminal marker. |
| |
| This encoding scheme is reversible and the GL is responsible for |
| converting the ASCII base-85 string into its corresponding binary |
| data. White space within an ASCII base-85 encoded string is ignored. |
| |
| The following conditions constitute encoding violations of the ASCII |
| base-85 scheme: |
| |
| * The value represented by a 5-tuple is greater than 2^32-1 |
| |
| * The 'z' value occurs in the middle of a 5-tuple. |
| |
| * A final partial 5-tuple contains only one character. |
| |
| Any such encoding violation is a parsing error. |
| |
| Once the ASCII base-85 string is decoded, this sequence of bytes |
| is treated as operator elements in the identical manner as the |
| elements for the "hexadecimal-string" subproduction. This means |
| invalid opcodes are possible and are treated as parsing errors, and |
| Valid opcodes and counts consume coordinates from the "data-array" |
| production to generate path commands with associated coordinates. |
| |
| The "short-binary-string", "be-long-binary-string", and |
| "le-long-binary-string" subproductions of "operator-string" are |
| binary encodings of a sequence of operator string elements. |
| |
| The "short-binary-string" has a count from 0 to 255 supplied by its |
| "one-byte" subproduction which indicates how many bytes follow. |
| These remaining (unsigned) bytes generate the sequence of operator |
| string elements. |
| |
| The "be-long-binary-string" has a count from 0 to 65535 supplied by |
| its "two-byte" subproduction which indicates how many bytes follow. |
| These remaining (unsigned) bytes generate the sequence of operator |
| string elements. The "two-byte" subproduction is converted to a |
| count by multiplying the first unsigned byte by 256 and adding it |
| to the second unsigned byte. |
| |
| The "le-long-binary-string" has a count from 0 to 65535 supplied by |
| its "two-byte" subproduction which indicates how many bytes follow. |
| These remaining (unsigned) bytes generate the sequence of operator |
| string elements. The "two-byte" subproduction is converted to a |
| count by multiplying the second unsigned byte by 256 and adding it |
| to the first unsigned byte. |
| |
| The "encoded-path" fails to parse if invalid opcodes are detected |
| in the operator string or the sequence of numbers for coordinates |
| is exhausted prematurely. |
| |
| If the string fails to satisfy the ps-path production, the path |
| object named /path/ is not changed. The production may not be |
| satisfied for one of three reasons: the grammar cannot be not |
| satisfied by the string, the string has invalid sequences (such |
| as ASCII base-85 violations, exhausting the coordinate data in the |
| "data-array" production, or invalid opcodes encountered in the |
| "operator-string" production), or the grammar is satisfied but |
| there still remain a non-zero number of characters in the string. |
| None of these failures to satisfy the grammar generates an error; |
| instead the PATH_ERROR_POSITION_NV state is set to the character |
| offset where the grammar was first not satisfied, violated |
| semantically, or where the grammar was exhausted. If the string |
| was parsed successfully and the command did not generate an error, |
| the PATH_ERROR_POSITION_NV state is set to negative one to indicate |
| success. |
| |
| If a parsing error occurs, the exact value assigned to the |
| PATH_ERROR_POSITION_NV state variable is implementation-dependent |
| (because the specifics of error position determination is difficult |
| to specify) though the determined error location should be nearby |
| the first error. |
| |
| 5.X.1.3 Font Glyph Path Specification |
| |
| PATH GLYPHS FROM CHARACTER CODE SEQUENCE |
| |
| The command |
| |
| void PathGlyphsNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| sizei numGlyphs, enum type, |
| const void *charcodes, |
| enum handleMissingGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| |
| creates, if no error occurs, a range of path objects named from |
| /firstPathName/ to /firstPathName/+/numGlyphs/-1 based on the |
| font face indicated by /fontTarget/, /fontName/, and /fontStyle/ |
| and the sequence of /numGlyphs/ character codes listed in the |
| /charcodes/ array, as interpreted based by the /type/ parameter. |
| However each particular name in the range /firstPathName/ to |
| /firstPathName/+/numGlyphs/-1 is specified as a new path object only |
| if that name is not already in use as a path object; if a name is |
| already in use, that named path object is silently left undisturbed. |
| A path object name is also left undisturbed if the |
| /handleMissingGlyphs/ parameter is SKIP_MISSING_GLYPH_NV and the |
| character code for a given glyph corresponds to the font's missing |
| glyph or the character code is otherwise not available. |
| |
| The error INVALID_VALUE is generated if /numGlyphs/ or /emScale/ |
| is negative. |
| |
| The /fontTarget/ parameter must be one of STANDARD_FONT_NAME_NV, |
| SYSTEM_FONT_NAME_NV, or FILE_NAME_NV; otherwise the INVALID_ENUM |
| error is generated. |
| |
| The /handleMissingGlyphs/ parameter must be one of |
| SKIP_MISSING_GLYPH_NV or USE_MISSING_GLYPH_NV; otherwise the |
| INVALID_ENUM error is generated. |
| |
| If /fontTarget/ is STANDARD_FONT_NAME_NV, then /fontName/ is |
| interpreted as a nul-terminated 8-bit ASCII character string that |
| must be one of the following strings: "Serif", "Sans", "Mono", |
| or "Missing"; otherwise the INVALID_VALUE error is generated. |
| These "Serif", "Sans", and "Mono" names respectively correspond to |
| serif, sans-serif, and sans monospaced font faces with the intent |
| that the font face matches the appearance, metrics, and kerning |
| of the DejaVu fonts of the same names. All implementations /must/ |
| support these font names for the STANDARD_FONT_NAME_NV target. |
| |
| For the STANDARD_FONT_NAME_NV targets with "Serif", "Sans", and |
| "Mono", all implementations /must/ support the first 256 character |
| codes defined by Unicode and the ISO/IEC 8859-1 (Latin-1 Western |
| European) character encoding though implementations are strongly |
| encouraged to support as much of the Unicode character codes as the |
| system's underlying font and language support provides. |
| |
| For the STANDARD_FONT_NAME_NV targets with "Missing", the entire |
| sequence of path objects must be populated with an identical box |
| outline with metrics matching this box. |
| |
| If /fontTarget/ is SYSTEM_FONT_NAME_NV, then /fontName/ is interpreted |
| as a nul-terminated 8-bit ASCII character string that corresponds to a |
| system-specific font name. These names are intended to correspond to |
| the fonts names typically used in web content (e.g. Arial, Georgia, |
| Times Roman, Helvetica). The mapping of the system font character |
| string to a system font is assumed to be performed by the GL server. |
| |
| If /fontTarget/ is FILE_NAME_NV, then /fontName/ is interpreted as |
| a nul-terminated 8-bit ASCII character string that corresponds to |
| a system-specific file name in a standard outline font format. |
| The specific interpretation of this name depends on the system |
| conventions for identifying files by name. This name can be an |
| absolute or relative path. The name is expected to include the |
| font name's extension. The mapping of the font file name to a |
| font is assumed to be performed by the GL client. What font file |
| formats are supported is system dependent but implementations are |
| encouraged to support outline font formats standard to the system |
| (e.g. TrueType for Windows systems, etc.). |
| |
| If the /fontTarget/ and /fontName/ combination can not be loaded for |
| any reason (including the file name could not be opened, the font |
| name is not available on the system, the font file format is not |
| supported, the font file format is corrupted, etc.) and there is no |
| other error generated, the command succeeds silently (so no error |
| is generated) and the range of named path objects is not modified. |
| If the named path objects did not exist previously, they continue |
| to not exist. |
| |
| The /fontStyle/ parameter is a bitfield allowed to have the |
| bits BOLD_BIT_NV or ITALIC_BIT_NV set; if other bits are set, the |
| INVALID_VALUE error is generated. The font style is used as a hint to |
| indicate the style of the font face. Glyphs are generated with the |
| font's bold or italic style respectively (or combination thereof) |
| if the BOLD_BIT_NV or ITALIC_BIT_NV bits are set; otherwise, the |
| value 0 or NONE indicates the default font face style should be used |
| to generate the requested glyphs. In situations where the bold or |
| italic style of the font is encoded in the font name or file name, |
| the /fontStyle/ parameter is ignored. |
| |
| The generated glyphs for the path objects named /firstPathName/ |
| to /firstPathName/+/numGlyphs/-1 are specified by the /numGlyphs/ |
| character codes listed in the /charcodes/ array where each element of |
| the array is determined by the /type/ parameter that must be one of |
| UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT, UTF8_NV, UTF16_NV, |
| 2_BYTES, 3_BYTES, and 4_BYTES with the array accessed in the same |
| manner as the CallLists command's /type/ and /lists/ parameters |
| (though not offset by the display list base), but indicating character |
| codes instead of display list names. |
| |
| The character codes from the /charcodes/ array are Unicode character |
| codes if the font in question can map from the Unicode character |
| set to the font's glyphs. If the font has no meaningful mapping |
| from Unicode, the font's standard character set is used instead |
| of Unicode (e.g. a font filled with non-standard symbols). For a |
| font supporting a character set that can be mapped to the Unicode |
| character set, a best effort should be made to map the specified |
| character code from its Unicode character code interpretation to |
| the closest appropriate glyph in the specified font. |
| |
| Path objects created from glyphs by PathGlyphsNV have their path |
| object metric state initialized from the metrics of the glyph from |
| which they were specified. Section 6.X.3. ("Path Object Glyph |
| Typographic Queries") explains how these metrics are queried and |
| what their values mean. While the per-glyph metrics are expected to |
| vary from glyph to glyph within a font face, the per-font metrics |
| are expected to be identical for every path object created from a |
| given font name and font style combination. |
| |
| Metrics in font space of glyphs are scaled by a value /s/ that is the |
| ratio of the /emScale/ parameter divided by the font's units per Em; |
| if the /emScale/ parameter equals zero, treat /emScale/ as if it was |
| identical to the font's units per Em such that /s/ is exactly 1.0. |
| Each glyph's outline are also scaled by /s/. The metric values /not/ |
| scaled by /s/ are GLYPH_HAS_KERNING_BIT_NV, FONT_UNITS_PER_EM_BIT_NV, |
| FONT_HAS_KERNING_BIT_NV, and FONT_NUM_GLYPH_INDICES_BIT_NV (since |
| these metric values are not specified in font units). |
| |
| The FONT_NUM_GLYPH_INDICES_BIT_NV metric value returns -1 for path |
| objects created with the STANDARD_FONT_NAME_NV (as such fonts are |
| not accessed by glyph index, only character point); otherwise, the |
| value is number of glyphs indices for the font, whether or not the |
| path object is created from a character point or glyph index. |
| |
| When unknown or missing character codes in a font face are specified |
| and the /handleMissingGlyph/ parameter is USE_MISSING_GLYPHS_NV, |
| this situation should be handled in a manner appropriate to the |
| character code, font face, and implementation. Typically this |
| involves using the font's missing glyph for the unknown or missing |
| character code. |
| |
| If the /pathParameterTemplate/ parameter names an existing path |
| object, that path object's current parameters listed in Table |
| 5.pathParameters (excepting PATH_FILL_MODE_NV as explained in |
| the following paragraph) are used to initialize the respective |
| parameters of path objects specified by this command; otherwise |
| if the /pathParameterTemplate/ path object name does not exist, |
| the initial path parameters are used as specified by table 6.Y |
| (without generating an error). |
| |
| Path objects created from glyphs by PathGlyphsNV have their |
| PATH_FILL_MODE_NV parameter, as explained in Section 5.X.1.5 ("Path |
| Parameter Specification"), initialized according to the fill |
| conventions of the font outlines within the font (instead of the |
| COUNT_UP_NV default for paths specified by means other than glyphs). |
| This may be one of: COUNT_UP_NV if the font's outline winding |
| convention is counterclockwise and its outline filling assumes the |
| non-zero winding rule; COUNT_DOWN_NV if the font's outline winding |
| convention is clockwise and its outline filling assumes the non-zero |
| winding rule; or INVERT if the font's outline filling assumes the |
| even-odd winding rule. |
| |
| PATH GLYPHS FROM CHARACTER CODE RANGE |
| |
| The command |
| |
| void PathGlyphRangeNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint firstGlyph, |
| sizei numGlyphs, |
| enum handleMissingGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| |
| allows a sequence of character codes in a font face to specify a |
| sequence of path objects and is equivalent to |
| |
| int *array = malloc(sizeof(int)*numGlyphs); |
| if (array) { |
| for (int i=0; i<numGlyphs; i++) { |
| array[i] = i + firstGlyph; |
| } |
| PathGlyphsNV(firstPathName, fontTarget, fontName, fontStyle, |
| numGlyphs, INT, array, |
| handleMissingGlyphs, pathParameterTemplate, emScale); |
| free(array); |
| } else { |
| // generate OUT_OF_MEMORY error |
| } |
| |
| PATH GLYPHS FROM GLYPH INDEX RANGE |
| |
| Advanced shaping of text renders glyphs by per-font glyph indices |
| (rather than Unicode code point). The commands |
| |
| enum PathGlyphIndexArrayNV(uint firstPathName, |
| enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint firstGlyphIndex, |
| sizei numGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| |
| enum PathMemoryGlyphIndexArrayNV(uint firstPathName, |
| enum fontTarget, |
| sizeiptr fontSize, |
| const void *fontData, |
| sizei faceIndex, |
| uint firstGlyphIndex, |
| sizei numGlyphs, |
| uint pathParameterTemplate, |
| float emScale); |
| |
| create, if successful and no error occurs, a range of path objects |
| that correspond to an array of glyphs as ordered by glyph index in |
| a font face. PathGlyphIndexArrayNV loads the font data from a file |
| name or system font name while PathMemoryGlyphIndexArrayNV loads |
| the font data from a standard font format in system memory. |
| |
| The commands return the value FONT_GLYPHS_AVAILABLE_NV when |
| successful; otherwise one of the following values is returned |
| depending on the nature of the failure. The unsuccessful command |
| returns the value FONT_TARGET_UNAVAILABLE_NV if the implementation |
| does not support a valid /fontTarget/, FONT_UNAVAILABLE_NV if |
| the font is not available (e.g. does not exist on the system), or |
| FONT_UNINTELLIGIBLE_NV if the font is available but cannot be loaded |
| for some implementation-dependent reason. FONT_UNAVAILABLE_NV will |
| not be returned by PathMemoryGlyphIndexArrayNV because the font |
| data is read from system memory. If the command generates an error, |
| that error's enum value will be returned. For example, an invalid |
| value for /fontTarget/ will return INVALID_ENUM. While the return |
| value indicates the error, the error will /also/ be generated in the |
| conventional way so GetError will return it and error callbacks are |
| generated normally. |
| |
| When successful, path names /firstPathName/ through |
| /firstPathName+numGlyphs-1/ now are specified as path objects |
| corresponding to the sequence of glyphs in the font indicated |
| by /fontTarget/, /fontSize/, and /fontData/ for glyph indices |
| from /firstGlyphIndex/ to /firstGlyphIndex+numGlyphs-1/ where |
| /firstPathName/ corresponds to the glyph index /firstGlyphIndex/ |
| and onward sequentially. If a glyph index does not correspond to an |
| actual glyph index in the font format, the respective path object is |
| left undisturbed. (It is the application's responsibility to know |
| the valid range of glyph indices for the font.) When unsuccessful |
| other than due to an OUT_OF_MEMORY error, no path objects are |
| specified or otherwise modified. |
| |
| The path objects are created in the same manner described for |
| PathGlyphsNV in section 5.X.1.3 (Font Glyph Path Specification) |
| except the GLYPH_HAS_KERNING_BIT_NV and FONT_HAS_KERNING_BIT_NV |
| metrics are always false (because GetPathSpacingNV applies to |
| glyphs specified from Unicode code points). In particular, the |
| /pathParameterTemplate/ and /emScale/ parameters have the same |
| interpretation as the PathGlyphsNV command. |
| |
| For the PathGlyphIndexArrayNV command, the /fontTarget/ parameter |
| must be either SYSTEM_FONT_NAME_NV or FILE_NAME_NV; otherwise the |
| INVALID_ENUM error is generated. The /fontStyle/ parameter is |
| a bitfield allowed to have the bits BOLD_BIT_NV or ITALIC_BIT_NV |
| set; if other bits are set, the INVALID_VALUE error is generated. |
| The interpretation of the /fontTarget/, /fontName/, and /fontStyle/ |
| parameters is identical to the interpretation described in section |
| 5.X.1.3 (Font Glyph Path Specification). |
| |
| For the PathMemoryGlyphIndexArrayNV command, /fontTarget/ must |
| be STANDARD_FONT_FORMAT_NV; otherwise INVALID_ENUM is generated |
| (and returned). STANDARD_FONT_FORMAT_NV implies: /fontSize/ is |
| the size of the memory storing the font data in memory; /fontData/ |
| is a pointer to the beginning of the font data; and /faceIndex/ is |
| the index of the face within the font, typically specified as zero. |
| |
| The specific standard font formats supported by |
| STANDARD_FONT_FORMAT_NV are implementation-dependent, but the TrueType |
| format should be supported. Magic numbers if the font memory data |
| are expected to be used to identify the specific font format. |
| |
| The INVALID_VALUE error is generated if any of /fontSize/ or |
| /faceIndex/ or /emScale/ are negative. |
| |
| [NOTE: PathGlyphIndexRangeNV is deprecated in favor of |
| PathGlyphIndexArrayNV and PathMemoryGlyphIndexArrayNV.] |
| |
| The command |
| |
| enum PathGlyphIndexRangeNV(enum fontTarget, |
| const void *fontName, |
| bitfield fontStyle, |
| uint pathParameterTemplate, |
| float emScale, |
| uint baseAndCount[2]); |
| |
| creates, if successful and no error occurs, a range of path objects |
| that correspond to the complete range of glyphs as ordered by glyph |
| index in a font face. |
| |
| The command returns the value FONT_GLYPHS_AVAILABLE_NV when |
| successful; otherwise one of the following values is returned |
| depending on the nature of the failure. The unsuccessful command |
| returns the value FONT_TARGET_UNAVAILABLE_NV if the implementation |
| does not support a valid /fontTarget/, FONT_UNAVAILABLE_NV if |
| the font is not available (e.g. does not exist on the system), or |
| FONT_UNINTELLIGIBLE_NV if the font is available but cannot be loaded |
| for some implementation-dependent reason. If the command generates |
| an error, that error's enum value will be returned. For example, an |
| invalid value for /fontTarget/ will return INVALID_ENUM. While the |
| return value indicates the error, the error will /also/ be generated |
| in the conventional way so GetError will return it and error callbacks |
| are generated normally. |
| |
| The /fontTarget/ parameter must be either SYSTEM_FONT_NAME_NV |
| or FILE_NAME_NV; otherwise the INVALID_ENUM error is generated. |
| The interpretation of the /fontTarget/ and /fontName/ parameters |
| is identical to the interpretation described in section 5.X.1.3 |
| (Font Glyph Path Specification). |
| |
| The error INVALID_VALUE is generated if /emScale/ is negative. |
| |
| The /fontStyle/ parameter is a bitfield allowed to have the |
| bits BOLD_BIT_NV or ITALIC_BIT_NV set; if other bits are set, the |
| INVALID_VALUE error is generated. |
| |
| When successful, elements 0 and 1 of the /baseAndCount/ array |
| parameter are written values /B/ and /N/ respectively where the |
| path names /B/ through /B+N-1/ are previously unused (i.e. there |
| are /N/ previously unused path object names starting at /B/) but |
| now are specified as path objects corresponding to the complete set |
| of glyphs in the font indicated by /fontTarget/ and /fontName/. |
| When unsuccessful (including when any error, even OUT_OF_MEMORY, |
| is generated by the command), elements 0 and 1 of the /baseAndCount/ |
| array parameter are both written to zero. |
| |
| The path objects are created in the same manner described for |
| PathGlyphsNV in section 5.X.1.3 (Font Glyph Path Specification) |
| except the GLYPH_HAS_KERNING_BIT_NV and FONT_HAS_KERNING_BIT_NV |
| metrics are always false (because GetPathSpacingNV applies to |
| glyphs specified from Unicode code points). In particular, the |
| /pathParameterTemplate/ and /emScale/ parameters have the same |
| interpretation as the PathGlyphsNV command. |
| |
| 5.X.1.4 Path Modification |
| |
| Several commands allow the commands and/or coordinates of an existing |
| path object to be modified. |
| |
| The command |
| |
| void PathCoordsNV(uint path, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| replaces all the coordinates of an existing path object with a new |
| set of coordinates. /path/ names the path object to modify; the |
| error INVALID_OPERATION is generated if /path/ is not an existing |
| path object. |
| |
| The new path coordinates are read sequentially from the |
| /coords/ array. The type of the coordinates read from the /coords/ |
| array is determined by the /coordType/ parameter which must be |
| one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT, |
| otherwise the INVALID_ENUM error is generated. |
| |
| The INVALID_OPERATION error is generated if /numCoords/ does not |
| equal the number of coordinates referenced by the path object's |
| existing command sequence (so /numCoords/ provides a sanity check |
| that the /coords/ array is being interpreted properly). The error |
| INVALID_VALUE is generated if /numCoords/ is negative. |
| |
| If the PathCoordsNV command results in an error, the path object named |
| /path/ is not changed; if there is no error, the prior coordinates of |
| /path/ are lost. If there is no error, the commands and parameters |
| of the path object are not changed. |
| |
| The command |
| |
| void PathSubCoordsNV(uint path, |
| sizei coordStart, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| replaces a range of the coordinates of an existing path object with |
| a new set of coordinates. /path/ names the path object to modify; |
| the error INVALID_OPERATION is generated if /path/ is not an existing |
| path object. |
| |
| The new path coordinates are read sequentially from the |
| /coords/ array. The type of the coordinates read from the /coords/ |
| array is determined by the /coordType/ parameter which must be |
| one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, or FLOAT, |
| otherwise the INVALID_ENUM error is generated. |
| |
| The coordinates from the /coords/ array replace the coordinates |
| starting at coordinate index (zero-based) /coordStart/ through |
| /coordStart/+/numCoords/-1 inclusive in the existing path object's |
| coordinate array. If /numCoords/ is zero, no coordinates are changed. |
| If /coordStart/+/numCoords/ is greater than the number of coordinates |
| in the existing path object, the INVALID_OPERATION error is generated. |
| If either /coordStart/ or /numCoords/ is negative, the INVALID_VALUE |
| error is generated. |
| |
| If the PathCoordsNV command results in an error, the path object named |
| /path/ is not changed; if there is no error, the prior coordinates |
| within the updated range of /path/ are lost. If there is no error, |
| the commands, coordinates outside the updated range, and parameters |
| of the path object are not changed. |
| |
| The command |
| |
| void PathSubCommandsNV(uint path, |
| sizei commandStart, sizei commandsToDelete, |
| sizei numCommands, const ubyte *commands, |
| sizei numCoords, enum coordType, |
| const void *coords); |
| |
| replaces a range of existing commands and their associated coordinates |
| with a new sequence of commands and associated coordinates. /path/ |
| names the path object to modify; the error INVALID_OPERATION is |
| generated if /path/ is not an existing path object. |
| |
| The error INVALID_OPERATION is generated if any of /commandStart/, |
| /commandsToDelete/, /numCommands/, or /numCoords/ is negative. |
| |
| The PathSubCommandsNV command works in two steps. |
| First, deleting commands in the range /commandStart/ to |
| /commandStart/+/commandsToDelete/-1 inclusive from the existing |
| path object. If /commandsToDelete/ exceeds the number of commands |
| from /commandStart/ to the end of the path command sequence, |
| all the commands from /commandsToDelete/ on are deleted. This |
| includes deleting the coordinates associated with these commands. |
| If /commandsToDelete/ is zero, zero commands and zero coordinates are |
| deleted. Second, /numCommands/ read sequentially from the /commands/ |
| array are inserted into the existing path object immediately before |
| index /commandStart/. This includes inserting a corresponding number |
| of coordinates from the /coords/ array. If the index /commandStart/ |
| is greater than the largest valid command index of the path object, |
| the commands are simply appended to the end of the path objects |
| command and coordinate sequences. |
| |
| Each of the /numCommands/ commands in the /command/ array references |
| a number of coordinates specified by "Coordinate count" column of |
| Table 5.pathCommands, starting with the first (zero) element of |
| the /coords/ array and advancing by the coordinate count for each |
| command. If any of these /numCommands/ commands are not listed |
| in the "Token" or "Character aliases" columns of Table 5.pathCommands, |
| the INVALID_ENUM error is generated. |
| |
| The INVALID_OPERATION error is generated if /numCoords/ does not equal |
| the number of coordinates referenced by the command sequence to insert |
| as specified by /numCommands/ and /commands/ (so /numCoords/ provides |
| a sanity check that the /coords/ array is being interpreted properly). |
| The error INVALID_VALUE is generated if any of /commandStart/, |
| /commandsToDelete/, /numCommands/ or /numCoords/ are negative. |
| |
| The type of the coordinates in the /coords/ array is specified |
| by /coordType/ and must be one of BYTE, UNSIGNED_BYTE, SHORT, |
| UNSIGNED_SHORT, or FLOAT; otherwise the INVALID_ENUM error is |
| generated. |
| |
| If the PathSubCommandsNV command results in an error, the path |
| object named /path/ is not changed; if there is no error, the prior |
| (now deleted) commands and coordinates within the updated range of |
| /path/ are lost. If there is no error, the commands, coordinates |
| outside the deleted range, and parameters of the path object are not |
| changed though commands and coordinates indexed beyond /commandStart/ |
| are shifted in their sequence within the path object to make room |
| in the command and coordinate arrays for the newly inserted commands |
| and coordinates. |
| |
| 5.X.1.5 Path Parameter Specification |
| |
| Each path object has its own set of path parameters that control |
| how the path object is filled and stroked when stenciled and covered. |
| |
| Table 5.pathParameters |
| |
| Name Type Required Values or Range |
| ------------------------------- ------- ----------------------------------------------- |
| PATH_STROKE_WIDTH_NV float non-negative |
| PATH_INITIAL_END_CAP_NV enum FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV |
| PATH_TERMINAL_END_CAP_NV enum FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV |
| PATH_INITIAL_DASH_CAP_NV enum FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV |
| PATH_TERMINAL_DASH_CAP_NV enum FLAT, SQUARE_NV, ROUND_NV, TRIANGULAR_NV |
| PATH_JOIN_STYLE_NV enum MITER_REVERT_NV, MITER_TRUNCATE_NV, BEVEL_NV, ROUND_NV, NONE |
| PATH_MITER_LIMIT_NV float non-negative |
| PATH_DASH_OFFSET_NV float any value |
| PATH_DASH_OFFSET_RESET_NV enum MOVE_TO_RESET_NV, MOVE_TO_CONTINUES_NV |
| PATH_CLIENT_LENGTH_NV float non-negative |
| PATH_FILL_MODE_NV enum COUNT_UP_NV, COUNT_DOWN_NV, INVERT |
| PATH_FILL_MASK_NV integer any value |
| PATH_FILL_COVER_MODE_NV enum CONVEX_HULL_NV, BOUNDING_BOX_NV |
| PATH_STROKE_COVER_MODE_NV enum CONVEX_HULL_NV, BOUNDING_BOX_NV |
| PATH_STROKE_MASK_NV integer any value |
| PATH_STROKE_BOUND_NV float any value in [0.0,1.0] |
| |
| The commands |
| |
| void PathParameterivNV(uint path, enum pname, const int *value); |
| void PathParameteriNV(uint path, enum pname, int value); |
| void PathParameterfvNV(uint path, enum pname, const float *value); |
| void PathParameterfNV(uint path, enum pname, float value); |
| |
| specify the value of path parameters for the specified path object |
| named /path/. The error INVALID_OPERATION is generated if /path/ |
| is not an existing path object. |
| |
| Each parameter has a single (scalar) value. |
| |
| /pname/ must be one of the tokens in the "Name" column of |
| Table 5.pathParameters, PATH_END_CAPS_NV, or PATH_DASH_CAPS_NV. |
| The required values or range of each allowed parameter name token |
| is listed in Table 5.pathParameter's "Required Values/Range" column. |
| |
| For values of /pname/ listed in Table 5.pathsParameters, the specified |
| parameter is specified by /value/ when /value/ is a float or int, |
| or if /value/ is a pointer to a float or int, accessed through that |
| pointer. The error INVALID_VALUE is generated if the specified |
| value is negative for parameters required to be non-negative in |
| Table 5.pathParameters. Values specified to be clamped to the [0,1] range |
| in Table 5.pathParameters are so clamped prior to setting the |
| specified path parameter to that clamped value. |
| |
| The /pname/ of PATH_END_CAPS_NV is handled specially and updates |
| /both/ the PATH_INITIAL_END_CAP_NV and PATH_TERMINAL_END_CAP_NV |
| parameters of the path with the specified value. The /pname/ |
| of PATH_DASH_CAPS_NV is handled specially and updates /both/ the |
| PATH_INITIAL_DASH_CAP_NV and PATH_TERMINAL_DASH_CAP_NV parameters |
| of the path with the specified value. |
| |
| The error INVALID_VALUE is generated if the specified parameter value |
| is not within the require range for parameters typed float or integer. |
| The error INVALID_ENUM is generated if the specified parameter value |
| is not one of the listed tokens for parameters typed enum. |
| |
| The dash pattern of a path object consists of a sequence of path-space |
| lengths of alternating "on" and "off" dash segments. The first |
| value of the dash array defines the length, in path space, of the |
| first "on" dash segment. The second value defines the length of the |
| following "off" segment. Each subsequent pair of values defines one |
| "on" and one "off" segment. |
| |
| Parameters to control the dash pattern of a stroked path are specified |
| by the command |
| |
| void PathDashArrayNV(uint path, |
| sizei dashCount, const float *dashArray); |
| |
| where /path/ is the name of an existing path object. The error |
| INVALID_OPERATION is generated if /path/ is not an existing path |
| object. |
| |
| A /dashCount/ of zero indicates the path object is not dashed; in |
| this case, the /dashArray/ is not accessed. Otherwise, /dashCount/ |
| provides a count of how many float values to read from the /dashArray/ |
| array. If any of the /dashCount/ elements of /dashArray/ are |
| negative, the INVALID_VALUE error is generated. |
| |
| If /dashCount/ is negative, the INVALID_VALUE error is generated. |
| |
| If an error occurs, the path object's existing dash pattern state |
| is not changed. |
| |
| The path parameters of a newly specified path object are initialized |
| as specified in Table 6.Y. |
| |
| 5.X.1.6 Path Weighting, Interpolation, and Copying |
| |
| The command |
| |
| void WeightPathsNV(uint resultPath, |
| sizei numPaths, |
| const uint paths[], const float weights[]); |
| |
| linearly combines, as appropriate, the /numPaths/ path objects in |
| the array paths based on each path object's respective weight from |
| the weights array. The resulting path creates or replaces the |
| path object /resultPath/. The INVALID_VALUE error is generated if |
| /numPaths/ is less than one. |
| |
| If the /resultPath/ name also names one of the paths in the /paths/ |
| array, the path resulting from the linear combination of paths |
| replaces the source path also named /resultPath/ but not until after |
| the linear combination path has been determined. |
| |
| This command requires all the paths in the paths array to |
| be /consistent/; otherwise the INVALID_OPERATION error is |
| generated. For all the paths to be /consistent/, all /numPaths/ paths |
| in the /paths/ array must have the identical count of commands and |
| each corresponding /i/th command in each path must have the identical |
| command type. |
| |
| However the arc commands (specifically SMALL_CCW_ARC_TO_NV, |
| RELATIVE_SMALL_CCW_ARC_TO_NV, SMALL_CW_ARC_TO_NV, |
| RELATIVE_SMALL_CW_ARC_TO_NV, LARGE_CCW_ARC_TO_NV, |
| RELATIVE_LARGE_CCW_ARC_TO_NV, LARGE_CW_ARC_TO_NV, |
| RELATIVE_LARGE_CW_ARC_TO_NV, CIRCULAR_CCW_ARC_TO_NV, |
| CIRCULAR_CW_ARC_TO_NV, CIRCULAR_TANGENT_ARC_TO_NV, ARC_TO_NV, and |
| RELATIVE_ARC_TO_NV) can not be weighted because the linear combination |
| of the curves these arc commands generate do not generally result in |
| a command of the same form; so if any of these arc commands appears |
| in a path object passed to WeightPathsNV the INVALID_OPERATION error |
| is generated. |
| |
| The weighted path has a command sequence identical to any of the |
| input path objects to be weighted (since all the input path command |
| sequences are required to be identical). |
| |
| The weighted path has a coordinate sequence constructed by weighting |
| each correspondingly indexed coordinate /i/ for all paths indexed by |
| /j/ from zero to /numPaths/-1 in the /paths/ array. Each coordinate |
| /i/ from path /j/ is weighted by the weight in /weights/ indexed |
| by /j/. |
| |
| The path parameters for the weighted path are copied from the path |
| named by the first (0th) element of the /paths/ array. The path |
| metric values (as queried by GetPathMetricsNV in section 6.X.3) |
| are all specified to be -1 for the newly specified path object |
| (ignoring the path metrics for all the input path objects). |
| Kerning information (as queriable by GetPathSpacingNV in section |
| 6.X.3) is also not copied. |
| |
| The command |
| |
| void InterpolatePathsNV(uint resultPath, |
| uint pathA, uint pathB, |
| float weight); |
| |
| is equivalent to |
| |
| uint paths[2] = { pathA, pathB }; |
| float weights[2] = { 1-weight, weight }; |
| WeightPathsNV(resultPath, 2, paths, weights); |
| |
| The command |
| |
| void CopyPathNV(uint resultPath, uint srcPath); |
| |
| copies the path object named /srcPath/ to the path object named |
| /resultPath/. The error INVALID_OPERATION is generated if /srcPath/ |
| does not exist. The outline (commands and coordinates), parameters, |
| and glyph metrics and kerning information (if they exist) are all |
| copied without change. |
| |
| 5.X.1.7 Path Transformation |
| |
| The command |
| |
| void TransformPathNV(uint resultPath, |
| uint srcPath, |
| enum transformType, |
| const float *transformValues); |
| |
| transforms the path object named /srcPath/ by the transform specified |
| by the /transformType/ and its associated /transformValues/. |
| The resulting path creates or replaces the path object /resultPath/. |
| |
| If the /resultPath/ and /srcPath/ names are identical, the path resulting |
| from the transform replaces the name after the source path is transformed. |
| |
| The /transformType/ must be one of NONE, TRANSLATE_X_NV, |
| TRANSLATE_Y_NV, TRANSLATE_2D_NV, TRANSLATE_3D_NV, AFFINE_2D_NV, |
| AFFINE_3D_NV, TRANSPOSE_AFFINE_2D_NV, or TRANSPOSE_AFFINE_3D_NV. |
| |
| transformType Matrix |
| -------------------------- ------------------------- |
| NONE [ 1 0 0 0 ] |
| [ 0 1 0 0 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| TRANSLATE_X_NV [ 1 0 0 v0 ] |
| [ 0 1 0 0 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| TRANSLATE_Y_NV [ 1 0 0 0 ] |
| [ 0 1 0 v0 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| TRANSLATE_2D_NV [ 1 0 0 v0 ] |
| [ 0 1 0 v1 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| TRANSLATE_3D_NV [ 1 0 0 v0 ] |
| [ 0 1 0 v1 ] |
| [ 0 0 1 v2 ] |
| [ 0 0 0 1 ] |
| |
| AFFINE_2D_NV [ v0 v2 0 v4 ] |
| [ v1 v3 0 v5 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| TRANSPOSE_AFFINE_2D_NV [ v0 v1 0 v2 ] |
| [ v3 v4 0 v5 ] |
| [ 0 0 1 0 ] |
| [ 0 0 0 1 ] |
| |
| AFFINE_3D_NV [ v0 v3 v6 v9 ] |
| [ v1 v4 v7 v10 ] |
| [ v2 v5 v8 v11 ] |
| [ 0 0 0 1 ] |
| |
| TRANSPOSE_AFFINE_3D_NV [ v0 v1 v2 v3 ] |
| [ v4 v5 v6 v7 ] |
| [ v8 v9 v10 v11 ] |
| [ 0 0 0 1 ] |
| |
| Table 5.transformType: Mapping from /transformType/ to a 4x4 |
| transform matrix where v/i/ is the ith (base 0) element of the |
| /transformValues/ array. |
| |
| The transformation of a path proceeds path command by path command. |
| Each path command results in a transformed path command equivalent |
| to what would happen if every point on the path command segment were |
| transformed by the transform from Table 5.transformType and had a |
| projective normalization applied. |
| |
| Commands with absolute control points have their control points |
| transformed by the effective 4x4 projective matrix, and the resulting |
| x & y coordinates serve as the transformed command's respective |
| control point. |
| |
| Control points of relative commands are first made into absolute |
| coordinates given the command's current control point, transformed |
| in the same manner as an absolute control point, and then adjusted |
| back to relative to their transformed current control point. |
| |
| Horizontal and vertical line to commands are promoted to corresponding |
| "line to" commands if the transformed command is not an exactly |
| horizontal or vertical command respectively after transformation; |
| otherwise, these commands are not promoted but may transition from |
| horizontal to vertical or vice versa as the case may be. |
| |
| Commands for partial elliptical arcs generate an equivalent new |
| transformed arc. |
| |
| XXX more detail/math about arcs? |
| |
| The CIRCULAR_CCW_ARC_TO_NV and CIRCULAR_CW_ARC_TO_NV commands are |
| converted to transformed *_ARC_TO_NV commands if the transformed |
| circular arc is itself not a circular arc. |
| |
| The CIRCULAR_TANGENT_ARC_TO_NV command is converted into a LINE_TO_NV |
| command and *_ARC_TO_NV command if the transformed circular arc is |
| itself not a circular arc. |
| |
| The CLOSE_PATH_NV and RESTART_PATH_NV (having no control points) |
| are undisturbed by path transformation. The order of path commands |
| is invariant under path transformation. |
| |
| 5.X.1.8 Path Name Management |
| |
| The command |
| |
| uint GenPathsNV(sizei range); |
| |
| returns an integer /n/ such that names /n/, ..., /n+range-1/ are |
| previously unused (i.e. there are /range/ previously unused path object |
| names starting at /n/). These names are marked as used, for the |
| purposes of subsequent GenPathsNV only, but they do not acquire |
| path object state until each particular name is used to specify |
| a path object. |
| |
| Path objects are deleted by calling |
| |
| void DeletePathsNV(uint path, sizei range); |
| |
| where /path/ contains /range/ names of path objects to be delete. |
| After a path object is deleted, its name is again unused. Unused |
| names in /paths/ are silently ignored. |
| |
| The query |
| |
| boolean IsPathNV(uint path); |
| |
| returns TRUE if /path/ is the name of a path object. If path is |
| not the name of a path object, or if an error condition occurs, |
| IsPathNV returns FALSE. A name retuned by GenPathsNV, but without |
| a path specified for it yet, is not the name of a path object. |
| |
| 5.X.2 Path Rendering |
| |
| Path objects update the framebuffer through one of two processes: |
| "stenciling" that updates /just/ the stencil buffer with the path's |
| coverage information, and "covering" that rasterizes fragments into |
| the framebuffer for a region guaranteed to cover the region of path |
| coverage updated by stenciling, assuming the same path object, |
| fill mode or stroking parameters, transformation state, and set of |
| accessible samples (as will be explained). |
| |
| 5.X.2.1 Path Stenciling |
| |
| STENCILING FILLED PATHS |
| |
| The command |
| |
| void PathStencilFuncNV(enum func, int ref, uint mask); |
| |
| configures the stencil function, stencil reference value, and stencil |
| read mask to be used by the StencilFillPathNV and StencilStrokePathNV |
| commands described subsequently. The parameters accept the same |
| values allowed by the StencilFunc command. |
| |
| The command |
| |
| void PathStencilDepthOffsetNV(float factor, float units); |
| |
| configures the depth offset factor and units state (see section 3.6.4) |
| to be used by the StencilFillPathNV and StencilStrokePathNV commands |
| described subsequently. |
| |
| The command |
| |
| void StencilFillPathNV(uint path, |
| enum fillMode, uint mask); |
| |
| transforms into window space the outline of the path object named |
| /path/ based on the current modelview, projection, viewport, |
| and depth range transforms (ignoring any vertex and/or geometry |
| shader or program that might be active/enabled) and then updates |
| the stencil values of all /accessible samples/ (explained below) in |
| the framebuffer. Each sample's stencil buffer value is updated based |
| on the winding number of that sample with respect to the transformed |
| outline of the path object with any non-closed subpath forced closed |
| and the specified /fillMode/. |
| |
| If /path/ does not name an existing path object, the command does |
| nothing (and no error is generated). |
| |
| If the path's command sequence specifies unclosed subpaths (so not |
| contours) due to MOVE_TO_NV commands, such subpaths are trivially |
| closed by connecting with a line segment the initial and terminal |
| control points of each such path command subsequence. |
| |
| Transformation of a path's outline works by taking all positions |
| on the path's outline in 2D path space (x,y) and constructing an |
| object space position (x,y,0,1) that is then used as the (xo,yo,zo,wo) |
| position in section 2.12 ("Fixed-Function Vertex Transformation") |
| to compute corresponding eye-space coordinates (xe,ye,ze,we) and |
| clip-space coordinates (xc,yc,zc,wc). A path outline's clip-space |
| coordinates are further transformed into window space as described in |
| section 2.16 ("Coordinate Transformations"). This process provides a |
| mapping 2D path coordinates to 2D window coordinates and depth values. |
| The resulting 2D window coordinates are undefined if any of the |
| transformations involved are singular or may be inaccurate if any |
| of the transformations (or their combination) are ill-conditioned. |
| |
| The winding number for a sample with respect to the path outline, |
| transformed into window space, is computed by counting the (signed) |
| number of revolutions around the sample point when traversing each |
| (trivially closed if necessary) contour once in the transformed path. |
| This traversal is performed in the order of the path's command |
| sequence. Starting from an initially zero winding count, each |
| counterclockwise revolution when the front face mode is CCW (or |
| clockwise revolution when the front face mode is CW) around the sample |
| point increments the winding count by one; while each clockwise |
| revolution when the front face mode is CCW (or counterclockwise |
| revolution when the front face mode is CW) around the sample point |
| decrements the winding count by one. |
| |
| The /mask/ parameter controls what subset of stencil bits are affected |
| by the command. If the /mask/ parameter is zero, the path object's |
| fill mask parameter (PATH_FILL_MASK_NV) is considered the effective |
| value of /mask/. |
| |
| The /fillMode/ parameter must be one of INVERT, COUNT_UP_NV, |
| COUNT_DOWN_NV, or PATH_FILL_MODE_NV; otherwise the INVALID_ENUM error |
| is generated. INVERT inverts the bits set in the effective /mask/ |
| value for each sample's stencil value if the winding number for the |
| given sample is odd. COUNT_UP_NV adds with modulo n arithmetic the |
| winding number of each sample with the sample's prior stencil buffer |
| value; the result of this addition is written into the sample's |
| stencil value but the bits of the stencil value not set in the |
| effective /mask/ value are left unchanged. COUNT_DOWN_NV subtracts |
| with modulo /n/ arithmetic the winding number of each sample with the |
| sample's prior stencil buffer value; the result of this subtraction is |
| written into the sample's stencil value but the bits of the stencil |
| value not set in the effective /mask/ value are left unchanged. |
| PATH_FILL_MODE_NV uses the path object's counting mode parameter |
| (one of INVERT, COUNT_UP_NV, or COUNT_DOWN_NV). |
| |
| The value of /n/ for the modulo /n/ arithmetic used by COUNT_UP_NV |
| and COUNT_DOWN_NV is the effective /mask/+1. The error INVALID_VALUE |
| is generated if the specified /fillMode/ is COUNT_UP_NV or |
| COUNT_DOWN_NV and the specified /mask/+1 is not an integer power |
| of two. If the /fillMode/ is PATH_FILL_MODE_NV; the path object's |
| counting mode parameter is COUNT_UP_NV or COUNT_DOWN_NV; and the |
| effective mask+1 value is not an integer power of two, treat the |
| mask as zero (effectively meaning no stencil bits will be modified). |
| |
| ACCESSIBLE SAMPLES WITH RESPECT TO A TRANSFORMED PATH |
| |
| The accessible samples of a transformed path that are updated are |
| the samples that remain after discarding the following samples: |
| |
| * Any sample that would be clipped as specified in section 2.22 |
| ("Primitive Clipping") because its corresponding position in |
| clip space (xc,yc,zc,wc) or (xe,ye,ze,we) would be clipped |
| by the clip volume or enabled client-defined clip planes. |
| |
| * Any sample that would not be updated during polygon rendering |
| due to polygon stipple (section 3.6.2) if POLYGON_STIPPLE |
| is enabled. |
| |
| * Any sample that would fail the pixel ownership test (section |
| 4.1.1) if rasterized. |
| |
| * Any sample that would fail the scissor test (section 4.1.2) |
| if SCISSOR_TEST is enabled. |
| |
| * Any sample that would fail the depth test (section 4.1.6) |
| if DEPTH_TEST is enabled where the fragment depth for the |
| depth test comes from the depth plane of the path when |
| transformed by the modelview, projection, viewport, and |
| depth range transforms and depth offset (section 3.6.4) |
| has been applied based on the slope of this plane operating |
| as if POLYGON_OFFSET_FILL is forced enabled and using the |
| factor and units parameters set by PathStencilDepthOffsetNV |
| (rather than the state set by PolygonOffset). |
| |
| * Any sample that would fail the depth bounds test (section |
| 4.1.X in EXT_depth_bounds_test specification) if |
| DEPTH_BOUNDS_TEST_EXT is enabled. |
| |
| And for the StencilFillPathNV and StencilStrokePathNV commands (so |
| not applicable to the CoverFillPathNV and CoverStrokePathNV commands): |
| |
| * Any sample that would fail the (implicitly enabled) stencil |
| test (section 4.1.5) with the stencil function configured |
| based on the path stencil function state configured by |
| PathStencilFuncNV. In the case of the StencilFillPathNV |
| and StencilStrokePathNV commands and their instanced |
| versions (section 5.X.2.3), the effective stencil read |
| mask for the stencil mask is treated as the value of |
| PATH_STENCIL_VALUE_MASK bit-wise ANDed with the bit-invert |
| of the effective /mask/ parameter value; otherwise, for the |
| cover commands, the stencil test operates normally. In the |
| case the stencil test fails during a path stencil operation, |
| the stencil fail operation is ignored and the pixel's stencil |
| value is left undisturbed (as if the stencil operation was |
| KEEP). |
| |
| * The state of the face culling (CULL_FACE) enable is ignored. |
| |
| STENCILING STROKED PATHS |
| |
| The command |
| |
| void StencilStrokePathNV(uint path, |
| int reference, uint mask); |
| |
| transforms into window space the stroked region of the path object |
| named /path/ based on the current modelview, projection, viewport, |
| and depth range transforms (ignoring any vertex and/or geometry |
| shader or program that might be active/enabled) and then updates |
| the stencil values of a subset of the accessible samples (see above) |
| in the framebuffer. |
| |
| If /path/ does not name an existing path object, the command does |
| nothing (and no error is generated). |
| |
| The path object's stroke width parameter (PATH_STROKE_WIDTH_NV) in |
| path space units determines the width of the path's stroked region. |
| |
| When the dash array count of a path object is zero (dashing is |
| considered subsequently), the stroke of a transformed path's outline |
| is the region of window space defined by the union of: |
| |
| * Sweeping an orthogonal centered line segment of the (above |
| determined) effective stroke width along each path segment |
| in the path's transformed outline. |
| |
| * End cap regions (explained below) appended to the initial |
| and terminal control points of non-closed command sequences |
| in the path. For a sequence of commands that form a closed |
| contour, the end cap regions are ignored. |
| |
| * Join style regions (explained below) between connected path |
| segments meet. |
| |
| Any accessible samples within the union of these three regions are |
| considered within the path object's stroke. |
| |
| The /mask/ parameter controls what subset of stencil bits are affected |
| by the command. If the /mask/ parameter is zero, the path object's |
| stroke mask parameter (PATH_STROKE_MASK_NV) is considered the effective |
| value of /mask/. |
| |
| A sample's stencil bits that are set in the effective /mask/ value |
| are updated with the specified stencil /reference/ value if the |
| sample is accessible (as specified above) and within the stroke of |
| the transformed path's outline. |
| |
| Every path object has an initial and terminal end cap parameter |
| (PATH_INITIAL_END_CAP_NV and PATH_TERMINAL_END_CAP_NV) that is |
| one of FLAT, SQUARE_NV, ROUND_NV, or TRIANGULAR_NV. There are no |
| samples within a FLAT end cap. The SQUARE_NV cap extends centered |
| and tangent to the given end (initial or terminal) of the subpath |
| for half the effective stroke width; in other words, a square cap |
| is a half-square that kisses watertightly the end of a subpath. |
| The ROUND_NV cap appends a semi-circle, centered and tangent, |
| with the diameter of the effective stroke width to the given end |
| (initial or terminal) of the subpath; in other words, a round cap |
| is a semi-circle that kisses watertightly the end of a subpath. |
| The TRIANGULAR_NV cap appends a right triangle, centered and tangent, |
| with its hypotenuse flush to the given end of the subpath; in other |
| words, a triangular cap is a right triangle that kisses watertightly |
| the end of a subpath with the triangle's longest side. |
| |
| Every path object has a join style parameter (PATH_JOIN_STYLE_NV) |
| that is one of BEVEL_NV, ROUND_NV, MITER_REVERT_NV, MITER_TRUNCATE_NV, |
| or NONE; each path object also has a miter limit value. The BEVEL_NV |
| join style inserts a triangle with two vertices at the outside |
| corners where two connected path segments join and a third vertex at |
| the common end point shared by the two path segments. The ROUND_NV |
| join style inserts a wedge-shaped portion of a circle centered at |
| the common end point shared by the two path segments; the radius of |
| the circle is half the effective stroke width. There are no samples |
| within a NONE join style. The MITER_REVERT_NV join style inserts a |
| quadrilateral with two opposite vertices at the outside corners where |
| the two connected path segments join and two opposite vertices with |
| one on the path's junction between the two joining path segments and |
| the other at the common end point shared by the two path segments. |
| However, the MITER_REVERT_NV join style behaves as the BEVEL_NV |
| style if the sine of half the angle between the two joined segments |
| is less than the path object's PATH_STROKE_WIDTH value divided by |
| the path's PATH_MITER_LIMIT_NV value. The MITER_TRUNCATE_NV join |
| style is similar to MITER_REVERT_NV but rather than reverting to a |
| bevel when the miter limit is exceeded, instead the tip of the miter |
| quadrilateral is truncated such that the miter does not extend beyond |
| the miter limit. |
| |
| When the dash array count of a path object is /not/ zero, the path is |
| broken up into a sequence of paths based on the path object's dash |
| array count, dash array, dash offset, and dash cap parameters (see |
| section 5.X.1.5). This sequence of paths are handled as if their |
| dash count array is zero so their stroked region can be determined |
| for this stroking case that has already been explained. |
| |
| The dash pattern defined by the dash array is a sequence of lengths of |
| alternating "on" and "off" dash segments. The first (0th) element of |
| the dash array defines the length, in path space, of the first "on" |
| dash segment. The second value defines the length of the following |
| "off" segment. Each subsequent pair of values defines on "on" |
| and one "off" segment. |
| |
| The initial cap of the first dash segment uses the path's initial |
| dash cap style state (PATH_INITIAL_END_CAP_NV) as the effective |
| initial end cap for this first dash segment; the terminal cap |
| of the last dash segment uses the path's terminal dash cap style |
| state (PATH_TERMINAL_END_CAP_NV) as the effective terminal cap for |
| this last dash segment; all other caps of dash segments use the |
| PATH_INITIAL_DASH_CAP_NV for the initial cap of the segment and the |
| PATH_TERMINAL_DASH_CAP_NV for the terminal cap of the segment. |
| |
| The MOVE_TO_RESETS_NV value for a path's dash offset reset parameter |
| (PATH_DASH_OFFSET_RESET_NV) means that the dash offset resets to the |
| path's dash offset parameter upon a MOVE_TO_NV, RELATIVE_MOVE_TO_NV, |
| RESTART_PATH_NV, or RECT_NV command (an command that does an implicit |
| or explicit move-to) while dashing the path's command sequence. |
| The MOVE_TO_CONTINUES_NV value means that the dash pattern |
| progresses normally (without reset) when dashing a MOVE_TO_NV or |
| RELATIVE_MOVE_TO_NV command. |
| |
| Every path object has a stroke approximation bound parameter |
| (PATH_STROKE_BOUND_NV) that is a floating-point value /sab/ clamped |
| between 0.0 and 1.0 and set and queried with the PATH_STROKE_BOUND_NV |
| path parameter. Exact determination of samples swept an orthogonal |
| centered line segment along cubic Bezier segments and rational |
| quadratic Bezier curves (so non-circular partial elliptical arcs) is |
| intractable for real-time rendering so an approximation is required; |
| /sab/ intuitively bounds the approximation error as a percentage of |
| the path object's stroke width. Specifically, this path parameter |
| requests the implementation to stencil any samples within /sweep/ |
| object space units of the exact sweep of the path's cubic Bezier |
| segments or partial elliptical arcs to be sampled by the stroke where |
| |
| sweep = ((1-sab)*sw)/2 |
| |
| where /sw/ is the path object's stroke width. The initial value |
| of /sab/ when a path is created is 0.2. In practical terms, this |
| initial value means the stencil sample positions coverage within 80% |
| (100%-20%) of the stroke width of cubic and rational quadratic stroke |
| segments should be sampled. |
| |
| If the path object's client length parameter (PATH_CLIENT_LENGTH_NV) |
| value /clen/ is non-zero, prior to generating the dashed segments, the |
| dash pattern and dash offset lengths should be scaled by (multiplied |
| by) the clen/plen where /plen/ is the path object's computed length |
| (PATH_COMPUTED_LENGTH_NV). |
| |
| 5.X.2.2 Path Covering |
| |
| COVERING FILLED PATHS |
| |
| The command |
| |
| void PathCoverDepthFuncNV(enum zfunc); |
| |
| configures the depth function to be used by the CoverFillPathNV and |
| CoverStrokePathNV commands described subsequently. The /zfunc/ parameter |
| accepts the same values allowed by the DepthFunc command. |
| |
| The command |
| |
| void CoverFillPathNV(uint path, enum coverMode); |
| |
| transforms into window space the outline of the path object named |
| /path/ based on the current modelview, projection, viewport, |
| and depth range transforms (ignoring any vertex and/or geometry |
| shader or program that might be active/enabled) and rasterizes a |
| subset of the accessible samples in the framebuffer guaranteed to |
| include all samples that would be have a net stencil value change if |
| StencilFillPathNV were issued with the same modelview, projection, |
| and viewport state. During this rasterization, the stencil test |
| operates normally and as configured; the expectation is the stencil |
| test will be used to discard samples not determined "covered" by a |
| prior StencilFillPathNV command. The depth function, if DEPTH_TEST is |
| enabled, during this rasterization uses the function specified by |
| PathCoverDepthFuncNV (instead of the state specified by DepthFunc). |
| |
| If /path/ does not name an existing path object, the command does |
| nothing (and no error is generated). |
| |
| /coverMode/ must be one of CONVEX_HULL_NV, BOUNDING_BOX_NV, or |
| PATH_FILL_COVER_MODE_NV. The PATH_FILL_COVER_MODE_NV uses the path |
| object's PATH_FILL_COVER_MODE_NV parameter value as the effective |
| fill cover mode of the cover command. |
| |
| When /coverMode/ is CONVEX_HULL_NV or BOUNDING_BOX_NV, the subset |
| of accessible pixels that are rasterized are within a convex |
| hull or bounding box respectively (each expected to be reasonably |
| tight) surrounding all the samples guaranteed to be rasterized by |
| CoverFillPathNV. The bounding box must be orthogonally aligned |
| to the path space coordinate system. (The area of the bounding |
| box in path space is guaranteed to be greater than or equal the |
| area of the convex hull in path space.) Each rasterized sample |
| will be rasterized once and exactly once when CONVEX_HULL_NV or |
| BOUNDING_BOX_NV is specified. |
| |
| While samples with a net stencil change /must/ be rasterized, |
| implementations are explicitly allowed to vary in the rasterization |
| of samples for which StencilFillPathNV would /not/ change sample's |
| net stencil value. This means implementations are allowed to (and, |
| in fact, are expected to) conservatively "exceed" the region strictly |
| stenciled by the path object. |
| |
| CoverFillPathNV /requires/ the following rasterization invariance: |
| calling CoverFillPathNV for the same (unchanged) path object with |
| fixed (unchanged) modelview, projection, and viewport transform state |
| with the same (unchanged) set of accessible samples will rasterize |
| the exact same set of samples with identical interpolated values |
| for respective fragment/sample locations. |
| |
| COVERING STROKED PATHS |
| |
| The command |
| |
| void CoverStrokePathNV(uint path, enum coverMode); |
| |
| operates in the same manner as CoverFillPathNV except the region |
| guaranteed to be rasterized is, rather than the region within /path/'s |
| filled outline, instead the region within the /path/'s stroked region |
| as determined by StencilStrokePathNV. During this rasterization, |
| the stencil test operates normally and as configured; the expectation |
| is the stencil test will be used to discard samples not determined |
| "covered" by a prior StencilStrokePathNV command. As with CoverFillPathNV, |
| the depth function, if DEPTH_TEST is enabled, uses the function specified |
| by PathCoverDepthFuncNV. |
| |
| /coverMode/ must be one of CONVEX_HULL_NV, BOUNDING_BOX_NV, or |
| PATH_STROKE_COVER_MODE_NV. The PATH_STROKE_COVER_MODE_NV uses |
| the path object's PATH_STROKE_COVER_MODE_NV parameter value as the |
| effective stroke cover mode of the cover command. |
| |
| If /path/ does not name an existing path object, the command does |
| nothing (and no error is generated). |
| |
| Analogous to the rasterization guarantee of CoverFillPathNV with |
| respect to StencilFillPathNV, CoverStrokePathNV guarantees that all |
| samples rasterized by StencilStrokePathNV, given the same transforms |
| and accessible pixels and stroke width, will also be rasterized by |
| the corresponding CoverStrokePathNV. |
| |
| CoverStrokePathNV /requires/ the following rasterization invariance: |
| calling CoverStrokePathNV for the same (unchanged) path object with |
| fixed (unchanged) modelview, projection, and viewport transform |
| state and with the same (unchanged) set of accessible samples will |
| rasterize the exact same set of samples with identical interpolated |
| values for respective fragment/sample locations. |
| |
| PATH COVERING RASTERIZATION DETAILS |
| |
| The GL processes fragments rasterized by path cover commands in |
| much the same manner as fragments generated by conventional polygon |
| rasterization. However path rendering /ignores/ the following |
| operations: |
| |
| * Interpolation of per-vertex data (section 3.6.1). Path |
| primitives have neither conventional vertices nor per-vertex |
| data. Instead fragments generate interpolated per-fragment |
| colors, texture coordinate sets, and fog coordinates as a |
| linear function of object-space or eye-space path coordinate's |
| or using the current color, texture coordinate set, or fog |
| coordinate state directly. |
| |
| * Polygon smooth (section 3.6.3). |
| |
| * Polygon mode (section 3.6.4). Fragments generated by path |
| covering never result from point or line rasterizations. |
| |
| Polygon stippling (section 3.6.2), depth offset (section 3.6.5), and |
| polygon multisample rasterization (3.6.6) do apply to path covering. |
| |
| Front and back face determination (explained in section 3.6.1 for |
| polygons) operates somewhat differently for transformed paths than |
| polygons. The path's convex hull, bounding box, or multiple hulls |
| (depending on the /coverMode/) are specified to wind counterclockwise |
| in object space though the transformation of the convex hull into |
| window space could reverse this winding. Whether the GL's front face |
| state is CCW or CCW (as set by the FrontFace command) determines |
| if the path is front facing or not. Because the specific vertices |
| that belong to the covering geometry are implementation-dependent, |
| when the signed area of the covering geometry (computed with equation |
| 3.8) is sufficiently near zero, the facingness of the path in such |
| situations is ill-defined. |
| |
| The determination of whether a path transformed into window space is |
| front facing or not affects face culling if enabled (section 3.6.1), |
| the gl_FrontFacing built-in variable (section 3.12.22), and separate |
| (two-sided) stencil testing (section 4.1.5). |
| |
| Once fragments have been generated by path covering, the fragments |
| are shaded in the same manner as fragments generated by polygon |
| rasterization with the following exception: If a GLSL program is |
| in use, any vertex or geometry shader linked into the GLSL program |
| is ignored. The fragment shader operates normally except that |
| user-defined inputs to the fragment shader behave as specified by |
| ProgramPathFragmentInputGenNV. When supported, the fragment shader |
| could also use the built-in varying inputs: gl_Texcoord[i], |
| gl_Color, gl_SecondaryColor, and gl_FogFragCoord. |
| |
| COLOR GENERATION FOR PATH COVER COMMANDS |
| |
| The command |
| |
| void PathColorGenNV(enum color, |
| enum genMode, |
| enum colorFormat, const float *coeffs); |
| |
| controls how the primary and secondary interpolated colors are |
| computed for fragment shading operations that occur as a result of |
| CoverFillPathNV or CoverStrokePathNV. |
| |
| /color/ must be one of PRIMARY_COLOR, |
| PRIMARY_COLOR_NV, SECONDARY_COLOR_NV to specify the indicated color |
| generation state for the primary, primary, and secondary color |
| respectively; otherwise INVALID_ENUM is generated. |
| |
| /genMode/ must be one of NONE, OBJECT_LINEAR, |
| PATH_OBJECT_BOUNDING_BOX_NV, EYE_LINEAR, or CONSTANT; otherwise |
| INVALID_ENUM is generated. |
| |
| NONE means the color is not generated but rather uses the |
| corresponding color's current color state. OBJECT_LINEAR means that |
| the specified color is generated from a linear combination of the 2D |
| path coordinates (x,y). EYE_LINEAR means the specified color |
| is generated from a linear combination of path's 2D coordinates |
| transformed in eye space, so (xe, ye, ze, we) from section 2.12 |
| ("Fixed-Function Vertex Transformation"). CONSTANT means the specified |
| color is generated from the specified constant coefficients. |
| |
| When covering single paths with CoverFillPathNV or CoverStrokePathNV, |
| PATH_OBJECT_BOUNDING_BOX_NV means the specified color is generated |
| as a function of object-space (x,y) coordinate normalized to the |
| [0..1]x[0..1] range where (0,0) is the corner of the path object's |
| bounding box with the minimum x and minimum y coordinates and (1,1) |
| is the corner of the path object's bounding box with the maximum x and |
| maximum y coordinates. Using PATH_OBJECT_BOUND_BOX_NV for /genMode/ |
| means generated colors are undefined if either the width or height |
| of the path's bounding box is zero. |
| |
| When covering instanced paths with CoverFillPathInstancedNV or |
| CoverStrokePathInstancedNV using the BOUNDING_BOX_OF_BOUNDING_BOXES_NV |
| cover mode (see section 5.X.2.3), the specified color is generated |
| as a function of object-space (x,y) coordinate normalized to the |
| [0..1]x[0..1] range where (0,0) is the corner of the bounding box of |
| the union of bounding boxes of the set of instanced path objects and |
| (1,1) is the corner of the same union bounding box with the maximum |
| x and maximum y coordinates. |
| |
| When /genMode/ is NONE, then /colorFormat/ must be NONE; |
| otherwise INVALID_ENUM is generated. When /genMode/ is not NONE, |
| then /colorFormat/ must be one of LUMINANCE, ALPHA, INTENSITY, |
| LUMINANCE_ALPHA, RGB, or RGBA; otherwise INVALID_ENUM is generated. |
| |
| In the following equations used for path color generation, coeffs[i] |
| is the /i/th element (base zero) of the /coeffs/ array; Rc, Gc, |
| Bc, and Aa are the red, green, blue, and alpha colors of the current |
| primary or secondary color (depending on the color parameter) when the |
| path is covered; and x, y, z, and w are determined by the /genMode/. |
| |
| When /genMode/ is EYE_LINEAR, xcoeffs[i] is the /i/th element (base |
| zero) of a /xcoeffs/ array generated by multiplying each respective |
| vector of four elements of coeffs by the current inverse modelview |
| matrix when PathColorGenNV is called. |
| |
| xcoeffs[0..3] = coeffs[0..3] * MV^-1 |
| xcoeffs[4..7] = coeffs[4..7] * MV^-1 |
| xcoeffs[8..11] = coeffs[8..11] * MV^-1 |
| xcoeffs[12..15] = coeffs[12..12] * MV^-1 |
| |
| [[ NOTATION: |
| |
| xxx[0..3] is a vector form from xxx[0], xxx[1], xxx[2], and xxx[3] |
| |
| MV^-1 is the inverse of the current modelview matrix when PathColorGenNV happens. |
| |
| ]] |
| |
| If the /genMode/ is NONE, no values from the /coeffs/ array are |
| accessed and the R, G, B, and A components of a covered fragment's |
| varying color (be it primary or secondary depending on color) |
| are computed: |
| |
| R = Rc |
| G = Gc |
| B = Bc |
| A = Ac |
| |
| If /colorFormat/ is LUMINANCE and /genMode/ is either OBJECT_LINEAR |
| or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from the |
| /coeffs/ array and the R, G, B, and A components of a covered |
| fragment's varying color are computed: |
| |
| R = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| G = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| B = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| A = Ac |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are |
| accessed and the varying color components are computed: |
| |
| R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| G = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| B = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| A = Ac |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| R = xcoeffs[0] |
| G = xcoeffs[0] |
| B = xcoeffs[0] |
| A = Ac |
| |
| If /colorFormat/ is INTENSITY and /genMode/ is either OBJECT_LINEAR |
| or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from |
| the /coeffs/ array and the R, G, B, and A components of a covered |
| fragment's varying color are computed: |
| |
| R = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| G = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| B = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| A = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are |
| accessed and the varying color components are computed: |
| |
| R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| G = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| B = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| A = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| R = xcoeffs[0] |
| G = xcoeffs[0] |
| B = xcoeffs[0] |
| A = xcoeffs[0] |
| |
| If /colorFormat/ is ALPHA and /genMode/ is either OBJECT_LINEAR |
| or PATH_OBJECT_BOUNDING_BOX_NV, then 3 values are accessed from |
| the /coeffs/ array and the R, G, B, and A components of a covered |
| fragment's varying color are computed: |
| |
| R = Rc |
| G = Gc |
| B = Bc |
| A = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are |
| accessed and the varying color components are computed: |
| |
| R = Rc |
| G = Gc |
| B = Bc |
| A = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| R = Rc |
| G = Gc |
| B = Bc |
| A = xcoeffs[0] |
| |
| If /colorFormat/ is RGB and /genMode/ is either OBJECT_LINEAR or |
| PATH_OBJECT_BOUNDING_BOX_NV, then 9 values are accessed from the |
| /coeffs/ array and the R, G, B, and A components of a covered |
| fragment's varying color are computed: |
| |
| R = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| G = coeffs[3] * x + coeffs[4] * y + coeffs[5] |
| B = coeffs[6] * x + coeffs[7] * y + coeffs[8] |
| A = Ac |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are |
| accessed and the varying color components are computed: |
| |
| R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| G = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we |
| B = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we |
| A = Ac |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| R = xcoeffs[0] |
| G = xcoeffs[1] |
| B = xcoeffs[2] |
| A = Ac |
| |
| If /colorFormat/ is RGBA and /genMode/ is either OBJECT_LINEAR |
| or PATH_OBJECT_BOUNDING_BOX_NV, then 12 values are accessed from |
| the /coeffs/ array and the R, G, B, and A components of a covered |
| fragment's varying color are computed: |
| |
| R = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| G = coeffs[3] * x + coeffs[4] * y + coeffs[5] |
| B = coeffs[6] * x + coeffs[7] * y + coeffs[8] |
| A = coeffs[9] * x + coeffs[10] * y + coeffs[11] |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are |
| accessed and the varying color components are computed: |
| |
| R = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| G = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we |
| B = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we |
| A = xcoeffs[12] * xe + xcoeffs[13] * ye + xcoeffs[14] * ze + xcoeffs[15] * we |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| R = xcoeffs[0] |
| G = xcoeffs[1] |
| B = xcoeffs[2] |
| A = xcoeffs[3] |
| |
| The state required for path color generation for each color (primary |
| and secondary) is a four-valued integer for the path color generation |
| mode and 16 floating-point coefficients. The initial mode is NONE |
| and the coefficients are all initially zero. |
| |
| As many coefficients are copied by the PathColorGenNV command |
| to the 16 floating-point coefficient state as are referenced by |
| the respective generation expression involving /colorFormat/ and |
| /genMode/; unreferenced coefficients in the array of 16 coefficients |
| are set to zero. |
| |
| TEXTURE COORDINATE SET GENERATION FOR PATH COVER COMMANDS |
| |
| The command |
| |
| void PathTexGenNV(enum texCoordSet, |
| enum genMode, |
| int components, const float *coeffs); |
| |
| controls how texture coordinate sets are computed for fragment |
| shading operations that occur as a result of CoverFillPathNV or |
| CoverStrokePathNV. |
| |
| /texCoordSet/ must be one of TEXTURE0 through |
| TEXTUREn where /n/ is one less than the implementation-dependent |
| value of MAX_TEXTURE_COORDS; otherwise INVALID_ENUM is generated. |
| |
| /genMode/ must be one of NONE, OBJECT_LINEAR, |
| PATH_OBJECT_BOUNDING_BOX_NV, or EYE_LINEAR; otherwise INVALID_ENUM |
| is generated. |
| |
| /components/ must be 0 if /genMode/ is NONE or for other allowed |
| /genMode/ values must be one of 1, 2, 3, or 4; otherwise INVALID_VALUE |
| is generated. /components/ determines how many texture coordinate |
| components of the texture coordinate set, how many coefficients read |
| from the /coeffs/ array, and the linear equations used to generate the |
| s, t, r, and q texture coordinates of the varying texture coordinate |
| set specified by /texCoordSet/. |
| |
| In the following equations, coeffs[i] is the /i/th element (base |
| zero) of the /coeffs/ array; sc, tc, rc, and qa are the s, t, r, |
| and q texture coordinates of the texture coordinate set indicated |
| by /texCoordSet/ when the path is covered; and x, y, z, and w are |
| determined by the /genMode/ in the same manner as PathColorGenNV's |
| /genMode/. |
| |
| When /genMode/ is EYE_LINEAR, xcoeffs[i] is the /i/th element (base |
| zero) of a /xcoeffs/ array generated by multiplying each respective |
| vector of four elements of coeffs by the current inverse modelview |
| matrix when PathColorGenNV is called. |
| |
| xcoeffs[0..3] = coeffs[0..3] * MV^-1 |
| xcoeffs[4..7] = coeffs[4..7] * MV^-1 |
| xcoeffs[8..11] = coeffs[8..11] * MV^-1 |
| xcoeffs[12..15] = coeffs[12..12] * MV^-1 |
| |
| [[ NOTATION: |
| |
| xxx[0..3] is a vector form from xxx[0], xxx[1], xxx[2], and xxx[3] |
| |
| MV^-1 is the inverse of the current modelview matrix when PathColorGenNV happens. |
| |
| ]] |
| |
| If the /components/ is 0, no values from the /coeffs/ array are |
| accessed and the s, t, r, and q coordinates of a covered fragment's |
| varying texture coordinate set for /texCoordSet/ are computed: |
| |
| s = sc |
| t = tc |
| r = rc |
| q = qc |
| |
| If the /components/ is 1 and /genMode/ is either OBJECT_LINEAR or |
| PATH_OBJECT_BOUNDING_BOX_NV, 3 values from the /coeffs/ array are |
| accessed and the s, t, r, and q coordinates of a covered fragment's |
| varying texture coordinate set for /texCoordSet/ are computed: |
| |
| s = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| t = tc |
| r = rc |
| q = qc |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 4 values are |
| accessed and the varying texture coordinate set for /texunit/ are |
| computed: |
| |
| s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| t = tc |
| r = rc |
| q = qc |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| s = xcoeffs[0] |
| t = tc |
| r = rc |
| q = qc |
| |
| If the /components/ is 2 and /genMode/ is either OBJECT_LINEAR or |
| PATH_OBJECT_BOUNDING_BOX_NV, 6 values from the /coeffs/ array are accessed and the |
| s, t, r, and q coordinates of a covered fragment's varying texture |
| coordinate set for /texCoordSet/ are computed: |
| |
| s = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| t = coeffs[3] * x + coeffs[4] * y + coeffs[5] |
| r = rc |
| q = qc |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 8 values are |
| accessed and the varying texture coordinate set for /texunit/ are |
| computed: |
| |
| s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we |
| r = rc |
| q = qc |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| s = xcoeffs[0] |
| t = xcoeffs[1] |
| r = rc |
| q = qc |
| |
| If the /components/ is 3 and /genMode/ is either OBJECT_LINEAR or |
| PATH_OBJECT_BOUNDING_BOX_NV, 9 values from the /coeffs/ array are accessed and the |
| s, t, r, and q coordinates of a covered fragment's varying texture |
| coordinate set for /texCoordSet/ are computed: |
| |
| s = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| t = coeffs[3] * x + coeffs[4] * y + coeffs[5] |
| r = coeffs[6] * x + coeffs[7] * y + coeffs[8] |
| q = qc |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| s = xcoeffs[0] |
| t = xcoeffs[1] |
| r = xcoeffs[2] |
| q = qc |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 12 values are |
| accessed and the varying texture coordinate set for /texunit/ are |
| computed: |
| |
| s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we |
| r = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we |
| q = qc |
| |
| If the /components/ is 4 and /genMode/ is either OBJECT_LINEAR or |
| PATH_OBJECT_BOUNDING_BOX_NV, 12 values from the /coeffs/ array are accessed and the |
| s, t, r, and q coordinates of a covered fragment's varying texture |
| coordinate set for /texCoordSet/ are computed: |
| |
| s = coeffs[0] * x + coeffs[1] * y + coeffs[2] |
| t = coeffs[3] * x + coeffs[4] * y + coeffs[5] |
| r = coeffs[6] * x + coeffs[7] * y + coeffs[8] |
| q = coeffs[9] * x + coeffs[10] * y + coeffs[11] |
| |
| Alternatively if the /genMode/ is EYE_LINEAR, then 16 values are |
| accessed and the varying texture coordinate set for /texunit/ are |
| computed: |
| |
| s = xcoeffs[0] * xe + xcoeffs[1] * ye + xcoeffs[2] * ze + xcoeffs[3] * we |
| t = xcoeffs[4] * xe + xcoeffs[5] * ye + xcoeffs[6] * ze + xcoeffs[7] * we |
| r = xcoeffs[8] * xe + xcoeffs[9] * ye + xcoeffs[10] * ze + xcoeffs[11] * we |
| q = xcoeffs[12] * xe + xcoeffs[13] * ye + xcoeffs[14] * ze + xcoeffs[15] * we |
| |
| Alternatively if the /genMode/ is CONSTANT, then: |
| |
| s = xcoeffs[0] |
| t = xcoeffs[1] |
| r = xcoeffs[2] |
| q = xcoeffs[3] |
| |
| The state required for path color generation for each texture |
| coordinate set is a four-valued integer for the path texture |
| coordinate set generation mode and 16 floating-point coefficients. |
| The initial mode is NONE and the coefficients are all initially zero. |
| |
| As many coefficients are copied by the PathTexGenNV command to |
| the 16 floating-point coefficient state as are referenced by the |
| respective generation expression involving /components/ and /genMode/; |
| unreferenced coefficients in the array of 16 coefficients are set |
| to zero. |
| |
| FOG COORDINATE GENERATION FOR PATH COVER COMMANDS |
| |
| The command |
| |
| void PathFogGenNV(enum genMode); |
| |
| controls how the fog coordinate is computed for fragment |
| shading operations that occur as a result of CoverFillPathNV or |
| CoverStrokePathNV. |
| |
| /genMode/ must be either FOG_COORDINATE or FRAGMENT_DEPTH; otherwise |
| INVALID_ENUM is generated. |
| |
| If the /genMode/ is FOG_COORDINATE, then current fog coordinate is |
| used (without varying) for all fragment generated by covering the |
| filled or stroked path. |
| |
| If the /genMode/ is FRAGMENT_DEPTH, then the current fog coordinate |
| is -ze, the interpolated negated (non-perspective-divided) eye-space |
| Z coordinate from transforming of path's 2D coordinates transformed |
| in eye space, so (xe, ye, ze, we) from section 2.12 ("Fixed-Function |
| Vertex Transformation"). |
| |
| The state required for path fog generation is a two-valued integer for |
| the path fog generation mode; the mode is initially FRAGMENT_DEPTH. |
| |
| 5.X.2.3 Instanced Path Stenciling and Covering |
| |
| Path rendering often depends on rendering a collection of paths at |
| once. The most common case of this is rendering text as a set of |
| glyphs corresponding to each character of text. To support this |
| usage efficiently, GL includes commands for instanced path stenciling |
| and covering. |
| |
| The command |
| |
| void StencilFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum transformType, |
| const float *transformValues); |
| |
| stencils a sequence of filled paths. |
| |
| The /pathBase/ is an offset added to the /numPaths/ path names read |
| from the /paths/ array (interpreted based on /pathNameType/). |
| |
| The /pathNameType/ determines the type of elements of the /paths/ |
| array and must be one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, |
| INT, UNSIGNED_INT, FLOAT, UTF8_NV, UTF16_NV, 2_BYTES, 3_BYTES, |
| or 4_BYTES; otherwise the INVALID_ENUM error is generated. |
| |
| The /transformType/ must be one of NONE, TRANSLATE_X_NV, |
| TRANSLATE_Y_NV, TRANSLATE_2D_NV, TRANSLATE_3D_NV, AFFINE_2D_NV, |
| AFFINE_3D_NV, TRANSPOSE_AFFINE_2D_NV, or TRANSPOSE_AFFINE_3D_NV; |
| otherwise the INVALID_ENUM error is generated. |
| |
| The /fillMode/ and /mask/ are validated identically to the same-named |
| parameters of StencilFillPathNV. |
| |
| The StencilFillPathInstancedNV command is equivalent to: |
| |
| const float *v = transformValues; |
| for (int i = 0; i<numPaths; i++) { |
| double m[16]; |
| |
| GetDoublev(MODELVIEW_MATRIX, m); // save matrix |
| v = applyTransformType(transformType, v); |
| uint pathName; |
| bool ok = getPathName(pathNameType, paths, pathBase, pathName); |
| if (!ok) |
| return; // stop early |
| if (IsPathNV(pathName)) { |
| StencilFillPathNV(pathName, fillMode, mask); |
| } |
| MatrixLoaddEXT(MODELVIEW, m); // restore matrix |
| } |
| |
| assuming these helper functions for applyTransformType and |
| getPathName: |
| |
| const float *applyTransformType(enum transformType, const float *v) |
| { |
| float m[16]; |
| switch (transformType) { |
| case NONE: |
| break; |
| case TRANSLATE_X_NV: |
| MatrixTranslateEXT(MODELVIEW, *v++, 0, 0); |
| break; |
| case TRANSLATE_Y_NV: |
| MatrixTranslateEXT(MODELVIEW, 0, *v++, 0); |
| break; |
| case TRANSLATE_2D_NV: |
| MatrixTranslateEXT(MODELVIEW, *v++, *v++, 0); |
| break; |
| case TRANSLATE_3D_NV: |
| MatrixTranslateEXT(MODELVIEW, *v++, *v++, *v++); |
| break; |
| case AFFINE_2D_NV: |
| m[0] =v[0]; m[4] =v[2]; m[8] =0; m[12]=v[4]; |
| m[1] =v[1]; m[5] =v[3]; m[9] =0; m[13]=v[5]; |
| m[2] =0; m[6] =0; m[10]=1; m[14]=0; |
| m[3] =0; m[7] =0; m[11]=0; m[15]=1; |
| v += 6; |
| MatrixMultfEXT(MODELVIEW, m); |
| break; |
| case TRANSPOSE_AFFINE_2D_NV: |
| m[0] =v[0]; m[4] =v[1]; m[8] =0; m[12]=v[2]; |
| m[1] =v[3]; m[5] =v[4]; m[9] =0; m[13]=v[5]; |
| m[2] =0; m[6] =0; m[10]=1; m[14]=0; |
| m[3] =0; m[7] =0; m[11]=0; m[15]=1; |
| v += 6; |
| MatrixMultfEXT(MODELVIEW, m); |
| break; |
| case AFFINE_3D_NV: |
| m[0] =v[0]; m[4] =v[3]; m[8] =v[6]; m[12]=v[9]; |
| m[1] =v[1]; m[5] =v[4]; m[9] =v[7]; m[13]=v[10]; |
| m[2] =v[2]; m[6] =v[5]; m[10]=v[8]; m[14]=v[11]; |
| m[3] =0; m[7] =0; m[11]=1; m[15]=0; |
| v += 12; |
| MatrixMultfEXT(MODELVIEW, m); |
| break; |
| case TRANSPOSE_AFFINE_3D_NV: |
| m[0] =v[0]; m[4] =v[1]; m[8] =v[2]; m[12]=v[3]; |
| m[1] =v[4]; m[5] =v[5]; m[9] =v[6]; m[13]=v[7]; |
| m[2] =v[8]; m[6] =v[9]; m[10]=v[10]; m[14]=v[11]; |
| m[3] =0; m[7] =0; m[11]=1; m[15]=0; |
| v += 12; |
| MatrixMultfEXT(MODELVIEW, m); |
| break; |
| default: // generate INVALID_ENUM |
| } |
| return v; |
| } |
| |
| bool getPathName(enum pathNameType, const void *&paths, |
| uint pathBase, uint &pathName) |
| { |
| switch (pathNameType) { |
| case BYTE: |
| { |
| const byte *p = (const byte*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case UNSIGNED_BYTE: |
| { |
| const ubyte *p = (const ubyte*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case SHORT: |
| { |
| const short *p = (const short*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case UNSIGNED_SHORT: |
| { |
| const ushort *p = (const ushort*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case INT: |
| { |
| const int *p = (const int*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case UNSIGNED_INT: |
| { |
| const uint *p = (const uint*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case FLOAT: |
| { |
| const float *p = (const float*)paths; |
| pathName = pathBase + p[0]; |
| paths = p+1; |
| return true; |
| } |
| case 2_BYTES: |
| { |
| const ubyte *p = (const ubyte*)paths; |
| pathName = pathBase + (p[0]<<8 | p[1]); |
| paths = p+2; |
| return true; |
| } |
| case 3_BYTES: |
| { |
| const ubyte *p = (const ubyte*)paths; |
| pathName = pathBase + (p[0]<<16 | p[1]<<8 | p[0]); |
| paths = p+3; |
| return true; |
| } |
| case 4_BYTES: |
| { |
| const ubyte *p = (const ubyte*)paths; |
| pathName = pathBase + (p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]); |
| paths = p+4; |
| return true; |
| } |
| case UTF8_NV: |
| { |
| const ubyte *p = (const ubyte*)paths; |
| ubyte c0 = p[0]; |
| if ((c0 & 0x80) == 0x00) { |
| // Zero continuation (0 to 127) |
| pathName = pathBase + c0; |
| p += 1; |
| } else { |
| ubyte c1 = p[1]; |
| if ((c1 & 0xC0) != 0x80) { |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| if ((c0 & 0xE0) == 0xC0) { |
| // One contination (128 to 2047) |
| pathName = pathBase + ((c1 & 0x3F) | (c0 & 0x1F) << 6); |
| if (pathName < 128) { |
| return false; |
| } |
| p += 2; |
| } else { |
| ubyte c2 = p[2]; |
| if ((c2 & 0xC0) != 0x80) { |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| if ((c0 & 0xF0) == 0xE0) { |
| // Two continuation (2048 to 55295 and 57344 to 65535) |
| pathName = pathBase + ((c2 & 0x3F) | (c1 & 0x3F) << 6 | |
| (c0 & 0xF) << 12); |
| if ((pathName >= 55296) && (pathName <= 57343)) { |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| if (pathName < 2048) { |
| return false; |
| } |
| p += 3; |
| } else { |
| ubyte c3 = p[3]; |
| if ((c3 & 0xC0) != 0x80) { |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| if ((c0 & 0xF8) == 0xF0) { |
| // Three continuation (65536 to 1114111) |
| pathName = pathBase + ((c3 & 0x3F) | (c2 & 0x3F) << 6 | |
| (c1 & 0x3F) << 12 | (c0 & 0x7) << 18); |
| if (pathName < 65536 && pathName > 1114111) { |
| return false; |
| } |
| p += 4; |
| } else { |
| // Skip invalid or restricted encodings. |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| } |
| } |
| } |
| paths = p; |
| return true; |
| } |
| case UTF16_NV: |
| { |
| const ushort *p = (const ushort*)paths; |
| |
| ushort s0 = p[0]; |
| if ((s0 < 0xDB00) || (s0 > 0xDFFF)) { |
| pathName = pathBase + s0; |
| p += 1; |
| } else { |
| if ((s0 >= 0xDB00) && (s0 <= 0xDBFF)) { |
| ushort s1 = p[1]; |
| if ((s1 >= 0xDC00) && (s1 <= 0xDFFF)) { |
| pathName = pathBase + (((s0 & 0x3FF) << 10 | |
| (s1 & 0x3FF)) + 0x10000); |
| p += 2; |
| } else { |
| // Stop processing the UTF byte sequence early. |
| return false; |
| } |
| } else { |
| return false; |
| } |
| } |
| paths = p; |
| return true; |
| } |
| default: |
| << generate INVALID_ENUM >> |
| return false; |
| } |
| } |
| |
| The command |
| |
| void StencilStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| int reference, uint mask, |
| enum transformType, |
| const float *transformValues); |
| |
| stencils a sequence of stroked paths and is equivalent to: |
| |
| const float *v = transformValues; |
| for (int i = 0; i<numPaths; i++) { |
| double m[16]; |
| |
| GetDoublev(MODELVIEW_MATRIX, m); // save matrix |
| v = applyTransformType(transformType, v); |
| uint pathName; |
| bool ok = getPathName(pathNameType, paths, pathBase, pathName); |
| if (!ok) |
| return; // stop early |
| if (IsPathNV(pathName)) { |
| StencilStrokePathNV(pathName, reference, mask); |
| } |
| MatrixLoaddEXT(MODELVIEW, m); // restore matrix |
| } |
| |
| assume the helper functions for applyTransformType and |
| getPathName defined above. |
| |
| The command |
| |
| void CoverFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| covers a sequence of filled paths and is equivalent to: |
| |
| if (coverMode == BOUNDING_BOX_OF_BOUNDING_BOXES_NV) { |
| renderBoundingBox(PATH_FILL_BOUNDING_BOX_NV, |
| numPaths, |
| pathNameType, paths, |
| pathBase, |
| transformType, transformValues); |
| } else { |
| const float *v = transformValues; |
| for (int i = 0; i<numPaths; i++) { |
| double m[16]; |
| uint path; |
| |
| GetDoublev(MODELVIEW_MATRIX, m); // save matrix |
| v = applyTransformType(transformType, v); |
| uint pathName; |
| bool ok = getPathName(pathNameType, paths, pathBase, pathName); |
| if (!ok) |
| return; // stop early |
| if (IsPathNV(pathName)) { |
| << set fragment shader instance ID to i >> |
| CoverFillPathNV(pathName, cover); |
| } |
| MatrixLoaddEXT(MODELVIEW, m); // restore matrix |
| } |
| } |
| |
| assuming these helper functions for applyTransformType and |
| getPathName defined above as well as: |
| |
| void renderBoundingBox(enum boundingBoxType, |
| sizei numPaths, |
| enum pathNameType, |
| const void *paths, |
| uint pathBase, |
| enum transformType, |
| const float *transformValues) |
| { |
| boolean hasBounds = FALSE; |
| float boundsUnion[4], bounds[4]; |
| |
| const float *v = transformValues; |
| for (int i = 0; i<numPaths; i++) { |
| uint pathName; |
| bool ok = getPathName(pathNameType, paths, pathBase, pathName); |
| if (!ok) |
| return; // stop early |
| if (IsPathNV(pathName)) { |
| GetPathParameterfvNV(pathName, boundingBoxType, bounds); |
| switch (transformType) { |
| case NONE: |
| break; |
| case TRANSLATE_X_NV: |
| bounds[0] += v[0]; |
| bounds[2] += v[0]; |
| v += 1; |
| break; |
| case TRANSLATE_Y_NV: |
| bounds[1] += v[0]; |
| bounds[3] += v[0]; |
| v += 1; |
| break; |
| case TRANSLATE_2D_NV: |
| bounds[0] += v[0]; |
| bounds[1] += v[1]; |
| bounds[2] += v[0]; |
| bounds[3] += v[1]; |
| v += 2; |
| break; |
| case TRANSLATE_3D_NV: // ignores v[2] |
| bounds[0] += v[0]; |
| bounds[1] += v[1]; |
| bounds[2] += v[0]; |
| bounds[3] += v[1]; |
| v += 3; |
| break; |
| case AFFINE_2D_NV: |
| bounds[0] = bounds[0]*v[0] + bounds[0]*v[2] + v[4]; |
| bounds[1] = bounds[1]*v[1] + bounds[1]*v[3] + v[5]; |
| bounds[2] = bounds[2]*v[0] + bounds[2]*v[2] + v[4]; |
| bounds[3] = bounds[3]*v[1] + bounds[3]*v[3] + v[5]; |
| v += 6; |
| break; |
| case TRANSPOSE_AFFINE_2D_NV: |
| bounds[0] = bounds[0]*v[0] + bounds[0]*v[1] + v[2]; |
| bounds[1] = bounds[1]*v[3] + bounds[1]*v[4] + v[5]; |
| bounds[2] = bounds[2]*v[0] + bounds[2]*v[1] + v[2]; |
| bounds[3] = bounds[3]*v[3] + bounds[3]*v[4] + v[5]; |
| v += 6; |
| break; |
| case AFFINE_3D_NV: // ignores v[2], v[5], v[6..8], v[11] |
| bounds[0] = bounds[0]*v[0] + bounds[0]*v[3] + v[9]; |
| bounds[1] = bounds[1]*v[1] + bounds[1]*v[4] + v[10]; |
| bounds[2] = bounds[2]*v[0] + bounds[2]*v[3] + v[9]; |
| bounds[3] = bounds[3]*v[1] + bounds[3]*v[4] + v[10]; |
| v += 12; |
| break; |
| case TRANSPOSE_AFFINE_3D_NV: // ignores v[2], v[6], v[8..11] |
| bounds[0] = bounds[0]*v[0] + bounds[0]*v[1] + v[3]; |
| bounds[1] = bounds[1]*v[4] + bounds[1]*v[5] + v[7]; |
| bounds[2] = bounds[2]*v[0] + bounds[2]*v[1] + v[3]; |
| bounds[3] = bounds[3]*v[4] + bounds[3]*v[5] + v[7]; |
| v += 12; |
| break; |
| default: // generate INVALID_ENUM |
| } |
| if (bounds[0] > bounds[2]) { |
| float t = bounds[2]; |
| bounds[2] = bounds[0]; |
| bounds[0] = t; |
| } |
| if (bounds[1] > bounds[3]) { |
| float t = bounds[3]; |
| bounds[3] = bounds[1]; |
| bounds[1] = t; |
| } |
| if (hasBounds) { |
| if (bounds[0] < boundsUnion[0]) { |
| boundsUnion[0] = bounds[0]; |
| } |
| if (bounds[1] < boundsUnion[1]) { |
| boundsUnion[1] = bounds[1]; |
| } |
| if (bounds[2] > boundsUnion[2]) { |
| boundsUnion[2] = bounds[2]; |
| } |
| if (bounds[3] > boundsUnion[3]) { |
| boundsUnion[3] = bounds[3]; |
| } |
| } else { |
| for (int i=0; i<4; i++) { |
| boundsUnion[i] = bounds[i]; |
| } |
| hasBounds = TRUE; |
| } |
| } |
| } |
| if (hasBounds) { |
| boolean polygonSmoothEnable = IsEnabled(POLYGON_SMOOTH); |
| int polygonModes[2]; |
| GetIntegerv(POLYGON_MODE, polygonModes); |
| PolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
| Disable(GL_POLYGON_SMOOTH); |
| Rectf(boundsUnion[0], boundsUnion[1], boundsUnion[2], boundsUnion[3]); |
| PolygonMode(FRONT, polygonModes[0]); |
| PolygonMode(BACK, polygonModes[1]); |
| if (polygonSmoothEnable) { |
| Enable(POLYGON_SMOOTH); |
| } else { |
| Disable(POLYGON_SMOOTH); |
| } |
| } |
| } |
| |
| The GetPathParameterfvNV query, used in the code above, is introduced |
| in section 6.X.1 ("Path Object Parameter Queries"). |
| |
| The command |
| |
| void CoverStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| covers a sequence of stroked paths and is equivalent to: |
| |
| if (coverage == BOUNDING_BOX_OF_BOUNDING_BOXES_NV) { |
| renderBoundingBox(PATH_STROKE_BOUNDING_BOX_NV, |
| numPaths, |
| pathNameType, paths, |
| pathBase, |
| transformType, transformValues); |
| } else { |
| const float *v = transformValues; |
| for (int i = 0; i<numPaths; i++) { |
| double m[16]; |
| |
| GetDoublev(MODELVIEW_MATRIX, m); // save matrix |
| v = applyTransformType(transformType, v); |
| uint pathName; |
| bool ok = getPathName(pathNameType, paths, pathBase, pathName); |
| if (!ok) |
| return; // stop early |
| if (IsPathNV(pathName)) { |
| << set fragment shader instance ID to i >> |
| CoverStrokePathNV(pathName, cover); |
| } |
| MatrixLoaddEXT(MODELVIEW, m); // restore matrix |
| } |
| } |
| |
| assuming these helper functions for applyTransformType, |
| getPathName, and renderBoundingBox defined above. |
| |
| 5.X.2.4 Path Stenciling Then Covering |
| |
| The following command combine the stencil and cover operations on |
| paths into a single command. |
| |
| The command |
| |
| void StencilThenCoverFillPathNV(uint path, enum fillMode, uint mask, enum coverMode); |
| |
| is equivalent to the two commands |
| |
| StencilFillPathNV(path, fillMode, mask); |
| CoverFillPathNV(path, coverMode); |
| |
| unless either command would generate an error; for any such error |
| other than OUT_OF_MEMORY, only that error is generated. |
| |
| The command |
| |
| void StencilThenCoverStrokePathNV(uint path, int reference, uint mask, enum coverMode); |
| |
| is equivalent to the two commands |
| |
| StencilStrokePathNV(uint path, int reference, uint mask); |
| CoverStrokePathNV(uint path, enum coverMode); |
| |
| unless either command would generate an error; for any such error |
| other than OUT_OF_MEMORY, only that error is generated. |
| |
| The command |
| |
| void StencilThenCoverFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| is equivalent to the two commands |
| |
| StencilFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| CoverFillPathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum fillMode, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| unless either command would generate an error; for any such error |
| other than OUT_OF_MEMORY, only that error is generated. |
| |
| The command |
| |
| void StencilThenCoverStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| int reference, uint mask, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| is equivalent to the two commands |
| |
| StencilStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| int reference, uint mask, |
| enum transformType, |
| const float *transformValues); |
| CoverStrokePathInstancedNV(sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| enum coverMode, |
| enum transformType, |
| const float *transformValues); |
| |
| unless either command would generate an error; for any such error |
| other than OUT_OF_MEMORY, only that error is generated. |
| |
| -- Section 5.4 "Display Lists" |
| |
| Add to the list of commands not compiled into display lists: |
| |
| "Path objects: GenPathsNV, DeletePathsNV." |
| |
| Additions to Chapter 6 of the OpenGL 3.2 (unabridged) Specification (State and |
| State Requests) |
| |
| -- Insert section 6.X "Path Object Queries" after 6.1.18 "Renderbuffer |
| Object Queries" |
| |
| 6.X. Path Rendering Queries |
| |
| 6.X.1. Path Object Parameter Queries |
| |
| The queries |
| |
| void GetPathParameterivNV(uint path, enum pname, int *value); |
| void GetPathParameterfvNV(uint path, enum pname, float *value); |
| |
| obtains the current value of the /param/ path parameter of the path |
| object named /name/; the error INVALID_OPERATION is generated if |
| /name/ is not an existing path object. /value/ is a pointer to a |
| scalar or array of the appropriate type, int for GetPathParameterivNV |
| and float for GetPathParameterfvNV, in which to place the returned |
| data. |
| |
| Table 6.readOnlyPathParameters |
| |
| Name Type Description |
| --------------------------- ------- ---------------------------- |
| PATH_COMMAND_COUNT_NV int Length of the path's |
| command sequence |
| PATH_COORD_COUNT_NV int Length of the path's |
| coordinate sequence |
| PATH_DASH_ARRAY_COUNT_NV int Length of the path's |
| dash array |
| PATH_COMPUTED_LENGTH_NV float Computed path-space |
| length of all the |
| segments in the path |
| (see section 6.X.4) |
| PATH_OBJECT_BOUNDING_BOX_NV 4*float tight path-space bounding |
| box around the path's |
| covered fill region |
| PATH_FILL_BOUNDING_BOX_NV 4*float Conservative path-space |
| bounding box around the |
| path's covered fill region |
| PATH_STROKE_BOUNDING_BOX_NV 4*float Conservative path-space |
| bounding box around the |
| path's covered stroke region |
| |
| /param/ must be one of the tokens listed in Table 5.pathParameters |
| or Table 6.readOnlyPathParameters; otherwise the INVALID_ENUM |
| error is generated. The parameters from Table 5.pathParameters |
| always return a single (scalar) value. The parameters from |
| Table 6.readOnlyPathParameters a single (scalar) value for all the |
| parameters but the PATH_*_BOUNDING_BOX_NV parameters; these bounding |
| box parameters return a vector of 4 values. These four values are |
| the minimum (x1,y1) corner of the respective path-space bounding |
| box and the maximum (x2,y2) corner of the respective path-space |
| orthogonally aligned bounding box, returned in (x1,y1,x2,y2) order. |
| (This guarantees x1<=x2 and y1<=y2.) Float parameters queried by |
| GetPathParameterivNV are rounded to the nearest integer (where values |
| with a floating-point fraction of 0.5 round up). |
| |
| The PATH_OBJECT_BOUNDING_BOX_NV bounding box is intended to bound |
| tightly the region of path space containing the path's outline. |
| The PATH_FILL_BOUNDING_BOX_NV bounding box matches the rectangle |
| region covered by the CoverFillPathNV command with the BOUNDING_BOX_NV |
| /coverMode/. With either the PATH_OBJECT_BOUNDING_BOX_NV or |
| PATH_FILL_BOUNDING_BOX_NV bounding boxes of a path object, a point at |
| (x,y) such that x<x1 or x>x2 or y<y1 or y>y2 is guaranteed to /not/ |
| be within the filled outline of the path. |
| |
| The PATH_STROKE_BOUNDING_BOX_NV bounding box matches the rectangle |
| region covered by the CoverFillPathNV command with the BOUNDING_BOX_NV |
| /coverMode/. With the PATH_STROKE_BOUNDING_BOX_NV bounding box of |
| a path object, a point at (x,y) such that x<x1 or x>x2 or y<y1 or |
| y>y2 is guaranteed to /not/ be within the stroked region of the path. |
| |
| 6.X.2. Path Object Varying Arrays Queries |
| |
| Path objects support a variable number of commands, coordinates, |
| and dash lengths. |
| |
| The query |
| |
| void GetPathCommandsNV(uint path, ubyte *commands); |
| |
| returns the sequence of commands within the path object named /name/ |
| into the array named /commands/; the error INVALID_OPERATION is |
| generated if /name/ is not an existing path object. The number of |
| commands returned is identical to the value of the path object's |
| PATH_COMMAND_COUNT_NV parameter. The application is responsible |
| for ensuring /commands/ array has sufficient space. |
| |
| Any path commands specified with a character alias value (from Table |
| 5.pathCommands) is returned as the command's token value instead. |
| |
| The query |
| |
| void GetPathCoordsNV(uint path, float *coords); |
| |
| returns the sequence of coordinates within the path object named |
| /name/ into the array named /coords/; the error INVALID_OPERATION |
| is generated if /name/ is not an existing path object. The number |
| of commands returned is identical to the value of the path object's |
| PATH_COORD_COUNT_NV parameter. The application is responsible for |
| ensuring /coords/ array has sufficient space. |
| |
| Boolean coordinates such as the large/small and sweep flags for arcs |
| are always returned as 1.0 or 0.0 for true and false respectively. |
| Other coordinates are returned as they were specified. |
| |
| The query |
| |
| void GetPathDashArrayNV(uint path, float *dashArray); |
| |
| returns the sequence of dash lengths within the path object named |
| /name/ into the array named /coords/; the error INVALID_OPERATION is |
| generated if /name/ is not an existing path object. The number of |
| dash lengths returned is identical to the value of the path object's |
| PATH_DASH_ARRAY_COUNT_NV parameter. The application is responsible |
| for ensuring /dashArray/ has sufficient space. |
| |
| 6.X.3. Path Object Glyph Typographic Queries |
| |
| GLYPH METRIC QUERIES |
| |
| To facilitate proper text layout, the command |
| |
| void GetPathMetricsNV(bitfield metricQueryMask, |
| sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| sizei stride, |
| float *metrics); |
| |
| queries glyph metrics associated with a sequence of path objects |
| specified by the /glyphBase/, /count/, /pathNameType/, and /paths/ |
| parameters. Metrics are associated with path objects specified by |
| PathGlyphsNV or PathGlyphRangeNV (see section 5.X.1.3). |
| |
| There are two kinds of metrics: |
| |
| * Per-glyph metrics that are typically different for each glyph. |
| |
| * Per-font face metrics that are identical for all glyphs belonging |
| to a given font face. |
| |
| Per-font face metrics are aggregate metrics such as the maximum |
| ascender or descender for all the glyphs in the font face. |
| |
| /metricQueryMask/ is a bitfield constructed from the bits listed |
| in Table 6.perGlyphMetrics and Table 6.perFontFaceMetrics. If a bit |
| is set in /metricQueryMask/ not listed in these tables, the error |
| INVALID_VALUE is generated. |
| |
| /stride/ is the byte (machine units) offset separating each group of |
| returned metrics for a given path object. If /stride/ is negative |
| or /stride/ is not a multiple of the size of float in bytes (machine |
| units), the INVALID_VALUE error is generated. The INVALID_OPERATION |
| error is generated if /stride/ divided by the size of float in bytes |
| is not either zero or else greater than or equal to the number of |
| metrics specified for querying in the metricQueryMask (based on the |
| number of specified bits specified in the mask) times the size of |
| float in bytes. A /stride/ of zero is specially handled; the value |
| zero is interpreted to indicate the number of bytes (machine units) |
| such that the all the metrics are written in a tightly packed array, |
| so the size of float in bytes times the number of specified bits in |
| the /metricQueryMask/ bitfield. |
| |
| For path objects not created with either PathGlyphsNV or |
| PathGlyphRangeNV or non-existent, all glyph metrics return -1. |
| |
| This metric information for a path object is /not/ updated if |
| the commands or coordinates or parameters of that path object are |
| changed. |
| |
| Figure 6.horizontalGlyphMetrics: Horizontal Glyph Metrics |
| |
| ^ |
| | xMin xMax |
| | | | |
| | | width | |
| | |<---------->| |
| | | | |
| | +============+ - - - - - - - - - - - yMax |
| | I I ^ ^ |
| | I I | hBearingY | |
| | I I | | |
| hBearingX |---->I GLYPH I | height | |
| | I OUTLINE I | | |
| ----O-----I------------I------*---> | |
| /| I HERE I | | |
| / | I I | v |
| origin | +============+ - - -|- - - - - - - - yMin |
| | | |
| |------------------------>| |
| | hAdvance | |
| |
| Figure 6.verticalGlyphMetrics: Vertical Glyph Metrics |
| |
| vBearingX |
| |<---------| origin |
| | | / |
| | |/ |
| ---------------------O-----------------------------> |
| | | | | |
| | | vBearingY | | |
| | | v | |
| yMax - - +================+ - - - - - - - - | |
| I | I ^ | |
| I | I | | |
| I GLYPH | I | | |
| I OUTLINE I | height | |
| I HERE| I | | |
| I | I | | |
| I | I | | |
| I | I v | vAdvance |
| yMin - - +================+ - - - | |
| | | | v |
| | * - - - - - - - - - - - - |
| | | | |
| xMin v xMax |
| |
| Table 6.perGlyphMetrics |
| |
| Bit number |
| Glyph from LSB |
| Bit field name metric tag in bitmask Description (units in path space) |
| --------------------------------------- ---------- ---------- ------------------------------------------- |
| GLYPH_WIDTH_BIT_NV width 0 Glyph's width |
| GLYPH_HEIGHT_BIT_NV height 1 Glyph's height |
| GLYPH_HORIZONTAL_BEARING_X_BIT_NV hBearingX 2 Left side bearing for horizontal layout |
| GLYPH_HORIZONTAL_BEARING_Y_BIT_NV hBearingY 3 Top side bearing for horizontal layout |
| GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV hAdvance 4 Advance width for horizontal layout |
| GLYPH_VERTICAL_BEARING_X_BIT_NV vBearingX 5 Left side bearing for vertical layout |
| GLYPH_VERTICAL_BEARING_Y_BIT_NV vBearingY 6 Top side bearing for vertical layout |
| GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV vAdvance 7 Advance height for vertical layout |
| GLYPH_HAS_KERNING_BIT_NV - 8 True if glyph has a kerning table. |
| |
| Table 6.perFontFaceMetrics |
| |
| Bit number |
| from LSB |
| Bit field name in bitmask Description (units in path space) |
| --------------------------------------- ---------- --------------------------------------------------- |
| FONT_X_MIN_BOUNDS_BIT_NV 16 Horizontal minimum (left-most) of the font bounding |
| box. The font bounding box (this metric and the |
| next 3) is large enough to contain any glyph from |
| the font face. |
| FONT_Y_MIN_BOUNDS_BIT_NV 17 Vertical minimum (bottom-most) of the font bounding |
| box. |
| FONT_X_MAX_BOUNDS_BIT_NV 18 Horizontal maximum (right-most) of the font |
| bounding box. |
| FONT_Y_MAX_BOUNDS_BIT_NV 19 Vertical maximum (top-most) of the font bounding |
| box. |
| FONT_UNITS_PER_EM_BIT_NV 20 Number of units in path space (font units) per |
| Em square for this font face. This is typically |
| 2048 for TrueType fonts, and 1000 for PostScript |
| fonts. |
| FONT_ASCENDER_BIT_NV 21 Typographic ascender of the font face. For font |
| formats not supplying this information, this value |
| is the same as FONT_Y_MAX_BOUNDS_BIT_NV. |
| FONT_DESCENDER_BIT_NV 22 Typographic descender of the font face (always a |
| positive value). For font formats not supplying |
| this information, this value is the same as |
| FONT_Y_MIN_BOUNDS_BIT_NV. |
| FONT_HEIGHT_BIT_NV 23 Vertical distance between two consecutive baselines |
| in the font face (always a positive value). |
| FONT_MAX_ADVANCE_WIDTH_BIT_NV 24 Maximal advance width for all glyphs in this font |
| face. (Intended to make word wrapping computations |
| easier.) |
| FONT_MAX_ADVANCE_HEIGHT_BIT_NV 25 Maximal advance height for all glyphs in this |
| font face for vertical layout. For font formats |
| not supplying this information, this value is the |
| same as FONT_HEIGHT_BIT_NV. |
| FONT_UNDERLINE_POSITION_BIT_NV 26 Position of the underline line for this font face. |
| This position is the center of the underling stem. |
| FONT_UNDERLINE_THICKNESS_BIT_NV 27 Thickness of the underline of this font face. |
| FONT_HAS_KERNING_BIT_NV 28 True if font face provides a kerning table |
| FONT_NUM_GLYPH_INDICES_BIT_NV 29 Number of glyph indices for this font. |
| |
| consulted by the GetPathSpacingNV command discussed below |
| ("GLYPH SPACING QUERIES"). |
| |
| The query |
| |
| void GetPathMetricRangeNV(bitfield metricQueryMask, |
| uint firstPathName, |
| sizei numPaths, |
| sizei stride, |
| float *metrics); |
| |
| is equivalent to |
| |
| int *array = malloc(sizeof(int)*numGlyphs); |
| if (array) { |
| for (int i=0; i<numGlyphs; i++) { |
| array[i] = i + firstPathName; |
| } |
| GetPathMetricsNV(metricQueryMask, |
| numPaths, |
| INT, array, |
| pathBase, |
| stride, metrics); |
| free(array); |
| } else { |
| // generate OUT_OF_MEMORY error |
| } |
| |
| GLYPH SPACING QUERIES |
| |
| The query |
| |
| void GetPathSpacingNV(enum pathListMode, |
| sizei numPaths, |
| enum pathNameType, const void *paths, |
| uint pathBase, |
| float advanceScale, |
| float kerningScale, |
| enum transformType, |
| float *returnedSpacing); |
| |
| returns a sequence of /numPaths/-1 glyph spacing vectors in path |
| space for spacing the specified sequence of path object pairs. |
| The returned vectors are written into the /returnedSpacing/ array. |
| |
| /pathListMode/ must be one of ADJACENT_PAIRS_NV, |
| ACCUM_ADJACENT_PAIRS_NV, or FIRST_TO_REST_NV; otherwise the |
| INVALID_ENUM error is generated. |
| |
| If /numPaths/ is negative, the error INVALID_VALUE is generated |
| |
| /pathNameType/ determines the type of elements of the /paths/ array |
| and must be one of BYTE, UNSIGNED_BYTE, SHORT, UNSIGNED_SHORT, INT, |
| UNSIGNED_INT, FLOAT, UTF8_NV, UTF16_NV, 2_BYTES, 3_BYTES, or 4_BYTES; |
| otherwise the INVALID_ENUM error is generated. |
| |
| /transformType/ must be either TRANSLATE_X_NV or TRANSLATE_2D_NV; |
| otherwise the INVALID_ENUM error is generated. |
| |
| In the absence of parameter errors, the following pseudo-code |
| implements this query: |
| |
| double accumX = 0, |
| accumY = 0; |
| float returnX = 0, |
| returnY = 0; |
| uint firstPath; |
| bool ok = getPathName(pathNameType, paths, pathBase, firstPath); |
| if (!ok) |
| return; // stop early |
| for (int i = 0; i<numPaths-1; i++) { |
| uint secondPath; |
| bool ok = getPathName(pathNameType, paths, pathBase, secondPath); |
| if (!ok) |
| return; // stop early |
| if (transformType == TRANSLATE_X_NV) { |
| returnedSpacing[i] = returnX; |
| } else { |
| // transformType == TRANSLATE_2D_NV |
| returnedSpacing[2*i ] = returnX; |
| returnedSpacing[2*i+1] = returnY; |
| } |
| float x = advanceScale * advanceX(firstPath) + |
| kerningScale * kerningX(firstPath,secondPath); |
| float y = kerningScale * kerningY(firstPath,secondPath); |
| if (pathListMode == ACCUM_ADJACENT_PAIRS_NV) { |
| returnX = accumX; |
| returnY = accumY; |
| accumX += x; |
| accumY += y; |
| } else { |
| returnX = x; |
| returnY = y; |
| } |
| if (pathListMode != FIRST_TO_REST_NV) { |
| firstPath = secondPath; |
| } |
| } |
| |
| The getPathName function is found in section 5.X.2.3 (Instanced Path |
| Stenciling and Covering). |
| |
| The advance, kerningX, and kerningY functions operate as follows: |
| |
| The advance function returns the hAdvance metric of path object |
| name passed to the function, but if the path object lacks glyph |
| metrics, the difference between the horizontal bounds of the path |
| object's bounding box (determined by PATH_OBJECT_BOUNDING_BOX_NV) |
| are returned instead. If the named path object passed to advance |
| does not exist, zero is returned. |
| |
| The kerningX and kerningY functions return the X and Y kerning |
| distances respectively between the character codes of the first |
| (typically left) and second (typically right) path objects if they |
| belong to the same font face; otherwise, zero is returned. If the |
| vertical kerning metrics are unavailable for the font face or either |
| named path object does not exist, zero is returned for kerningY. |
| (When the FONT_HAS_KERNING_BIT_NV or GLYPH_HAS_KERNING_BIT_NV glyph |
| metrics are false for the first path object name, kerningX and |
| kerningY must return zero.) |
| |
| Spacing information (horizontal advance or kerning) in a path object |
| is not changed if the path's commands, coordinates, or parameters |
| change--except in the case where the horizontal kerning value is |
| determined by the first path's object bounding box. |
| |
| 6.X.4. Path Object Geometric Queries |
| |
| The query |
| |
| boolean IsPointInFillPathNV(uint path, |
| uint mask, float x, float y); |
| |
| computes the winding number of the path-space 2D (x,y) point given |
| by /x/ and /y/ with respect to the path object named /path/ and |
| returns TRUE if the winding count ANDed with /mask/ is non-zero; |
| otherwise the query returns FALSE. If the /mask/ parameter is zero, |
| substitute the path object's PATH_FILL_MASK_NV parameter value |
| when ANDing with the winding count. The error INVALID_OPERATION is |
| generated if /path/ does not exist. |
| |
| This point-inside computation occurs in /path space/ rather than in |
| the window space as the StencilFillPathNV command operates. |
| |
| The query |
| |
| boolean IsPointInStrokePathNV(uint path, |
| float x, float y); |
| |
| returns TRUE if the path-space 2D (x,y) point given by /x/ and |
| /y/ is within the stroked region of the path object named /path/; |
| otherwise the query returns FALSE. The error INVALID_OPERATION is |
| generated if /path/ does not exist. |
| |
| The stroked region's stroke width is specified by the path object's |
| stroke width parameter. |
| |
| The stroked region is defined as in section 5.X.2.1 ("Path |
| Stenciling") so accounts for the path object's current end cap, |
| join style, and dashing parameters. |
| |
| This point-inside computation occurs in /path space/ rather than in |
| the window space as the StencilStrokePathNV command operates. |
| |
| The query |
| |
| float GetPathLengthNV(uint path, |
| sizei startSegment, sizei numSegments); |
| |
| returns an approximation of the geometric length of a given portion |
| of a path object named /path/. The portion of the path measured is |
| from the (0-indexed) /startSegment/ through the next /numSegments/. |
| The returned length is measured in path-space units. The error |
| INVALID_OPERATION is generated if /path/ does not exist. |
| |
| The geometric length of the path's measured portion depends only |
| on the path's commands and associated coordinates for the indicated |
| range of segments and the respective coordinates of these segments. |
| The geometric length of the path does not, for example, depend on |
| the path's dashing parameters. |
| |
| The MOVE_TO_NV and RELATIVE_MOVE_TO_NV commands contribute zero |
| units to the computed geometric length. For all other path commands, |
| a path segment's geometric length contribution /s/ is: |
| |
| s = int(sqrt(fx(t)^2+fy(t)^2), t, 0, 1) |
| |
| [[ int(f(t),t,a,b) computes the definite integration of the function |
| f(t) over the interval [a,b]. ]] |
| |
| where /fx/ and /fy/ is the partial derivative of the command's |
| respective path segment parametric function found in Table |
| 5.pathCommands. |
| |
| The return value, assuming no error, is the sum of all /s/ values |
| for segments /startSegment/ through /startSegment/+/numSegments/-1 |
| inclusive. If /numSegments/ is zero and no error is generated, |
| 0 is returned. |
| |
| The INVALID_VALUE error is generated in any of the following |
| circumstances: |
| |
| * /startSegment/ is negative, |
| |
| * /numSegments/ is negative, |
| |
| * /startSegment/+/numSegments/-1 is greater than the index of |
| the final path segment. |
| |
| If an error occurs, -1.0 is returned. When no error occurs, the |
| return value is always non-negative. |
| |
| If /startSegment/ is zero and /numSegments/ is equal to the |
| value of /path/'s PATH_COMMAND_COUNT_NV parameter and no error |
| is generated, the value returned is identical to (equals) the value |
| returned if GetPathParameterfvNV were used to query the value of |
| /path/'s PATH_COMPUTED_LENGTH_NV parameter. |
| |
| The query |
| |
| boolean PointAlongPathNV(uint path, |
| sizei startSegment, sizei numSegments, |
| float distance, |
| float *x, float *y, |
| float *tangentX, float *tangentY); |
| |
| returns the point lying a given distance along a given portion of a |
| path object specified by /path/ and the unit-length tangent vector |
| at that point. The boolean return value is TRUE if /distance/ |
| is within (inclusive) the arc length of the range of segments from |
| /startSegment/ to /startSegment/+/numSegments/-1; otherwise FALSE |
| is returned. |
| |
| The 2D point's (x,y) position is written to the values indicated |
| by the /x/ and /y/ pointers respectively. The tangent vector is |
| written to the values indicated by the /tangentX/ and /tangentY/ |
| points. However if /x/, /y/, /tangentX/, or /tangentY/ is a |
| NULL pointer, no value is written to such NULL pointers. Only the |
| subpath consisting of the /numSegments/ path segments beginning with |
| /startSegment/ (where the initial path segment has index 0) is used. |
| PointAlongPathNV only considers this subpath. |
| |
| If /distance/ is less than or equal to zero, the starting point |
| of the path is used (and the query returns FALSE). If /distance/ |
| is greater than the path length (i.e., the value returned when the |
| GetPathLengthNV query is called with the same /startSegment/ and |
| /numSegments/ parameters), the final point along the subpath is used |
| (and the query returns FALSE). |
| |
| The error INVALID_OPERATION is generated if /path/ does not exist. |
| |
| The error INVALID_VALUE is generated if /startSegment/ |
| or /numSegments/ are negative. The error INVALID_VALUE is |
| generated if /startSegment/ is greater than the index of /path/'s |
| final path segment. The error INVALID_VALUE is generated if |
| /startSegment/+/numSegments/-1 is less than zero or greater than |
| the index of /path/'s final path segment. |
| |
| Because it is not possible in general to compute exact distances along |
| a path, an implementation is not required to use exact computation |
| even for segments where such computations are possible. |
| |
| Implementations are not required to compute distances exactly, as |
| long as the satisfy the constraint that as /distance/ increases |
| monotonically the returned point and tangent move forward |
| monotonically along the path. |
| |
| Implementations should use the same distance-along-a-path algorithm |
| for PointAlongPathNV as is used for dashing a stroked path. (The dash |
| count and dashing array state of the path object is irrelevant to |
| the results of this query.) |
| |
| Where an implementation is able to determine that the point being |
| queried lies exactly at a discontinuity or cusp, the incoming point |
| and tangent should be returned. |
| |
| 6.X.5. Path Color and Texture Coordinate Generation Queries |
| |
| The queries |
| |
| void GetPathColorGenivNV(enum color, enum pname, int *value); |
| void GetPathColorGenfvNV(enum color, enum pname, float *value); |
| |
| return path color generation state. /color/ must be one of |
| PRIMARY_COLOR, PRIMARY_COLOR_NV, SECONDARY_COLOR_NV to return the |
| requested color generation state for the primary, primary, and |
| secondary color respectively. /pname/ must be either PATH_GEN_MODE_NV, |
| PATH_GEN_COLOR_FORMAT_NV, or PATH_GEN_COEFF_NV. |
| |
| If /pname/ is PATH_GEN_MODE_NV, the scalar value of the respective |
| color's path generation mode is written to the value referenced by |
| the /value/ pointer. |
| |
| If /pname/ is PATH_GEN_COLOR_FORMAT_NV, the scalar value of the |
| respective color's path generation color format is written to the |
| value reference by the /value/ pointer. |
| |
| If /pname/ is PATH_GEN_COEFF_NV, 16 coefficients for the respective |
| color's path generation are written to the array referenced by the |
| /value/ pointer. Assuming no error is generated, 16 coefficients |
| are written no matter what the path color generation mode is though |
| coefficients not accessed by the indicated path color generation |
| mode are returned as zero. |
| |
| The queries |
| |
| void GetPathTexGenivNV(enum texCoordSet, enum pname, int *value); |
| void GetPathTexGenfvNV(enum texCoordSet, enum pname, float *value); |
| |
| return path texture coordinate set generation state. /texCoordSet/ |
| indicates the texture coordinate set being queried and must be |
| one of TEXTURE0 through TEXTUREn where /n/ is one less than the |
| implementation-dependent value of MAX_TEXTURE_COORDS; otherwise |
| INVALID_ENUM is generated. /pname/ must be either PATH_GEN_MODE_NV |
| PATH_GEN_COMPONENTS_NV, or PATH_GEN_COEFF_NV. |
| |
| If /pname/ is PATH_GEN_MODE_NV, the scalar value of the respective |
| texture coordinate set's path generation mode is written to the |
| value referenced by the /value/ pointer. |
| |
| If /pname/ is PATH_GEN_COMPONENTS_NV, the scalar value of the |
| respective texture coordinate set's path generation number of |
| components is written to the value reference by the /value/ pointer. |
| |
| If /pname/ is PATH_GEN_COEFF_NV, 16 coefficients for the respective |
| texture coordinate set's path generation are written to the array |
| referenced by the /value/ pointer. Assuming no error is generated, 16 |
| coefficients are written no matter what the path texture generation |
| mode is though coefficients not accessed by the indicated path |
| texture generation mode are returned as zero. |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| Path objects are shared between AGL/GLX/WGL rendering contexts if |
| and only if the rendering contexts share display lists. No change |
| is made to the AGL/GLX/WGL API. |
| |
| Changes to path objects shared between multiple rendering contexts |
| will be serialized (i.e., the changes, queries, deletions, and |
| stencil/cover operations will occur in a specific order). |
| |
| Additions to the OpenGL Shading Language |
| |
| None |
| |
| GLX Protocol |
| |
| XXX |
| |
| Errors |
| |
| XXX |
| |
| Dependencies on ARB_program_interface_query. |
| |
| When ARB_program_interface_query is not supported, all references to |
| FRAGMENT_INPUT_NV and ProgramPathFragmentInputGenNV should be ignored. |
| |
| Dependencies on Core Profile and OpenGL ES |
| |
| When NV_path_rendering is advertised, the following functionality |
| must be supported... |
| |
| References to the following commands should be ignored: |
| |
| PathColorGenNV |
| PathTexGenNV |
| PathFogGenNV |
| GetPathColorGenivNV |
| GetPathColorGenfvNV |
| GetPathTexGenivNV |
| GetPathTexGenfvNV |
| |
| including the state set and queried by these commands. |
| |
| References to the following tokens should be ignored: |
| |
| PATH_FOG_GEN_MODE_NV |
| PRIMARY_COLOR |
| PRIMARY_COLOR_NV |
| SECONDARY_COLOR_NV |
| PATH_GEN_COLOR_FORMAT_NV |
| |
| References to the following GLSL built-in variables should be ignored: |
| |
| gl_TexCoord |
| gl_MaxTextureCoords |
| gl_Color |
| gl_FrontColor |
| gl_BackColor |
| gl_SecondaryColor |
| gl_FrontSecondaryColor |
| gl_BackSecondaryColor |
| gl_FogFragCoord |
| |
| The following types are defined as alias to the GL tokens: |
| |
| 2_BYTES_NV 0x1407 // from GL compat |
| 3_BYTES_NV 0x1408 // from GL compat |
| 4_BYTES_NV 0x1409 // from GL compat |
| EYE_LINEAR_NV 0x2400 // from GL compat |
| OBJECT_LINEAR_NV 0x2401 // from GL compat |
| CONSTANT_NV 0x8576 // from GL compat |
| |
| The following entry points (specified by the EXT_direct_state_access |
| extension) MUST be supported: |
| |
| void MatrixLoadfEXT(enum matrixMode, const float *m); |
| void MatrixLoaddEXT(enum matrixMode, const double *m); |
| |
| void MatrixMultfEXT(enum matrixMode, const float *m); |
| void MatrixMultdEXT(enum matrixMode, const double *m); |
| |
| void MatrixLoadTransposefEXT(enum matrixMode, const float *m); |
| void MatrixLoadTransposedEXT(enum matrixMode, const float *m); |
| |
| void MatrixMultTransposefEXT(enum matrixMode, const float *m); |
| void MatrixMultTransposedEXT(enum matrixMode, const float *m); |
| |
| void MatrixLoadIdentityEXT(enum matrixMode); |
| |
| void MatrixRotatefEXT(enum matrixMode, float angle, |
| float x, float y, float z); |
| void MatrixRotatedEXT(enum matrixMode, double angle, |
| double x, double y, double z); |
| |
| void MatrixScalefEXT(enum matrixMode, |
| float x, float y, float z); |
| void MatrixScaledEXT(enum matrixMode, |
| double x, double y, double z); |
| |
| void MatrixTranslatefEXT(enum matrixMode, |
| float x, float y, float z); |
| void MatrixTranslatedEXT(enum matrixMode, |
| double x, double y, double z); |
| |
| void MatrixOrthoEXT(enum matrixMode, double l, double r, |
| double b, double t, double n, double f); |
| void MatrixFrustumEXT(enum matrixMode, double l, double r, |
| double b, double t, double n, double f); |
| |
| void MatrixPushEXT(enum matrixMode); |
| void MatrixPopEXT(enum matrixMode); |
| |
| These commands must support the PATH_PROJECTION_NV and PATH_MODELVIEW_NV |
| tokens for matrixMode. The associated modelview and projection matrix |
| state, including matrix stacks, MUST be supported. These token values |
| for matrices are supported: |
| |
| PATH_PROJECTION_NV 0x1701 |
| PATH_MODELVIEW_NV 0x1700 |
| |
| PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3 |
| PATH_MODELVIEW_MATRIX_NV 0x0BA6 |
| PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36 |
| PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3 |
| PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4 |
| PATH_PROJECTION_MATRIX_NV 0x0BA7 |
| PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38 |
| PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4 |
| |
| The last 8 tokens are supported by GetFloatv, GetIntegerv, GetDoublev |
| to query associated path modelview and projection state. |
| |
| The values of sc, tc, rc, and qc discussed in section 5.X.2.2 "Path |
| Covering" are always zero in a Core profile context as these values |
| involve deprecated state. |
| |
| New State |
| |
| -- NEW table 6.X, "Path (state per context)" following Table 6.33, "Renderbuffer" |
| |
| Get Value Type Get Command Initial Value Description Section Attribute |
| ----------------------------------- ------- ------------------- -------------- ------------------------ ------------ -------------- |
| PATH_GEN_MODE_NV 2xZ4 GetPathColorGenivNV NONE path's color 6.X.5 lighting |
| generation mode |
| PATH_GEN_COLOR_FORMAT_NV 2xZ6 GetPathColorGenivNV NONE path's color 6.X.5 lighting |
| generation color format |
| PATH_GEN_COEFF_NV 2x16xR GetPathColorGenfvNV all 0's path's color gen mode 6.X.5 lighting |
| generation coefficients |
| PATH_GEN_MODE_NV nxZ4 GetPathTexGenivNV NONE path's texture 6.X.5 texture |
| generation mode |
| PATH_GEN_COMPONENTS_NV nxZ5 GetPathTexGenivNV 0 path's texture 6.X.5 texture |
| generation number of |
| components |
| PATH_GEN_COEFF_NV nx16xR GetPathTexGenfvNV all 0's path's texture 6.X.5 texture |
| generation coefficients |
| PATH_FOG_GEN_MODE_NV Z2 GetIntegerv FRAGMENT_DEPTH path's fog generation 5.X.2.1 fog |
| mode |
| PATH_ERROR_POSITION_NV Z GetIntegerv -1 last path string 5.X.1.2 - |
| error position |
| PATH_STENCIL_FUNC_NV Z8 GetIntegerv ALWAYS path stenciling function 5.X.2.1 stencil-buffer |
| PATH_STENCIL_REF_NV Z+ GetIntegerv 0 path stenciling 5.X.2.1 stencil-buffer |
| reference value |
| PATH_STENCIL_VALUE_MASK_NV Z+ GetIntegerv 1's path stencil read mask 5.X.2.1 stencil-buffer |
| PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV R GetFloatv 0 path stencil depth 5.X.2.1 polygon |
| offset factor |
| PATH_STENCIL_DEPTH_OFFSET_UNITS_NV R GetFloatv 0 path stencil depth 5.X.2.1 polygon |
| units factor |
| PATH_COVER_DEPTH_FUNC_NV Z8 GetIntegerv LESS path covering depth 5.X.2.2 depth-buffer |
| function |
| |
| where n is the implementation-dependent number of texture coordinate |
| sets (MAX_TEXTURE_COORDS). |
| |
| -- NEW table 6.Y, "Path (state per path object)" following Table 6.X |
| |
| Get Value Type Get Command Initial Value Description Section Attribute |
| ------------------------------- ------- -------------------- -------------------- -------------------------------- ------------ --------- |
| - nxZ8* GetPathCommandsNV - path's sequence of path commands 6.X.1 - |
| - mxR GetPathCoordsNV - path's sequence of path 6.X.1 - |
| coordinates |
| - cxR GetPathDashArrayNV - dash array contents 5.X.1.5 - |
| PATH_COMMAND_COUNT_NV Z+ GetPathParameterivNV - path's count of path commands 6.X.1 - |
| PATH_COORD_COUNT_NV Z+ GetPathParameterivNV - path's count of path coordinates 6.X.1 - |
| PATH_COMPUTED_LENGTH_NV R+ GetPathParameterfvNV - GL's calculation of the path's 6.X.1 - |
| length |
| PATH_STROKE_WIDTH_NV R+ GetPathParameterfvNV 1.0 stroke width 5.X.1.5 - |
| PATH_INITIAL_END_CAP_NV Z4 GetPathParameterivNV FLAT path's initial end cap style 5.X.1.5 - |
| PATH_TERMINAL_END_CAP_NV Z4 GetPathParameterivNV FLAT path's terminal end cap style 5.X.1.5 - |
| PATH_JOIN_STYLE_NV Z4 GetPathParameterivNV MITER_REVERT_NV path's join style 5.X.1.5 - |
| PATH_MITER_LIMIT_NV R+ GetPathParameterfvNV 4 path's miter limit 5.X.1.5 - |
| PATH_DASH_ARRAY_COUNT_NV Z+ GetPathParameterivNV 0 path's count of dashes in the 5.X.1.5 - |
| path's dash array 5.X.1.5 - |
| PATH_DASH_OFFSET_NV R GetPathParameterfvNV 0.0 path's dash offset 5.X.1.5 - |
| PATH_DASH_OFFSET_RESET_NV Z2 GetPathParameterivNV MOVE_TO_CONTINUES_NV path's dash offset reset 5.X.1.5 - |
| PATH_CLIENT_LENGTH_NV R+ GetPathParameterfvNV 0.0 the client-supplied calculation 5.X.1.5 - |
| of the path's length |
| PATH_INITIAL_DASH_CAP_NV Z4 GetPathParameterivNV FLAT path's initial dash cap style 5.X.1.5 - |
| PATH_TERMINAL_DASH_CAP_NV Z4 GetPathParameterivNV FLAT path's terminal dash cap style 5.X.1.5 - |
| PATH_FILL_MODE_NV Z3 GetPathParameterivNV COUNT_UP_NV path's default fill mode 5.X.1.5 - |
| PATH_FILL_MASK_NV Z+ GetPathParameterivNV all 1's path's default fill mask 5.X.1.5 - |
| PATH_FILL_COVER_MODE_NV Z4 GetPathParameterivNV CONVEX_HULL_NV path's default fill cover mode 5.X.1.5 - |
| PATH_STROKE_COVER_MODE_NV Z4 GetPathParameterivNV CONVEX_HULL_NV path's default stroke cover mode 5.X.1.5 - |
| PATH_STROKE_MASK_NV Z+ GetPathParameterivNV all 1's path's default stroke mask 5.X.1.5 - |
| PATH_STROKE_BOUND_NV R[0,1] GetPathParameterfvNV 0.2 (20%) path's stroke approximation 5.X.1.5 - |
| bound |
| PATH_OBJECT_BOUNDING_BOX_NV R4 GetPathParameterfvNV - path's outline bounding box 6.X.1 - |
| PATH_FILL_BOUNDING_BOX_NV R4 GetPathParameterfvNV - path's fill bounding box 6.X.1 - |
| PATH_STROKE_BOUNDING_BOX_NV R4 GetPathParameterfvNV - path's stroke bounding box 6.X.1 - |
| |
| where n is the number of commands in a path object, m is the number |
| of coordinates in a path object, and c is the dash array count of |
| a path object. |
| |
| -- NEW table 6.Z, "Path Glyph Metrics (state per path object)" following Table 6.Z |
| |
| Get Value Type Get Command Initial Value Description Section Attribute |
| --------------------------------------- ------- --------------------- ------------- --------------------------- ------------ --------- |
| GLYPH_WIDTH_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph width 6.X.3 - |
| GLYPH_HEIGHT_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph height 6.X.3 - |
| GLYPH_HORIZONTAL_BEARING_X_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph left side bearing 6.X.3 - |
| for horizontal layout |
| GLYPH_HORIZONTAL_BEARING_Y_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph top side bearing 6.X.3 - |
| for horizontal layout |
| GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph advance width 6.X.3 - |
| for horizontal layout |
| GLYPH_VERTICAL_BEARING_X_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph left side bearing 6.X.3 - |
| for vertical layout |
| GLYPH_VERTICAL_BEARING_Y_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph top side bearing 6.X.3 - |
| for vertical layout |
| GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's glyph advance width 6.X.3 - |
| for vertical layout |
| GLYPH_HAS_KERNING_BIT_NV B GetPathMetricsNV see 5.X.1.3 whether or not glyph has kerning 6.X.3 - |
| table |
| |
| -- NEW table 6.W, "Path Font Metrics (state per path object though identical for glyphs from the same font face)" following Table 6.Z |
| |
| Get Value Type Get Command Initial Value Description Section Attribute |
| ------------------------------- ------- ---------------- ------------- --------------------------------------- ------------ --------- |
| FONT_X_MIN_BOUNDS_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's horizontal minimum (left-most) 6.X.3 - |
| of the font bounding box |
| FONT_Y_MIN_BOUNDS_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's vertical minimum (bottom-most) 6.X.3 - |
| of the font bounding box |
| FONT_X_MAX_BOUNDS_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's horizontal maximum (right-most) 6.X.3 - |
| of the font bounding box |
| FONT_Y_MAX_BOUNDS_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's vertical maximum (top-most) 6.X.3 - |
| of the font bounding box |
| FONT_UNITS_PER_EM_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's number of units in path space 6.X.3 - |
| (font units) per Em square for font |
| face |
| FONT_ASCENDER_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's typographical ascender (in font 6.X.3 - |
| units) of the font face |
| FONT_DESCENDER_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's typographical descender (in font 6.X.3 - |
| units) of the font face |
| FONT_HEIGHT_BIT_NV R+ GetPathMetricsNV see 5.X.1.3 path's font face vertical distance 6.X.3 - |
| between two consecutive baselines |
| (in font units) |
| FONT_MAX_ADVANCE_WIDTH_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's maximal advance width (in font 6.X.3 - |
| units) for all glyphs in font face |
| FONT_MAX_ADVANCE_HEIGHT_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's maximal advance height (in font 6.X.3 - |
| units) for all glyphs in font face |
| for vertical layout |
| FONT_UNDERLINE_POSITION_BIT_NV R GetPathMetricsNV see 5.X.1.3 path's position (in font units) of the 6.X.3 - |
| center of underline line for font face |
| FONT_UNDERLINE_THICKNESS_BIT_NV R GetPathMetricsNV see 5.X.1.3 thickness (in font units) of the 6.X.3 - |
| underline for font face |
| FONT_HAS_KERNING_BIT_NV B GetPathMetricsNV see 5.X.1.3 whether or not glyph has kerning 6.X.3 - |
| table |
| FONT_NUM_GLYPH_INDICES_BIT_NV Z+ GetPathMetricsNV see 5.X.1.3 number of glyph indices in font face 6.X.3 - |
| |
| Increment "n" in the Type field of the "Program Interface State" |
| table by 1 to correspond to the FRAGMENT_INPUT_NV program interface. |
| |
| Add the following rows to the table labeled "Program Object Resource |
| State" (only fragment input resources support this state): |
| |
| Initial |
| Get Value Type Get Command Value Description Sec. |
| ---------------------- ---- -------------------- --------- ------------------------------------------- ----- |
| PATH_GEN_MODE_NV Z4 GetProgramResourceiv NONE Path fragment input generation mode |
| PATH_GEN_COMPONENTS_NV Z5 GetProgramResourceiv 0 Number of path fragment input components |
| PATH_GEN_COEFF_NV 16*R GetProgramResourceiv all zeros Path fragment input generation coefficients |
| |
| New Implementation Dependent State |
| |
| None |
| |
| NVIDIA Implementation Details |
| |
| -- API revision 1.0 |
| |
| Released in NVIDIA Driver Release 275.33 (June 2011). |
| |
| -- API revision 1.1 |
| |
| Follow-on release (circa September 2011) adds these path |
| commands for ISO PDF 32000 support: |
| |
| GL_RESTART_PATH_NV |
| GL_DUP_FIRST_CUBIC_CURVE_TO_NV |
| GL_DUP_LAST_CUBIC_CURVE_TO_NV |
| GL_RECT_NV |
| |
| These path commands are not operational (generate GL_INVALID_ENUM |
| errors) if used in 275.xx or 280.xx drivers. |
| |
| Follow-on release (circa September 2011) adds these transformType |
| parameters: |
| |
| GL_NONE |
| GL_TRANSLATE_3D_NV |
| GL_AFFINE_3D_NV |
| GL_TRANSPOSE_AFFINE_3D_NV |
| |
| These transformType tokens are not operational (generate |
| GL_INVALID_ENUM errors) if used in 275.xx or 280.xx drivers. |
| |
| -- API revision 1.2 |
| |
| Follow-on release (circa December 2013) adding these commands: |
| |
| void glMatrixLoad3x2fNV(GLenum matrixMode, const GLfloat *m); |
| void glMatrixLoad3x3fNV(GLenum matrixMode, const GLfloat *m); |
| void glMatrixLoadTranspose3x3fNV(GLenum matrixMode, const GLfloat *m); |
| |
| void glMatrixMult3x2fNV(GLenum matrixMode, const GLfloat *m); |
| void glMatrixMult3x3fNV(GLenum matrixMode, const GLfloat *m); |
| void glMatrixMultTranspose3x3fNV(GLenum matrixMode, const GLfloat *m); |
| |
| void glStencilThenCoverFillPathNV(GLuint path, GLenum fillMode, |
| GLuint mask, GLenum coverMode); |
| void glStencilThenCoverStrokePathNV(GLuint path, GLint reference, |
| GLuint mask, GLenum coverMode); |
| void glStencilThenCoverFillPathInstancedNV(GLsizei numPaths, |
| GLenum pathNameType, |
| const void *paths, |
| GLuint pathBase, |
| GLenum fillMode, uint mask, |
| GLenum coverMode, |
| GLenum transformType, |
| const GLfloat *transformValues); |
| void glStencilThenCoverStrokePathInstancedNV(GLsizei numPaths, |
| GLenum pathNameType, |
| const void *paths, |
| GLuint pathBase, |
| GLint reference, uint mask, |
| GLenum coverMode, |
| GLenum transformType, |
| const GLfloat *transformValues); |
| enum glPathGlyphIndexRangeNV(GLenum fontTarget, |
| const void *fontName, |
| GLbitfield fontStyle, |
| GLuint pathParameterTemplate, |
| GLfloat emScale, |
| GLuint baseAndCount[2]); |
| |
| If the window system's GetProcAddress mechanism for GL commands returns |
| NULL for these function names, these API revision 1.2 features are |
| not available. Likewise the these tokens are not supported either. |
| |
| GL_ROUNDED_RECT_NV |
| GL_RELATIVE_ROUNDED_RECT_NV |
| GL_ROUNDED_RECT2_NV |
| GL_RELATIVE_ROUNDED_RECT2_NV |
| GL_ROUNDED_RECT4_NV |
| GL_RELATIVE_ROUNDED_RECT4_NV |
| GL_ROUNDED_RECT8_NV |
| GL_RELATIVE_ROUNDED_RECT8_NV |
| GL_RELATIVE_RECT_NV |
| |
| These tokens may be returned by glPathGlyphIndexRangeNV: |
| |
| GL_FONT_GLYPHS_AVAILABLE_NV |
| GL_FONT_TARGET_UNAVAILABLE_NV |
| GL_FONT_UNAVAILABLE_NV |
| GL_FONT_UNINTELLIGIBLE_NV |
| |
| -- API revision 1.3 |
| |
| Follow-on release (circa May 2014, first appearing in the 337.88 |
| drivers) adding these commands: |
| |
| These new path commands: |
| |
| GL_CONIC_CURVE_TO_NV |
| GL_RELATIVE_CONIC_CURVE_TO_NV |
| GL_RELATIVE_RECT_NV |
| |
| New path glyph metric query: |
| |
| GL_FONT_NUM_GLYPH_INDICES_BIT_NV |
| |
| New return values from glyph index path specification commands: |
| |
| GL_FONT_UNINTELLIGIBLE_NV |
| GL_STANDARD_FONT_FORMAT_NV |
| |
| New programInferface token: |
| |
| FRAGMENT_INPUT_NV |
| |
| New (aliased) matrix tokens for ES support: |
| |
| PATH_PROJECTION_NV |
| PATH_MODELVIEW_NV |
| |
| PATH_MODELVIEW_STACK_DEPTH_NV |
| PATH_MODELVIEW_MATRIX_NV |
| PATH_MAX_MODELVIEW_STACK_DEPTH_NV |
| PATH_TRANSPOSE_MODELVIEW_MATRIX_NV |
| PATH_PROJECTION_STACK_DEPTH_NV |
| PATH_PROJECTION_MATRIX_NV |
| PATH_MAX_PROJECTION_STACK_DEPTH_NV |
| PATH_TRANSPOSE_PROJECTION_MATRIX_NV |
| |
| New glyph index path specification commands: |
| |
| enum glPathGlyphIndexArrayNV(GLuint firstPathName, |
| GLenum fontTarget, |
| const void *fontName, |
| GLbitfield fontStyle, |
| GLuint firstGlyphIndex, |
| GLsizei numGlyphs, |
| GLuint pathParameterTemplate, |
| GLfloat emScale); |
| enum glPathMemoryGlyphIndexArrayNV(GLuint firstPathName, |
| GLenum fontTarget, |
| GLsizeiptr fontSize, |
| const void *fontData, |
| GLsizei faceIndex, |
| GLuint firstGlyphIndex, |
| GLsizei numGlyphs, |
| GLuint pathParameterTemplate, |
| GLfloat emScale); |
| |
| GLSL-related commands: |
| |
| void glProgramPathFragmentInputGenNV(GLuint program, |
| GLint location, |
| GLenum genMode, |
| GLint components, |
| const GLfloat *coeffs); |
| |
| void glGetProgramResourcefvNV(GLuint program, GLenum programInterface, |
| GLuint index, GLsizei propCount, |
| const GLenum *props, GLsizei bufSize, |
| GLsizei *length, GLfloat *params); |
| |
| If the window system's GetProcAddress mechanism for GL commands returns |
| NULL for these function names, these API revision 1.3 features are |
| not available. Likewise the these tokens are not supported either. |
| |
| -- Performance improvements: |
| |
| Release 304.xx and on substantially improves the performance of |
| path rendering stencil and cover operations on NVIDIA Fermi- and |
| Kepler-based GPUs (GeForce 400 Series and on). |
| |
| Release 314.xx improves the performance of initially specifying or |
| modifying a path object prior to stenciling or covering the paths. |
| |
| -- Bugs: |
| |
| Due to NVIDIA driver bug 1315267, path objects were not actually |
| shared among contexts prior to Driver release 320.xx (July 2013). |
| |
| Issues |
| |
| 1. What should this extension be called? |
| |
| RESOLVED: NV_path_rendering |
| |
| The extension adds an entirely new rendering paradigm for filled |
| and stroked paths, hence "path rendering". |
| |
| "path" alone was considered but deemed to vague. |
| |
| 2. Should this extension support specifying paths based on glyphs in fonts? |
| |
| RESOLVED: Yes. |
| |
| There are several problems solved by including first-class path |
| specification via glyphs in fonts. |
| |
| 1) Support for glyphs from fonts are an expected part of nearly |
| all path rendering systems. Not including glyph support will force |
| all path rendering applications to build their own glyph system. |
| |
| 2) Fonts, particularly for Asian languages, can be large. |
| By putting glyph specification from fonts directly into |
| the extension, implementations will have the opportunity to |
| cache commonly loaded font glyphs, including shared on-GPU |
| representations. |
| |
| 3) Also because fonts have many glyphs, first-pass specification |
| of a range of glyphs allows the GL implementation to load glyphs |
| sparsely in response to use. It isn't appropriate to burden |
| applications with the burden of properly caching large sets of |
| glyphs from fonts. So while Unicode glyphs 0 through 2^21-1 |
| might be loaded for an entire Unicode font, the GL implementation |
| could only actually load queried and used path objects. |
| |
| 4) Locating font files tends to be very system-specific. To the |
| extent OpenGL supports cross-platform rendering, minimizing |
| system-specific aspects of rendering increases the cross-platform |
| nature of OpenGL applications. |
| |
| 5) I still feel bad about glutBitmapCharacter and |
| glutStrokeCharacter being so lame; I thought something better |
| would take their place but nothing has. |
| |
| 3. Should this extension provide a one-shot (single-pass) way to fill |
| and stroke path objects? |
| |
| RESOLVED: No. |
| |
| The two-pass decoupling of path rendering into stenciling and |
| covering operations has lots of advantages. |
| |
| Some of the advantages are: |
| |
| 1) The cover step has complete control over how the fragment |
| shader is configured. GLSL, assembly, or fixed-function |
| (glTexEnv, glFog, etc.) fragment shading can all be used |
| without conflating the path's coverage determination with |
| the shading. |
| |
| 1a) If shading resources are used to implement the path coverage |
| determination such as interpolants or textures, these |
| resources aren't over-subscribed as could occur in a |
| one-step API. |
| |
| 2) GPUs can accelerate stencil-only rendering during the stencil |
| step in ways that are rasterization and bandwidth efficient. |
| |
| 3) Path rendering standards all allow a rendered path to be clipped |
| by another arbitrary (clipping) path. This can even be |
| done recursively sometimes. When the stencil coverage |
| determination is a separate step from the shading, such |
| clipping operations are easy to accomplish as simply multiple |
| stenciled stencil steps. Otherwise clipping a path to another |
| path is a complex intersection and re-tessellation task. |
| |
| 4) A two-step stencil, then cover" approach makes it |
| straightforward to guarantee that pixels and samples are |
| only visited once per path rendering as path rendering |
| standards require. |
| |
| 5) Unconventional but efficient algorithms such as reverse |
| Painter's algorithm are straightforward to implement when |
| stencil and covering steps are decoupled. In this case, |
| the stencil buffer simply never allows a pixel to be shaded |
| a second time once covered. |
| |
| 6) Dilations and erosions can be performed with the two-step |
| approach. You can fill a shape and then stroke the shape |
| to dilate the shape. Then cover with both fill and stroking. |
| |
| 7) Novel stroking effects such as pin-striping are easy to |
| accomplish. You can stroke a path with a stroke width of 7.5 |
| to write stencil to 1 and then stroke the same curve with |
| a stroke width of 3.1 to write a stencil of 0. Then cover |
| stroked path with a stroke width of 7.5 and accomplish the |
| pen-striping. |
| |
| 4. What string formats should be supported for paths? |
| |
| UNRESOLVED: Definitely SVG and PostScript. Perhaps Silverlight? |
| |
| Silverlight's path syntax is very similar to SVG but allows |
| infinity values and the specification of the fill mode. |
| |
| Adobe's Type 2 charstring format, part of Adobe's Compact |
| Font Format (CFF) standard, provides yet another encoding |
| of a path outline. This is a binary, rather than textual, |
| format that exists within OpenType and Type 2 font formats. |
| It includes glyph hinting information. The utility of accepting |
| the Type 2 charstring format is not sufficient for inclusion for |
| a number of reasons. Content creation tools don't target this |
| format for arbitrary path descriptions. This extension already |
| provides commands (glPathGlyphsNV and glPathGlyphRangeNV) for |
| specifying path objects from font glyphs. And the font hinting |
| information the format provides would just be ignored. |
| |
| 5. Should there be a query to return a path as a string? |
| |
| RESOLVED: No, returning dynamic strings of variable length is too hard. |
| |
| Unlike parsing which is straightforward but slightly difficult, |
| building a string from the results of glGetPathCommandsNV and |
| glGetPathCoordsNV is not hard. But there's no one "right" |
| way to build a string for a given path. |
| |
| There are various string encodings of varying compactness and |
| readability. How much precision is really required for converting |
| a floating-point coordinate to a string representation varies? |
| |
| 6. Should path rendering allow per-vertex specification of attributes? |
| |
| RESOLVED: No. |
| |
| There is no allowance for the specification of interpolants |
| (colors, texture coordinates, etc.) specified per control point. |
| Assigning per-vertex values to control points doesn't really |
| make sense in the context of path rendering. Instead a mechanism |
| for generating color, texture coordinate, and fog generation as |
| a linear function of object space. |
| |
| The glPathTexGenNV, glPathColorGenNV, and glPathFogGenNV commands |
| provide this mechanism. |
| |
| glPathColorGenNV, glPathTexGenNV, and glPathFogGenNV |
| provide a way to specify coefficients for plane equations based |
| on the object-space or eye-space (x,y,1) position of a fragment |
| generating by covering a filled or stroked path. |
| |
| For those used to conventional 3D graphics where geometry is |
| defined by meshes of triangles, not having per-vertex attributes |
| sounds really strange. But this is the natural situation for |
| path rendering. Paths do not really have vertices but rather |
| control points. |
| |
| 7. Should path rendering use the existing texture coordinate |
| generation state (glTexGen)? |
| |
| RESOLVED: No, this extension should have its own path-specific |
| texture coordinate generation state controlled by glPathColorGenNV |
| and glPathTexGenNV. |
| |
| The existing texture coordinate generation state has modes such |
| as sphere, normal, and reflection mapping that make no sense for |
| path rendering (since there are no per-vertex normals). |
| |
| Also it is very desirable to keep the per-vertex attribute |
| computations (normal transformation, lighting, texture coordinate |
| generation) completely separate from the varying computations |
| for path rendering. This means the vertex processing program |
| needed for path rendering isn't changed by state updates intended |
| to control geometric and image primitives. |
| |
| 8. How does path rendering work if all the fixed-function state, |
| particularly the modelview and projection matrices and named vertex |
| attributes (primary color, etc.) have been deprecated? |
| |
| RESOLVED: ARB_compatibility (for OpenGL 3.1) or the Compatibility |
| profile (for OpenGL 3.2 and up) is useful and supports the |
| glPathColorGenNV, glPathTexGenNV, and glPathFogGenNV commands |
| to interact properly with fixed-function OpenGL. |
| |
| NV_path_rendering assumes that the modelview and projection |
| matrices combine to transform the path into clip space. |
| Without these matrices, there's no way to get the path |
| transformed. Therefore these matrices are introduced through |
| EXT_direct_state_access commands when only the Core profile is |
| supported. |
| |
| Without ARB_compatibility or the Compatibility profile, there is |
| no way for GLSL to access built-in varyings as these have been |
| deprecated. This means generated or passed-through colors and |
| texture coordinate sets are inaccessible. There's also no longer |
| a way to compile a fragment shader that doesn't have a vertex |
| shader. The ARB_separate_shader_objects extension (core in OpenGL |
| 4.1) now allows a fragment shader to be specified in a program |
| object with a vertex shader. The ARB_program_interface_query |
| extension (core in OpenGL 4.3) allows queries to specific program |
| object resources. The glProgramPathFragmentInputGenNV provides |
| a means, in combination with the ARB_separate_shader_objects and |
| ARB_program_interface_query extensions, to configure fragment |
| input generation for GLSL fragment shaders use during the "cover" |
| step of path rendering without reference to fixed-function |
| mechanisms. |
| |
| See the "Dependencies on Core Profile and OpenGL ES" section |
| and issue 133 for more details about the Core profile support. |
| |
| 9. How does a GLSL fragment shader processing fragment generated by |
| covering path access fragment varyings? |
| |
| RESOLVED: The obvious way is to used the gl_TexCoord[], gl_Color, |
| and gl_SecondaryColor built-in varyings for texture coordinate |
| sets, primary color, and secondary color respectively. |
| |
| Any user-specified varyings will be undefined since there is no |
| upstream geometry or vertex shader to write them. |
| |
| 10. How should the command token values be assigned? |
| |
| RESOLVED: Consistent with OpenVG's enumeration values but ALSO using |
| the SVG command characters too. |
| |
| The two token addition (missing from OpenVG's supported commands) |
| are relative and absolute 7-component partial elliptical arc |
| tokens (GL_ARC_TO_NV and GL_RELATIVE_ARC_TO_NV) that include the |
| large/small and sweep flags as coordinates. These corresponds |
| to the SVG 'arcto' commands. |
| |
| Using character codes, in addition to tokens, allows simpler |
| path descriptions coded with C character arrays (strings) such |
| as "MLLCz" instead of the equivalent verbose aggregate array |
| initializer { GL_MOVE_TO_NV, GL_LINE_TO_NV, GL_LINE_TO_NV, |
| GL_CUBIC_CURVE_TO_NV, GL_CLOSE_PATH_NV }. |
| |
| Also note there are NO character codes for the eight 5-component |
| partial elliptical arc commands because these commands lack |
| exact analogues in the SVG path command syntax. |
| |
| There are also commands corresponding to PostScript's circular arc |
| commands (arc, arcn, and arct), also without character aliases. |
| |
| Unfortunately the path command token values do NOT match the |
| SVGPathSeg interface path segment type values because these |
| values overlap with the OpenVG enumeration values. |
| |
| Excepting the printable ASCII character command tokens, absolute |
| command token values should always be even, while relative |
| command token values should always be odd. |
| |
| 11. Why are the glyph metric bits in the order they are specified? |
| |
| RESOLVED: The glyph metric order matches the FreeType 2 library's |
| FT_Glyph_Metrics structure for the per-glyph metrics. The |
| per-font metric order matches the FreeType 2 library's FT_FaceRec |
| structure. |
| |
| Kerning information for a font face can be queried with the |
| separate query glGetPathSpacingNV because the kerning displacement |
| is not per-glyph, but rather dependent on a sequence of two |
| glyphs. |
| |
| 12. What glyph metric information is beyond the scope of this extension? |
| |
| RESOLVED: Metrics for vertical kerning, bi-directional layout, |
| ligatures, etc. are beyond the scope of this extension. |
| |
| Kerning information for horizontal layout is available. |
| |
| The scope of the metrics provided by this extension are sufficient |
| for basic kerned and non-kerned horizontal and non-kerned vertical |
| text layout. |
| |
| Applications that want more sophisticated metric information |
| should either query the metrics from the corresponding system |
| font directly or load the glyph outline data entirely from the |
| application. |
| |
| 13. What glyph outline information is beyond the scope of this |
| extension? |
| |
| RESOLVED: For now, normal (indicated by GL_NONE), italic, |
| bold, and bold/italic font faces are supported. Other styles |
| (small caps, etc.) may be added with future extensions to this |
| extension, but the four supported font styles are sufficient. |
| |
| This is consistent with FreeType 2's support for the |
| FT_STYLE_FLAG_ITALIC and FT_STYLE_FLAG_BOLD flags. |
| |
| 14. Should horizontal kerning information always be available? |
| |
| RESOLVED: Yes, if the font provides this kerning information. |
| |
| 15. Why is the horizontal kerning information for a pair of path |
| objects returned as a 2D (x,y) displacement? |
| |
| RESOLVED: TrueType fonts always return kerning information |
| as a sequence of horizontal displacements in x, but not y (the |
| displacement is assumed to be zero in y). However PostScript |
| fonts can support a 2D displacement. |
| |
| This matches the behavior of FreeType 2's FT_Get_Kerning function. |
| |
| Note that the returned (x,y) float pairs are NOT immediately |
| suitable to be used as values for the /transformValues/ |
| array parameter to StencilFillPathInstancedNV, |
| StencilStrokePathInstancedNV, CoverFillPathInstancedNV, or |
| CoverStrokePathInstancedNV with a /transformType/ parameter |
| of TRANSLATE_2D_NV. The application would be responsible for |
| accumulating the various translates to provide proper horizontal |
| layout. When all the y values are zero (as will often be the |
| case), GL_TRANSLATE_1D_NV could be used instead. |
| |
| 16. Should the path name zero be treated specially? |
| |
| RESOLVED: No. There's no need for specially handling the zero |
| name for a path object. |
| |
| 17. What tokens for color should glPathColorGenNV accept? |
| |
| RESOLVED: GL_PRIMARY_COLOR (from OpenGL 1.3), GL_PRIMARY_COLOR_NV |
| (from NV_register_combiners), and GL_SECONDARY_COLOR_NV (from |
| NV_register_combiners). |
| |
| GL_PRIMARY_COLOR and GL_PRIMARY_COLOR_NV have different token |
| values; to avoid an API pitfall, both are accepted. |
| |
| (There is no core GL_SECONDARY_COLOR token.) |
| |
| 18. Should two-sided color be supported for path rendering? |
| |
| RESOLVED: No. No path rendering standards support this concept. |
| |
| Two-sided lighting could be simulated with two passes and face |
| culling. |
| |
| 19. How do PostScript's user path operators correspond to |
| NV_path_rendering's path command tokens? |
| |
| RESOLVED: |
| |
| PostScript path |
| operator Path command token |
| --------------- ----------------------------- |
| arc GL_CIRCULAR_CCW_ARC_TO_NV |
| arcn GL_CIRCULAR_CW_ARC_TO_NV |
| arcto GL_CIRCULAR_TANGENT_ARC_TO_NV |
| closepath GL_CLOSE_PATH_NV |
| curveto GL_CUBIC_CURVE_TO_NV |
| lineto GL_LINE_TO_NV |
| moveto GL_MOVE_TO_NV |
| rcurveto GL_RELATIVE_CUBIC_CURVE_TO_NV |
| rlineto GL_RELATIVE_LINE_TO_NV |
| rmoveto GL_RELATIVE_MOVE_TO_NV |
| setbbox /ignored/ |
| ucache /ignored/ |
| |
| The setbbox (set bounding box) operator "establishes a bounding |
| box for the current path, within which the coordinates of all |
| subsequent path construction operators must fall." There is |
| no such requirement in this extension so this bounding box |
| information is parsed but ignored. |
| |
| The ucache (user cache) operator "notifies the PostScript |
| interpreter that the enclosing user path is to be retained in |
| the cache if the path is not already there." This notion that |
| paths are expensive and so must be cached is not particularly |
| applicable to this extension because all path object are in |
| some sense cached. Therefore the ucache operator is parsed |
| but ignored. |
| |
| 20. How do OpenVG 1.1's commands (as enumerated by the VGPathCommand |
| and VGPathCommand enumerations) correspond to NV_path_rendering's |
| path command tokens? |
| |
| RESOLVED: |
| |
| OpenVG path |
| segment command Path command token |
| ----------------- ---------------------------------------- |
| VG_CLOSE_PATH GL_CLOSE_PATH_NV |
| VG_CUBIC_TO GL_CUBIC_CURVE_TO_NV |
| VG_CUBIC_TO_ABS " |
| VG_CUBIC_TO_REL GL_RELATIVE_CUBIC_CURVE_TO_NV |
| VG_HLINE_TO GL_HORIZONTAL_LINE_TO_NV |
| VG_HLINE_TO_ABS " |
| VG_HLINE_TO_REL GL_RELATIVE_HORIZONTAL_LINE_TO_NV |
| VG_LCCWARC_TO GL_LARGE_CCW_ARC_TO_NV |
| VG_LCCWARC_TO_ABS " |
| VG_LCCWARC_TO_REL GL_RELATIVE_LARGE_CCW_ARC_TO_NV |
| VG_LCWARC_TO GL_LARGE_CW_ARC_TO_NV |
| VG_LCWARC_TO_ABS " |
| VG_LCWARC_TO_REL GL_RELATIVE_LARGE_CW_ARC_TO_NV |
| VG_LINE_TO GL_LINE_TO_NV |
| VG_LINE_TO_ABS " |
| VG_LINE_TO_REL GL_RELATIVE_LINE_TO_NV |
| VG_MOVE_TO GL_MOVE_TO_NV |
| VG_MOVE_TO_ABS " |
| VG_MOVE_TO_REL GL_RELATIVE_MOVE_TO_NV |
| VG_QUAD_TO GL_QUADRATIC_CURVE_TO_NV |
| VG_QUAD_TO_ABS " |
| VG_QUAD_TO_REL GL_RELATIVE_QUADRATIC_CURVE_TO_NV |
| VG_SCCWARC_TO GL_SMALL_CCW_ARC_TO_NV |
| VG_SCCWARC_TO_ABS " |
| VG_SCCWARC_TO_REL GL_RELATIVE_SMALL_CCW_ARC_TO_NV |
| VG_SCUBIC_TO GL_SMOOTH_CUBIC_TO_NV |
| VG_SCUBIC_TO_ABS " |
| VG_SCUBIC_TO_REL GL_RELATIVE_SMOOTH_CUBIC_TO_NV |
| VG_SCWARC_TO GL_SMALL_CW_ARC_TO_NV |
| VG_SCWARC_TO_ABS " |
| VG_SCWARC_TO_REL GL_RELATIVE_SMALL_CW_ARC_TO_NV |
| VG_SQUAD_TO GL_SMOOTH_QUADRATIC_CURVE_TO_NV |
| VG_SQUAD_TO_ABS " |
| VG_SQUAD_TO_REL GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV |
| VG_VLINE_TO GL_VERTICAL_LINE_TO_NV |
| VG_VLINE_TO_ABS " |
| VG_VLINE_TO_REL GL_RELATIVE_VERTICAL_LINE_TO_NV |
| |
| 21. What should the initial GL_PATH_FILL_MODE_NV state be? |
| |
| RESOLVED: GL_PATH_FILL_MODE_NV should initially be |
| GL_COUNT_UP_NV. |
| |
| This is consistent with SVG default non-zero fill rule and the |
| typical usage of PostScript. |
| |
| However this is the opposite of Silverlight's default fill rule |
| which is even-odd. |
| |
| 22. Should we support a GL_PATH_FORMAT_SL3_NV for Silverlight 3.0 be |
| added? |
| |
| UNRESOLVED: Silverlight 3.0's path markup syntax includes |
| support for two extensions of the SVG 1.1 path grammar: 1) |
| specification of a fill rule ("F0" is even-odd, "F1" is non-zero) |
| at the beginning of the string; and 2) allowing "Infinity", |
| "-Infinity" and "NaN" (all case-sensitive) as special values |
| allowed instead of standard numerical values. |
| |
| Seems like a reasonable thing to support. |
| |
| The fill rule specification is straightforward. This would |
| simply allow the path object's GL_PATH_FILL_MODE_NV parameter to |
| be specified as part of the path string specification. The "F0" |
| or "F1" would not be treated as an actual path command however. |
| |
| Note that Silverlight's default fill rule if none is specified is |
| EvenOdd whereas NV_path_rendering's default GL_PATH_FILL_MODE_NV |
| is GL_COUNT_UP_NV (essentially a non-zero rule). So specifying a |
| path with the Silverlight format would have a different initial |
| value for GL_PATH_FILL_MODE_NV if "F0" or no initial F |
| command is specified. |
| |
| What exactly would it mean to allow infinite and not-a-number |
| values for the coordinate values of a path object? Infinite is |
| probably representable today by simply writing a number with a |
| sufficiently large enough magnitude. Allowing not-a-number is |
| probably more |
| |
| 23. Should there be some maximum specified limit for the number of |
| command (and hence coordinates) in a path object? |
| |
| RESOLVED: No. The standards for path rendering do no generally |
| have limits on path command lengths. |
| |
| For extreme cases, the OUT_OF_MEMORY error would be generated but |
| that is considered an exceptional case due to memory exhaustion, |
| not simply the specification of a huge path. |
| |
| 24. Should there be some maximum specified limit for the dash array? |
| |
| RESOLVED: No. The standards for path rendering do not generally |
| have a limit on the dash array length. |
| |
| 25. How do the client-defined clip planes and the clip volume interact |
| with path rendering? |
| |
| RESOLVED: Stenciled and covered paths are affected by both the |
| clip volume and client-defined clip planes. |
| |
| Clip planes affect the set of accessible pixels for stenciling |
| and covering operations (see the "ACCESSIBLE SAMPLES WITH RESPECT |
| TO A TRANSFORMED PATH" subsection of section 5.X.2.1). |
| |
| 26. What should the end cap style be called that adds no additional |
| cap region to a stroked path? |
| |
| RESOLSVED: FLAT. |
| |
| FLAT is already an existing OpenGL token name. Silverlight and |
| the OpenXML Paper Specification (XPS) calls this end cap style |
| "flat". However PostScript, Flash, OpenVG, SVG, Quartz 2D, |
| and Cairo Graphics all call this end cap style "butt". |
| |
| Using FLAT also avoids verbalizing the awkward phrase "butt |
| stroking" (not that there's anything wrong with that). |
| |
| 27. Should the PostScript grammar for user-defined paths be supported? |
| |
| RESOLVED: Yes. PostScript has commands (arc, arcn, arct) that |
| do not correspond to precisely to SVG command. This is |
| particularly true of arct. |
| |
| Applications have been generating paths according to the syntax |
| of Level 2 PostScript for a long time. |
| |
| Level 2 PostScript also has support for binary encoding that |
| makes it significantly more compact and less expensive to parse |
| than the SVG grammar. |
| |
| The binary encoding allows precise floating-point (and compact |
| fixed-point) values to be specified. |
| |
| 28. Should the PostScript grammar support big-endian, little-endian, |
| and native numeric encodings? |
| |
| RESOLVED: Yes, yes, yes. |
| |
| 29. Should the PostScript grammar support encoded user paths? |
| |
| RESOLVED: Yes. |
| |
| 30. How should the PostScript grammar support strings? |
| |
| UNRESOLVED: Hexadecimal encoded data, that is strings enclosed |
| in < and >, are supported. |
| |
| Strings for ASCII base-85 encoded data, that is strings enclosed |
| in <~ and ~>, are supported for the data-array and operator-string |
| production |
| |
| Also the short-binary-string, be-long-binary-string, and |
| le-long-binary-string productions allow very compact and precise |
| encoding of operator strings through binary encoding. |
| |
| Strings for literal text, that is strings enclosed in ( and ), |
| are NOT supported. |
| |
| The rationale for not supporting literal text is this format |
| is awkward for encoding the operator-string production (though |
| PostScript does technically allow it) and is not compact. |
| |
| 31. Should the PostScript grammar support Binary Object Sequences? |
| |
| RESOLVED: No. |
| |
| Binary Object Sequences are intended to support complex |
| (potentially nested) data structures and are over-kill for |
| user paths. |
| |
| 32. Why are the binary tokens in the PS grammar assigned the values |
| they are assigned? |
| |
| RESOLVED: These values are from the "Binary Tokens" section of |
| the PostScript Language Reference Manual. |
| |
| 33. Why are the binary encodings for the path commands in the PS |
| grammar assigned the specified values? |
| |
| RESOLVED: These values match PostScript's system name table |
| values. These are documented in the "System Name Encodings" |
| appendix of the PostScript Language Reference Manual. |
| Specifically (in decimal): |
| |
| Index Name |
| ----- --------- |
| 22 closepath |
| 99 lineto |
| 107 moveto |
| 133 rlineto |
| 134 rmoveto |
| 143 setbbox |
| 43 curveto |
| 122 rcurveto |
| 5 arc |
| 6 arcn |
| 7 arct |
| 177 ucache |
| |
| 34. Why do glGetPathCommandsNV, glGetPathCoordsNV, and |
| glGetPathDashArrayNV have their own queries? Could there not |
| simply be a token for glGetPathParameteriv/glGetPathParameterfvNV |
| to return this state? |
| |
| RESOLVED: These queries for path commands, coordinates, and |
| the path's dash array return a variable payload of data so are |
| more like glGetTexImage than glGetIntegerv/glGetFloatv which |
| return a static amount of data. |
| |
| APIs that return variable amounts of data are prone to buffer |
| overflows. It is somewhat more obvious these commands return |
| a variable amount of data if they have their own API calls, than |
| simply having certain token values to a multi-purpose glGet* call |
| that mysteriously returns varying amounts of data for these token |
| values while all the other tokens return static amounts of data. |
| |
| This resolution follows the existing precedent from |
| core OpenGL where glGetColorTable is distinct from |
| glGetColorTableParameter{fv,iv}. Same with glGetConvolutionFilter |
| and glGetHistogram relative to glGetConvolutionParameter{fv,iv} |
| and glGetHistogramParameter{fv,iv}. |
| |
| (There is a poor precedent for having an OpenGL query return both |
| static and varying amounts of data based on a pname parameter. |
| glGetMap{dv,fv,iv} returns varying data when GL_COEFF is queried |
| while GL_ORDER and GL_DOMAIN return n and 2*n values respectively |
| where n is the dimensionality of the map target. This isn't a |
| good precedent and is obscure.) |
| |
| 35. How should the GL_PATH_*_BOUNDING_BOX_NV path parameters be |
| returned? |
| |
| RESOLVED: In (x1,y1,x2,y2) order where (x1,y1) is the minimum |
| bounds of the bounding box and (x2,y2) is the maximum bounds. |
| |
| This is contrary to the precedent of GL_SCISSOR_BOX query |
| which returns the scissor as an (x,y,width,height) 4-tuple. |
| While that makes sense for a scissor box, particularly given how |
| the scissor is specified with glScissor, it is not a convenient |
| way to specify a bounding box. |
| |
| The (x1,y1,x2,y2) format also makes the |
| glCover{Fill|Stroke}PathInstancedNV pseudo-code work nicely |
| with glRectf. See the renderBoundingBox pseudo-code. |
| |
| The (x1,y1,x2,y2) format is also consistent with the way |
| FreeType 2 provides per-font face bounds information through |
| the GL_FONT_X_MIN_BOUNDS_BIT_NV, GL_FONT_Y_MIN_BOUNDS_BIT_NV, |
| GL_FONT_X_MAX_BOUNDS_BIT_NV, and GL_FONT_Y_MAX_BOUNDS_BIT_NV |
| metric queries. |
| |
| 36. Why is font loading part of this extension? Shouldn't OpenGL |
| stick with just rendering and not involved itself with fonts? |
| |
| RESOLVED: An explicit goal of this extension is to provide |
| GPU-accelerated path rendering that INCLUDES excellent support |
| for glyphs and their associated metrics. |
| |
| The fact is all the major existing standards for path rendering |
| (PostScript, SVG, OpenVG, Java 2D, Quartz 2D, Flash) include |
| first-class font and glyph support. |
| |
| Not including font and glyph support would be a glaring omission |
| that would make this extension much less useful to simple OpenGL |
| applications that don't want to incorporate large font libraries. |
| |
| Additionally font loading is notoriously platform dependent. |
| This extension provides a simple platform-independent mechanism to |
| rendezvous with standard font names. However an implementation of |
| this extension can make use of whatever platform-specific font |
| services the platform provides (such as through DirectWrite, |
| etc.). |
| |
| Fonts, particularly for Asian languages or designed to support a |
| large portion of Unicode, are large. Populating their complete |
| outlines can consume substantial amounts of system and video |
| memory. Many applications on a system are likely to access |
| the same collections of fonts. Having fonts loaded by name |
| allows GL implementations to coordinate the efficient sharing |
| of font outline data among multiple GL application instances. |
| This font sharing can have a substantial reduction in the total |
| system resources devoted to font data which is not possible if |
| the GL is unable to be aware of duplicated font outline data |
| within the system. |
| |
| Font formats change and evolve over time. Building font format |
| knowledge into applications will ultimately be limiting long-term. |
| |
| Fonts are really properly thought of as system resources. |
| They represent intellectual property that is typically licensed |
| on a per-system basis. Building font access into the GL promotes |
| use of the system's properly licensed fonts. Most applications |
| do not want to be encumbered by licensing issues associated with |
| fonts so to the extent that the API makes access to system fonts |
| easier, that promotes properly licensed use of fonts. |
| |
| 37. What is the typographical philosophy for this extension? |
| |
| RESOLVED: This extension relies on other standards to provide |
| its typographic backbone and philosophy. |
| |
| The character set supported depends on the Unicode standard. |
| |
| Specific font formats supported depend on the system but the |
| expectation is that standard TrueType, PostScript, and OpenType |
| fonts can be used through this extension. The metrics from such |
| fonts will generally be "passed through" the glGetPathMetricsNV |
| query. |
| |
| The naming of fonts is consistent with the underlying system |
| with the expectation that the system's naming is consistent with |
| modern web standards for identifying fonts in web content. |
| |
| While the specific set of supported fonts may vary from system to |
| system based on the available installed fonts, the expectation is |
| that standard TrueType fonts such as Arial, New Courier, Georgia, |
| etc. will be available on systems that support this extension. |
| |
| For applications that demand a set of glyphs that are guaranteed |
| to be available, the GL_STANDARD_FONT_NAME font target is |
| available for the names "Sans", "Serif", and "Mono" and these |
| fonts are understood to match a set of glyphs consistent with the |
| DejaVu font set populated with at least the Latin-1 character set. |
| |
| The underlying font engine is likely to be FreeType 2 or the |
| system's native font engine (such as DirectWrite for newer |
| Windows versions). |
| |
| 38. What is the path rendering philosophy for this extension? |
| |
| RESOLVED: Two-step stencil-based GPU-acceleration + broad-tent |
| support for the accepted functionality of path rendering. |
| |
| This extension assumes that the two-step "stencil, then cover" |
| stencil-based approach to GPU-accelerating path rendering. |
| |
| Both stenciling and stroking are supported. Strokes are |
| first-class representations and not treated as fills that |
| approximate the stroked region. For pragmatic reasons, cubic |
| Bezier segments, conic segments, and partial elliptical |
| (non-circular) arcs path segments are assumed to be approximated |
| by a sequence of quadratic Bezier path segments that guarantee |
| G1 continuity. |
| |
| The contrapositive of this approach is an avoidance of schemes |
| based on tessellation of path outlines. |
| |
| Paths are defined using both cubic and quadratic Bezier curves. |
| This broadly allows path content from TrueType (based on quadratic |
| Bezier curves) and PostScript and its font families (based on |
| cubic Bezier curves) to be supported. |
| |
| Arcs are drawn consistent with both SVG (partial elliptical arcs) |
| and PostScript (circular arcs and circular tangent arcs). |
| |
| The set of stroking options is a union of the stroking features |
| of OpenVG, SVG, XML Paper Specification (XPS), PostScript, and |
| other standards. For example, XPS supports dash caps that other |
| standards lack. |
| |
| The path queries support the key path queries supported by OpenVG. |
| |
| 39. Should there be an API for assigning path metric information to |
| a path object? |
| |
| RESOLVED: No. |
| |
| Path metrics are available when a path object is created with |
| glPathGlyphsNV or glPathGlyphRangeNV. In these cases, the font |
| supplies the metric data for these path objects. |
| |
| It might be useful to allow these metrics to be specified for an |
| arbitrary path object. This way user-defined path objects could |
| appear to have metrics available as if they had been specified |
| by glPathGlyphsNV or glPathGlyphRangeNV. |
| |
| Supporting the specification of path metrics would require new |
| API. Something like glPathMetricsNV perhaps? Or having parameter |
| names for the font metrics supported by glPathParameter{f,i}v? |
| The later approach would probably require new tokens and would |
| mean glGetPathParameter{f,i}v should support these tokens too. |
| |
| Since the metrics are for information purposes only, meaning |
| the rendering functionality for paths never involves the metrics |
| (unlike other path parameters), it seems odd to allow information |
| to be specified just so it can be queried by the application. |
| This doesn't feel like essential functionality though its |
| absence may be missed by library developers that want to "fake" |
| font loaders. |
| |
| 40. What happens when an input path object to glWeightPathsNV, |
| glInterpolatePathsNV contains an arc command when there are two |
| or more path objects involved? |
| |
| RESOLVED: An INVALID_OPERATION error is generated. |
| |
| In general, arc commands are not "closed" under linear |
| combination. Said another way, the linear combination of two |
| or more arcs is not, in general, itself an arc of the same form. |
| |
| glCopyPathNV copies outlines for path objects containing any |
| valid commands including arc commands. |
| |
| 41. When a path object is created from other existing path objects |
| through the glWeightPathsNV, glInterpolatePathsNV, or glCopyPathNV |
| commands, where does the new path's parameters come from? |
| |
| RESOLVED: While the path commands are interpolated on a |
| command-by-command basis with these commands, the path parameters |
| should be copied from the first path object specified. |
| |
| So for glWeightPathsNV, glInterpolatePathsNV, and glCopyPathNV, |
| the path parameters from the path[0], pathA, and srcPath |
| parameters respectively. |
| |
| 42. How is the glyph metric and kerning information specified for |
| a path object created from other existing path objects through the |
| glWeightPathsNV, glInterpolatePathsNV, or glCopyPathNV commands, |
| where does the new path's parameters come from? |
| |
| RESOLVED: The path metric information is set to negative one |
| for glWeightPathsNV and glInterpolatePathsNV. |
| |
| There's no reasonable way to weight the metric information. |
| Metric information is tuned to a particular glyph. |
| |
| More explicitly, the path metric information from the first path |
| object to be combined is NOT copied (as the parameters are). |
| |
| However glCopyPathNV does copy the glyph metric and kerning |
| information (since only one path object is involved so there's |
| no combination of outlines). |
| |
| 43. Should there be a way to specify different stroking parameters |
| (stroke width, end caps, etc.) within the command sequence of |
| a path? |
| |
| RESOLVED: No. |
| |
| Existing path rendering standards keep the stroking parameters |
| constant for a given path's outline. For example, there's not |
| support for a dashed stroked segment of width 5.0 as well as a |
| non-dashed stroked segment with width 9.4 in the same path. |
| |
| This wouldn't be impossible to support; commands that changed |
| stroking parameters could be supported within the command |
| sequence. However it would complicate the meaning of the path |
| parameters for stroking; these parameters could be considered |
| defaults for stroking parameters if stroking parameters are not |
| otherwise specified. There's also the complication of when |
| new stroking parameters would latch into place. Would it be |
| immediately (mid path?) or not latch until the next "moveto" |
| command? And how would such commands be weighted/interpolated? |
| |
| Attempting to support changing stroking parameters within a path |
| appears to open up a complicated can of worms. |
| |
| The same rendering effect can be achieved with the |
| gl{Stencil,Cover}StrokePathInstancedNV commands using multiple |
| path object, each with the appropriate stroking parameters for |
| the appropriate path segments. |
| |
| 44. What should the query token for the path color and texture |
| coordinate generation coefficients be named? |
| |
| RESOLVED: GL_PATH_GEN_COEFF_NV. |
| |
| Alternatively this could be GL_PATH_GEN_COEFF_NV (plural), |
| but that doesn't match the precedent set by GL_COEFF used by |
| glGetMap{f,d}v. These existing queries return a plurality of |
| coefficients too. |
| |
| 45. What should the number of coefficients returned when querying the |
| path color and texture coordinate generation coefficients depend |
| on the current path color or texture coordinate generation mode or |
| should a fixed maximum number of coefficients always be returned? |
| |
| RESOLVED: A fixed maximum of 16 coefficients should always |
| be returned. |
| |
| It is error-prone and likely to result in obscure buffer |
| overflow cases if the number of coefficients returned depends |
| on the respective current path generation mode. It is better |
| to simply always return 16 values. Unused coefficients by the |
| current generation mode should always be returned as zero. |
| |
| 46. How does glGetPathLengthNV compare to OpenVG's vgPathLength? |
| |
| RESOLVED: glGetPathLengthNV and vgPathLength compute |
| essentially the same result except glGetPathLengthNV returns |
| 0 when /numSegments/ is 0 whereas vgPathLength considers this |
| case an error. |
| |
| 47. Where does all the discussion of partial elliptical arc |
| parameterization come from? |
| |
| RESOLVED: This discussion is based on and fully consistent with: |
| |
| http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes |
| |
| 48. Where does the parameterization of the |
| GL_CIRCULAR_TANGENT_ARC_TO_NV come from? |
| |
| RESOLVED: The GL_CIRCULAR_TANGENT_ARC_TO_NV is based on the |
| PostScript arct command (which is based on arcto) for user paths. |
| |
| See the gs_arcto routine in: |
| |
| http://svn.ghostscript.com/ghostscript/trunk/gs/base/gspath1.c |
| |
| 49. How should fog coordinate generation work for path rendering? |
| |
| RESOLVED: The glPathFogGenNV command controls how generation |
| of the fog coordinate operates for path rendering commands. |
| |
| The GL_FOG enable is tricky because it controls both per-vertex and |
| per-fragment processing state (unlike per-vertex lighting and texture |
| coordinate generation). |
| |
| Simply using the existing fixed-function fog coordinate state is |
| undesirable because that 1) entangles fog coordinate generation |
| with conventional vertex processing and path vertex processing, |
| and 2) the NV_fog_distance extension allows a non-linear fog |
| coordinate to be generated through the GL_EYE_RADIAL_NV mode. |
| |
| The fog coordinate generation for path rendering can either |
| use the fog coordinate "as is" for the entire covered path or |
| have the fog coordinate be the negated perspective-divided |
| eye-space Z component (which can vary, but only linearly). |
| |
| 50. What should glyph metrics return for path objects not specified |
| by glPathGlyphsNV or glPathGlyphRangeNV? |
| |
| RESOLVED: All queried metrics should return the value -1. |
| |
| Negative values are out-of-range for many of the metric values so |
| negative values provide a reliable indicator that a path object |
| was not specified from a glyph. |
| |
| 51. How should the fill mode state of path objects created from |
| glyphs be initialized? |
| |
| RESOLVED: The initial GL_PATH_FILL_MODE_NV for path objects |
| created from glyphs depends on the source font's convention. |
| |
| Typically TrueType and newer (all?) PostScript fonts depend on the |
| non-zero fill rule. TrueType fonts assume a clockwise outline |
| winding (hence will use GL_COUNT_DOWN_NV) while PostScript |
| fonts assume a counterclockwise outline winding (hence will |
| use GL_COUNT_UP_NV). |
| |
| It's unlikely an actual font will use GL_INVERT as its |
| GL_PATH_FILL_MODE_NV but the possibility is allowed. |
| |
| 52. Should other path object parameters other than the fill mode be |
| initialized specially when path objects are specified from glyphs? |
| |
| RESOLVED: No. |
| |
| In theory, other path parameters such as stroke width, join style, |
| etc. could all be specified from the font. In practice, most |
| font forms don't provide such parameters. |
| |
| At least one font format, Bitstream's PFA format, does provide |
| such information though how applicable these parameters are to |
| a path object is unclear. The availability of these parameters |
| appears to be intended as a way to bold or otherwise dilate the |
| glyph's outline rather than being intended for stroking. |
| |
| SVG supports stroking of fonts but the stroke-width tag is |
| specified in the current user coordinate system rather than |
| depending on the particular font or its glyphs. |
| |
| 53. How should the integers passed to glPathGlyphsNV and |
| glPathGlyphRangeNV be mapped to actual glyph outlines for a font? |
| |
| RESOLVED: The integers that come from the charcode array or |
| the firstGlyph to firstGlyph+numGlyphs-1 range are treated as |
| Unicode character codes if the font has a meaningful mapping of |
| Unicode to its glyphs. |
| |
| The existence of a meaningful mapping from Unicode to glyph |
| outlines is the expected situation. For fonts without a |
| meaningful mapping to Unicode character codes (such as custom |
| symbol fonts), the font's standard mapping of character codes to |
| glyphs should be used. This situation should be rare, probably |
| due to a font that is poorly authored, very old, or custom built. |
| |
| 54. How are typographical situations such as ligatures, composite |
| characters, glyph substitution, and language-dependent character |
| sequence conversion handled? |
| |
| RESOLVED: If a particular behavior is desired for how such |
| situations are handled, that is up to the application software |
| using this extension. |
| |
| For example, in the case of ligatures, multiple Unicode characters |
| may map to a single ligature glyph. Support for ligatures is |
| a stylistic typographic decision and the application is free to |
| handle this in any of a number of ways; this extension neither |
| forces nor precludes specific approaches to handle ligatures. |
| The application can overlap existing glyphs to create the |
| appearance of a path object by rendering the individual multiple |
| Unicode characters overlapped; a ligature character that is |
| part of the Unicode character set could be selected; or the |
| application could create its own custom path object in this |
| situation and render it. |
| |
| For composite characters, the underlying font engine used to |
| implement this extension may construct composite characters. |
| Or this may be a situation where, due to limitations of the |
| font or font engine, possibly in combination, this is treated as |
| an unknown or missing character where implementation-dependent |
| handling is possible. Such a situation could also exist for a |
| ligature character specified by Unicode. |
| |
| In general, higher level details of text presentation such |
| as ligatures, composite characters, glyph substitution, and |
| language-dependent character sequence conversion are beyond the |
| scope of this extension. |
| |
| See the Unicode FAQ on "Ligatures, Digraphs and Presentation |
| Forms": |
| |
| http://www.unicode.org/faq/ligature_digraph.html |
| |
| In complicated typographical situations, the assumption is that |
| the application will construct the appropriate inter-glyph |
| transformation values (the transformValues and transformType |
| for glStencilFillPathInstancedNV and glCoverFillPathInstancedNV) |
| and build digraphs or other presentation forms. |
| |
| 55. Are relative path commands converted to absolute commands upon |
| path specification? |
| |
| RESOLVED: No, relative commands are first-class and are |
| maintained as relative commands. |
| |
| This includes when relative commands are created by copying, |
| interpolating, or weighting existing path objects. Relative path |
| commands must match identical relative path commands and their |
| relatively control points are weighted as relative position |
| offsets. |
| |
| Another implication if this is that if an application modifying |
| the control points with glPathSubCoordsNV, those edits can effect |
| the outline of subsequent relative commands that depend on the |
| modified coordinates. |
| |
| The same applies to changing commands. Editing commands with |
| glPathSubCommandsNV can change how coordinates are interpreted |
| for the edited commands and subsequent relative commands. |
| |
| In other words, if a path object is modified or edited, the |
| outline of the path is the same as if the path object had been |
| specified from scratch with the same command and coordinate |
| sequences. |
| |
| 56. What does this extension do with so-called "hinting" in outline |
| font glyphs? |
| |
| RESOLVED: When a path object is specified from the glyph of a |
| font, the path object's outline is specified from the "ideal" |
| resolution-independent form of the glyph. |
| |
| This is because a path object is rendered (stenciled or covered) |
| from a resolution-independent form. There is an implicit |
| assumption in the specified transformation and rendering process |
| that the process is unaware of the device coordinate grid. |
| |
| This means there's not the knowledge of device coordinate space |
| necessary to apply hinting information. |
| |
| In TrueType terms, this amounts to the path object's outline for |
| a TrueType glyph being the glyph's "master outline". This means |
| the TrueType instructions associated with the glyph are ignored |
| and not executed. |
| |
| While it is beyond the scope of this extension, there's nothing |
| in this extension that keeps an application in decoding itself the |
| TrueType master outline of a glyph and performing the grid-fitted |
| outline generation at a given arbitrary device resolution. |
| Then this fitted outline could be specified for a path object. |
| The key observation is that doing so makes the resulting outline |
| resolution-dependent which obviates much of the advantage of |
| this extension's ability to render from a resolution-independent |
| outline. |
| |
| Rather than relying on hinting for legibility, applications using |
| this extension are likely to rely on multisampling or multiple |
| jittered rendering passes for antialiasing and assume a certain |
| amount of grayscale appearance as a consequence. |
| |
| 57. If a font format has bitmap font data, is that used? |
| |
| RESOLVED: No, only resolution-independent outline data is used; |
| bitmap data is ignored. Bitmap-only font formats won't be loaded. |
| |
| In the FreeType 2 API, the information available is comparable |
| to calling FT_Load_Glyph with the FT_LOAD_NO_SCALE and |
| FT_LOAD_NO_BITMAP flags specified. |
| |
| 58. How is antialiasing of path object rendering accomplished? |
| |
| RESOLVED: Multisampling is the expected way that antialiasing |
| will be accomplished when rendering path objects. |
| |
| Recall in multisampling that the stencil buffer is maintained |
| at per-sample resolution. This means the coverage determined |
| by stenciling path objects should be accurate to the sample |
| resolution. |
| |
| If a multisampled framebuffer provides N samples per pixel, that |
| means that there are N+1 possible coverage weightings of a given |
| path with respect to that pixel, assuming a single "stencil, then |
| cover step", equal weighting of samples in the final pixel color, |
| and the samples for a given pixel belonging to a single pixel. |
| |
| One explicit goal of this extension is to maintain a separation |
| between coverage and opacity. The two concepts are often |
| conflated treating both as percentages and then modulating |
| opacity with coverage. Conflating the two leads to coverage |
| bleeding at what should be sharp, though transparent, edges and |
| corners. |
| |
| In this extension, the stencil buffer maintains coverage and |
| the alpha channel for RGBA colors, which is per-sample when the |
| framebuffer format supports multisampling, maintains opacity. |
| |
| Philosophically this extension provides a robust and accurate |
| mechanism for determining point-sampled coverage for arbitrary |
| filled and stroked paths. The extension does not rely on, nor |
| does it even attempt, to compute or approximate a path's area |
| coverage with respect to a pixel. For practical reasons, such |
| analytical computations are inevitably approximations for |
| arbitrary paths and are difficult to make robust. |
| |
| Point sampling of path object rasterization can offer more |
| robustness and precision. Point sampling also allows this |
| extension's rendering results to seamlessly co-exist with OpenGL's |
| conventional point, line, and polygon rasterization approaches |
| which are point-sampled. |
| |
| The implication of this observation is path rendered content can |
| be mixed with arbitrary OpenGL 3D content, whether rendered with |
| depth testing or not. This provides the very powerful ability to |
| mix path rendered and 3D rendered content in the same framebuffer |
| in predictable ways with negligible overhead for doing so. |
| |
| Keep in mind that 2D path rendered content is transformed by the |
| projective modelview-projection transform, just like other OpenGL |
| rendering primitives, so fragments generated with path rendering |
| have varying depth values that can be depth tested, fogged, etc. |
| |
| Point sampling is prone to missing coverage but avoids indicating |
| coverage where no actual coverage exists. |
| |
| This extension implicitly assumes that GPUs have some maximum |
| sample location precision while rasterizing. This is an artifact |
| of subpixel precision. This concept is built into OpenGL; see |
| the GL_SUBPIXEL_BITS implementation-dependent limit. Developers |
| should not expect any additional sampling precision beyond this |
| limit. To get beyond this limit, applications would be expected |
| to render at a larger framebuffer resolution and downsample to |
| the appropriate resolution or render in some tiled fashion. |
| |
| If multisampling provides insufficient antialiasing, further |
| antialiasing is possible by rendering with multiple passes. |
| |
| For example, applications can use accumulation buffer techniques |
| with sub-pixel jittered re-rendering of the entire scene |
| to improve the overall quality. This provides full-scene |
| antialiasing. |
| |
| Alternatively, a path object itself needing extra antialiasing, |
| perhaps because the application has determined the path object |
| maps to a small region of the framebuffer in window space, can |
| be rendered multiple times, each time with subpixel jittering. |
| By writing just into the non-visible alpha component of the |
| framebuffer, a coverage percentage at each color sample can |
| be accumulated. Then a final cover operation can blend this |
| coverage information into the visible RGB color channels. |
| |
| Despite the multiple passes involved, this approach can still |
| be several times faster than CPU path rendering methods because |
| of the rendering rate possible through GPU acceleration. |
| |
| 59. How do the multisample fragment operations interact with path |
| rendering? |
| |
| RESOLVED: They are ignored for the "stencil" path rendering |
| operations (since only the stencil buffer is updated), and they |
| work as specified for the "cover" path rendering operation. |
| |
| The coverage determination made during the "cover" path |
| rendering operation doesn't reflect the path itself but rather |
| the conservative coverage provide by the covering operation. |
| For this reason, the coverage mask is conservative, meaning |
| samples may be covered that don't actually belong to the filled |
| or stenciled region of the path being covered. And exactly how |
| conservative this coverage is depends on the implementation. |
| |
| Still the coverage is available and can be used as specified in |
| section 4.1.3 ("Multisample Fragment Operations"). |
| |
| The GL_SAMPLE_COVERAGE mode would be more useful if the stencil |
| testing was performed prior to the shading of the covered geometry |
| and the covered sample mask reflected any discards performed by |
| the stencil (or depth) tests. |
| |
| The NV_explicit_multisample extension and its |
| ARB_texture_multisample functionality (standard with OpenGL 3.2) |
| provide explicit control of the multisample mask. This mask is |
| respected for path rendering. |
| |
| 60. Does creating multiple instances of path objects from the same |
| glyph in the same font face "waste memory"? What about copies |
| of objects created with glCopyPathNV? |
| |
| RESOLVED: This is an implementation issue, but it is reasonable |
| to expect that copies of path objects created with glCopyPathNV |
| will share their outline data on a copy-on-write basis. This is |
| true even if a path object is copied and its path parameters |
| are modified (but not the path commands and coordinates). |
| |
| It is also reasonable to expect that path objects created with |
| glPathGlyphsNV may use copies if there are replicated character |
| codes. While glPathGlyphRangeNV isn't subject to replicated |
| character codes, if two or more character codes share the same |
| glyph, it would be reasonable to expect the implementation might |
| share the outline data. |
| |
| It's always possible to use glPathSubCommandsNV or |
| glPathSubCoordsNV to modify the path commands and/or coordinate |
| data so then sharing will have to be broken. |
| |
| 61. Why does glPathGlyphsNV (and hence glPathGlyphRangeNV as well) |
| not disturb path objects that already exist in the range of path |
| objects to be created? |
| |
| RESOLVED: This facilitates a strategy for supporting multiple |
| font names specified in preferential order. |
| |
| An application can do something like: |
| |
| GLint firstPathName = glGenPathsNV(256); |
| const GLfloat emScale = 2048; |
| glPathGlyphRangeNV(firstPathName, GL_SYSTEM_FONT_NAME_NV, |
| "Helvetica", GL_NONE, 0, 256, emScale); |
| glPathGlyphRangeNV(firstPathName, GL_SYSTEM_FONT_NAME_NV, |
| "Arial", GL_NONE, 0, 256, emScale); |
| glPathGlyphRangeNV(firstPathName, GL_STANDARD_FONT_NAME_NV, |
| "Sans", GL_NONE, 0, 256, emScale); |
| |
| This ensures that path object names /firstPathName/ through |
| /firstPathName/+255 will be loaded with the glyphs from Helvetica, |
| Arial, or the guaranteed-present Sans font face, in that order |
| of preference. |
| |
| This is consistent with the CSS font-family property used in |
| web standards, including SVG. |
| |
| 62. Why are the angles for the arc path commands specified with |
| degrees (instead of radians)? |
| |
| RESOLVED: Using degrees is consistent with OpenGL's existing |
| glRotatef, glRotated, and gluPerspective commands. |
| |
| Using degrees for angles is also consistent with the conventions |
| of the PostScript, SVG, and OpenVG commands upon which the arc |
| path commands are based. |
| |
| Using degrees (90 degrees, 30 degrees, 45 degrees) also allows |
| important angles be represented exactly with integer values. |
| This is relevant for compact coordinate formats and paths defined |
| by strings. |
| |
| 63. Should UTF-8 and UTF-16 be supported for arrays of path names? |
| |
| RESOLVED: Yes. |
| |
| 64. What order should the arguments be listed when a array of |
| path objects with typed elements and a base are specified? |
| |
| RESOLVED: |
| |
| 1) sizei count, |
| 2) enum pathNameType, |
| 3) const void *paths, |
| 4) uint pathBase |
| |
| The standard OpenGL parameter pattern is count/type/array. |
| Examples of this are glDrawElements and glCallLists. |
| (More generally the pattern is count/format/type/array.) |
| |
| Having the pathBase parameter last matches the precedent set by. |
| glDrawElementsBaseVertex where the base vertex value follows |
| the list of element indices. Hence the pattern |
| count/type/array/base. |
| |
| The basevertex parameter to glDrawElementsBaseVertex is typed |
| GLint; the pathBase parameter is typed GLuint. GLuint makes |
| sense to avoid useless signed/unsigned mismatch warnings from |
| C compilers when most values passed to pathBase parameters are |
| likely to be from GLuint variables. When GLuint and GLint are |
| both 32-bit data types, the choice is not consequential. |
| |
| Commands that use this order are glStencilFillPathInstancedNV, |
| glStencilStrokePathInstancedNV, glCoverFillPathInstancedNV, |
| glCoverStrokePathInstancedNV, glGetPathMetricsNV, and |
| glGetPathSpacingNV. |
| |
| 65. What order should the arguments be listed when a range of |
| path objects is specified? |
| |
| RESOLVED: |
| |
| 1) uint firstPath, |
| 2) sizei count |
| |
| The glDeletePathsNV command and GetPathMetricRangeNV query use |
| this order. |
| |
| glDeleteLists uses this same order. |
| |
| 66. Where does the UTF-8 and UTF-16 specification language come from? |
| |
| See the RFC "UTF-8, a transformation format of ISO 10646": |
| |
| http://tools.ietf.org/html/rfc3629 |
| |
| See the RFC "UTF-16, an encoding of ISO 10646": |
| |
| http://tools.ietf.org/html/rfc2781 |
| |
| The intent of the specification language is to match these RFCs. |
| |
| 67. How does the GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV cover mode |
| work for glCoverFillPathInstancedNV and glCoverStrokePathInstancedNV? |
| |
| RESOLVED: The command computes the bounding box of all the |
| path's bounding boxes. (This can be too conservative for an |
| arbitrarily arranged collection of path objects but works well |
| enough for glyphs in line of text.) |
| |
| This bounding box has a consistent counterclockwise winding |
| order no matter what path objects are listed. This property |
| is a combination of how glRectf works and how the parameters to |
| glRectf are computed. |
| |
| The object-space z (depth) is always zero. (This behavior is |
| a consequence of the primitive being emitted by glRectf.) The |
| matrix elements in the Z row (if such a row exists) of the |
| transforms specified for glCoverFillPathInstancedNV and |
| glCoverStrokePathInstancedNV is ignored. |
| |
| Programmers are cautioned that this could result in the |
| covering geometry being view-frustum culled if the programmer |
| is not careful when using 3D transformTypes (GL_TRANSLATE_3D_NV, |
| GL_AFFINE_3D_NV, GL_TRANSPOSE_AFFINE_3D_NV). To guard against |
| this mishap, consider something such as the following: |
| |
| glMatrixPushEXT(GL_PROJECTION); |
| glScalef(1,1,0); |
| glCoverFillPathInstancedNV(...); |
| glMatrixPopEXT(GL_PROJECTION); |
| |
| This essentially forces the clip-space Z to be zero which will |
| never be clipped by the near or far view-frustum clip planes. |
| |
| If depth testing is desired, perform the depth testing during the |
| "stenciling" step so that depth testing is unnecessary during the |
| "covering" step done by the glCoverFillPathInstancedNV command. |
| |
| 68. What happens when the radius of a circular arc command is |
| negative? |
| |
| UNRESOLVED: The intent is to match the behavior of the PostScript |
| circular arc commands (arc, arcn, arct). Unfortunately the |
| PostScript specification is not entirely clear about how negative |
| radius is handled. |
| |
| Table 5.arcParameterSpecialization has absolute values (abs) |
| computed for the rv and rh columns. |
| |
| However, the points A and B (used for arc and arcn) are computed |
| with c[2] directly (without an absolute value). |
| |
| This computation looks consistent with Ghostscript's behavior |
| for arct: |
| |
| dist = abs(c[4] * num/denom) |
| l0 = dist/sqrt(dot(d0,d0)) * c[4]/abs(c[4]) |
| l2 = dist/sqrt(dot(d2,d2)) * c[4]/abs(c[4]) |
| |
| Could this simply be: |
| |
| dist = c[4] * num/denom |
| l0 = dist/sqrt(dot(d0,d0)) |
| l2 = dist/sqrt(dot(d2,d2)) |
| |
| Probably. |
| |
| This really needs testing and comparison with a PostScript |
| implementation to make sure the specified equations really match |
| PostScript's implemented behavior. |
| |
| 69. What happens when the two angles (c[2] and c[3]) for a circular |
| arc command (GL_CIRCULAR_CCW_ARC_TO_NV or |
| GL_CIRCULAR_CW_ARC_TO_NV) create 1 or more full revolutions? |
| |
| UNRESOLVED: The intent is to match the behavior of the PostScript |
| circular arc commands (arc and arcn). |
| |
| PostScript specifies that "If angle2 is less than angle1, it is |
| increased by multiples of 360 [degrees] until it becomes greater |
| than or equal to angle1. No other adjustments are made to the |
| two angles. In particular, if the difference angle2-angle1 |
| exceeds 360 [degrees], the resulting path will trace portions |
| of the circle more than once." |
| |
| The current equations based on an end-point partial elliptical arc |
| parameterization achieve this. Extra parametric behavior would be |
| necessary to trace a circle multiple times. The current equations |
| in Table 5.pathEquations do not capture this (but should). |
| |
| This needs to be thought through carefully to make sure stroking, |
| particularly when dashed, is handled correctly. |
| |
| 70. PostScript generates a limitcheck error when numbers are |
| encountered that exceed the implementation limit for real numbers. |
| Should the PostScript grammar treat such situations as a parsing |
| error? |
| |
| RESOLVED: No, it's not a parsing error, but the results in |
| such a situation are likely to be undefined. |
| |
| This paragraph in Section 5.X.1 ("Path Specification") applies |
| which begins "If a value specified for a coordinate (however |
| the coordinate is specified) or a value computed from these |
| coordinates (as specified in the discussion that follows) |
| exceeds the implementation's maximum representable value for a |
| single-precision floating-point number, ..." |
| |
| The PostScript's notion of a limitcheck error doesn't nicely |
| correspond to a parsing error. And PostScript's notion of "the |
| implementation limit for real numbers" (likely double precision) |
| might not correspond to the GL's notion of floating-point |
| (typically single precision). |
| |
| The PostScript notion of a limitcheck on numeric range is |
| particularly hard to enforce with relative commands where the |
| limitcheck might not occur until all the relative offsets are |
| applied, something which isn't really part of parsing. |
| |
| What an actual implementation does may vary but a likely |
| implementation approach is generate an IEEE infinity value when |
| single-precision floating-point range is exceeded. This will |
| generate undefined rendering behavior. |
| |
| SVG doesn't offer guidance in its specification when coordinate |
| values exceed the representable range of floating-point. |
| Presumably such range overflows result in implementation-dependent |
| undefined rendering behavior too. |
| |
| 71. What happens when the radius of a OpenVG-style partial elliptical |
| arc commands is negative? |
| |
| RESOLVED: The absolute value of the radius is used for |
| the OpenVG-style arc commands GL_SMALL_CCW_ARC_TO_NV, |
| GL_RELATIVE_SMALL_CCW_ARC_TO_NV, GL_SMALL_CW_ARC_TO_NV, |
| GL_RELATIVE_SMALL_CW_ARC_TO_NV, GL_LARGE_CCW_ARC_TO_NV, |
| GL_RELATIVE_LARGE_CCW_ARC_TO_NV, GL_LARGE_CW_ARC_TO_NV, and |
| GL_RELATIVE_SMALL_CW_ARC_TO_NV. |
| |
| Table 5.arcParameterSpecialization specifies an absolute value |
| (abs) in the rh and rv entries of all these commands. |
| |
| The OpenVG specification is clear on this point in section 8.4 |
| ("Elliptical Arcs") saying "Negative values of [radii] rh and |
| rv are replaced with their absolute values." |
| |
| 72. What should happen for a stroked subpath that is zero length? |
| |
| UNRESOLVED: Not sure yet. |
| |
| SVG gives this advice: |
| |
| http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes |
| |
| Probably need to check what other path renders, particularly |
| PostScript do in this situation. Requires testing actual |
| implementations because the specifications are not clear. |
| |
| 73. Why have the GL_PATH_CLIENT_LENGTH_NV path parameter? |
| |
| RESOLVED: This supports SVG's pathLength attribute used to |
| calibrate distance-along-a-path computations. |
| |
| This applies to dashing a stroked segment, but does NOT |
| apply to the lengths returned by the glGetPathLengthNV and |
| glPointAlongPathNV queries. |
| |
| The client length just applies to dashing because having a |
| client length that is different from the GL's computed length |
| for a path may greatly affect the dashing pattern. The client |
| knows the path's client length, but the GL doesn't unless the |
| client state is available to the GL when dashing a stroked path. |
| |
| It's better to have the client send the client path length |
| unconditionally than require the client to query the GL's computed |
| path length ahead of any sending of a rescaled version of the |
| dash offset or dash array. |
| |
| For the queries, presumably the client can perform the necessary |
| scaling by the client length itself if that's desirable. |
| |
| 74. Should there be a query for GL_PATH_END_CAPS_NV and |
| GL_PATH_DASH_CAPS_NV? |
| |
| RESOLVED: No. You have to query GL_PATH_INTIAL_END_CAP_NV or |
| GL_PATH_TERMINAL_END_CAP_NV for the each respective end cap; or |
| query GL_PATH_INITIAL_DASH_CAP_NV or GL_PATH_TERMINAL_DASH_CAP_NV |
| for each respective dash cap. |
| |
| GL_PATH_END_CAPS_NV and GL_PATH_DASH_CAPS_NV are convenient |
| for most path rendering systems that have identical initial |
| and terminal end and dash caps, but are NOT supported by |
| glGetPathParameteriv or glGetPathParameterfv. |
| |
| 75. What should the path format tokens for SVG and PostScript tokens |
| be named? |
| |
| RESOLVED: Use the abbreviated names SVG and PS respectively: |
| GL_PATH_FORMAT_SVG_NV and GL_PATH_FORMAT_PS_NV. These names |
| are shorter and avoid putting an Adobe trademark in a token name. |
| |
| Future extensions might want to add version numbers to these |
| abbreviated names (another reason to stick with short abbreviated |
| names). |
| |
| 76. In what content (GL client or GL server) are font file names |
| and system font names interpreted? |
| |
| RESOLVED: The GL_STANDARD_FONT_NAME_NV and GL_SYSTEM_FONT_NAME_NV |
| font targets map their respective font names to a font within |
| the GL server. The GL_FILE_NAME_NV font target does the file |
| reading in the GL client; for GLX, there needs to be GLX protocol |
| to transfer glyphs including their kerning and metric data to |
| the GL server. |
| |
| 77. How can the glPathSubCommandsNV command be used to append to |
| the end of an existing path object? |
| |
| RESOLVED: If you set the /commandStart/ parameter to |
| glPathSubCommandsNV to be sufficiently large (greater or equal |
| to the number of path commands in the path object suffices), |
| that works to append commands. |
| |
| 78. Does depth offset (a.k.a. polygon offset) work when using the |
| "stencil" and "cover" path operations? |
| |
| RESOLVED: Yes with caveats. |
| |
| The "stencil" path operations use the |
| GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV and |
| GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV state set by |
| glPathStencilDepthOffsetNV. There is no specific enable; instead |
| set the scale and units to zero if no depth offset is desired. |
| |
| The "cover" path operations use the polygon depth offset state if |
| the GL_POLYGON_OFFSET_FILL enable is enabled, using the polygon |
| offset factor and units specified for glPolygonOffset. This is |
| because the "cover" operation (unlike the stencil operation) |
| does rasterize a polygon primitive. |
| |
| Depth offset is useful when a path rendered decal is applied |
| on depth tested 3D geometry and the path rendered geometry has |
| to be biased forward (negative bias) by polygon offset to avoid |
| depth ambiguities. See issue #120 for details. |
| |
| This is also useful when putting path rendered primitives into |
| shadow maps with a positive depth bias to avoid shadow acne |
| issues. |
| |
| There is NOT a guarantee that the depth offset computed for a |
| "stencil" operation will exactly match the depth offset for a |
| "cover" operation given identical path object and transformations. |
| The two offsets will be close but not generally exact for all |
| generated samples. |
| |
| 79. Can fragment shaders access the facingness state during a cover |
| operation? |
| |
| RESOLVED: Yes, the gl_FrontFacing special variable in GLSL |
| is available. So is the fragment.facing fragment attribute |
| binding in NV_fragment_program2 and subsequent NVIDIA shader |
| assembly extensions. |
| |
| In cases where the path rendered primitive is "very edge" on the |
| facingness fragment state may be ambiguous in extreme situations. |
| |
| 80. When are various computed path parameters re-computed? |
| |
| RESOLVED: If the computed parameter parameters |
| (PATH_COMMAND_COUNT_NV, PATH_COORD_COUNT_NV, |
| PATH_DASH_ARRAY_COUNT_NV, PATH_COMPUTED_LENGTH_NV, |
| PATH_OBJECT_BOUNDING_BOX_NV, PATH_FILL_BOUNDING_BOX_NV, and |
| PATH_STROKE_BOUNDING_BOX_NV) are queried, the values returned |
| always reflect the most up-to-date state of the path object. |
| |
| This also includes when path object parameters are used in |
| contexts such as instanced "cover" operations. |
| |
| 81. Should projective 2D path coordinates be supported? |
| |
| RESOLVED: No. Major path rendering standards don't support |
| projective 2D path coordinates. |
| |
| Moreover, projective 2D path coordinates create technical |
| problems because the projective transformation of projective |
| 2D path coordinates for cubic Bezier curves do not necessarily |
| retain their topology (serpentine, cusp, or loop). |
| |
| 82. Should a non-dashed stroked path's coverage be the same |
| independent of how its control points are specified? |
| |
| RESOLVED: Yes, this is a symmetry rule mandated by the OpenXML |
| Paper Specification. This applies to lines and Bezier curves. |
| |
| So a cubic Bezier curve defined by control points cp0, cp1, cp2, |
| and cp3 should generate the same stroked coverage (assuming the |
| same stroke parameters and requiring the dash array count to be |
| zero) as a cubic Bezier curve with control points cp3, cp2, cp1, |
| and cp0 (so the reversed control point order). |
| |
| XXX Unresolved if it applies to arcs. |
| |
| 83. Should character aliases used to specify path commands be returned |
| as their character alias values or remapped to the actual token |
| name of the command? |
| |
| RESOLVED: Remapped. Any path commands specified with a |
| character alias value (from Table 5.pathCommands) is returned |
| as the command's token value instead. |
| |
| This avoids applications calling glGetPathCommandsNV from having |
| bugs where they handle token names but not character aliases. |
| |
| This also makes it simpler to say "identical" when saying command |
| sequences must match for glWeightPathsNV. Character aliases |
| remapped to command token values makes it unambiguous that |
| GL_LINE_TO and 'L" are the identical command. |
| |
| 84. Is there a way to use this extension to trade-off rendering performance |
| for more effective samples per pixel to improve coverage quality? |
| |
| RESOLVED: Yes. |
| |
| This code demonstrates how multiple passes could accumulate |
| coverage information in the alpha channel of the framebuffer and |
| then a final cover pass could blend the incoming color with the |
| accumulated coverage from the framebuffer's alpha channel. |
| |
| // INITIALIZATION |
| // assume stencil is cleared to zero and framebuffer alpha is clear to zero |
| const int coveragePassesToAccumulate = 4; |
| glEnable(GL_STENCIL_TEST); |
| glStencilFunc(GL_NOT_EQUAL, 0x80, 0x7F); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // tricky: zero 0x7F mask stencil on covers, but set 0x80 |
| glColorMask(0,0,0,1); // just update alpha |
| |
| // M STENCIL+COVER PASSES to accumulate jittered path coverage into framebuffer's alpha channel |
| glStencilFillPathNV(path, GL_COUNT_UP_NV, 0x7F); |
| glCoverFillPathNV(path, GL_PATH_FILL_COVER_MODE_NV); |
| glEnable(GL_BLEND); |
| glBlendFunc(GL_ONE, GL_ONE); // sum up alpha |
| glColor4f(0,0,0, 1.0/coveragePassesToAccumulate ); |
| static const GLfloat jitters[4][2] = { |
| {0,0}, /* various small subpixel jitter X & Y values */ |
| }; |
| for (i=1; i<coveragePassesToAccumulate ; i++) { |
| glMatrixPushEXT(GL_MODELVIEW); { |
| glMatrixTranslatef(GL_MODELVIEW, jitters[i][0], jitters[i][1], 0); |
| glStencilFillPathNV(path, GL_COUNT_UP_NV, 0x7F); |
| glCoverFillPathNV(path, GL_PATH_FILL_COVER_MODE_NV); |
| } glMatrixPopEXT(GL_MODELVIEW); |
| } |
| |
| // FINAL COVER PASS uses accumulated coverage stashed in destination alpha |
| glColorMask(1,1,1,1); |
| // modulate RGB with destination alpha and then zero destination alpha |
| glBlendFuncSeparate(GL_DST_ALPHA, GL_ZERO, GL_ZERO, GL_ZERO); |
| glColor4f(red, green, blue, dontcare); // some color |
| glStencilFunc(GL_EQUAL, 0x80, 0xFF); // update any sample touched in earlier passes |
| glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); // now set stencil back to zero (clearing 0x80) |
| glCoverFillPathInstancedNV(coveragePassesToAccumulate, |
| GL_UNSIGNED_BYTE, "\0\0\0\0", // tricky: draw path objects path+0,path+0,path+0,path+0 |
| path, // this is that path object that is added to zero four times |
| GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV, GL_TRANSLATE_2D_NV, jitters); |
| |
| Assuming N passes and M samples per pixel, this approach |
| accumulates coverage for N*M+1 grayscale levels doing N stencil |
| operations and N+1 cover operations. |
| |
| 85. Why do the commands glGenPathsNV and glDeletePathsNV allocate |
| contiguous ranges of path objects instead of returning an array of |
| (possibly scattered) names and deleting an array of names? |
| |
| RESOLVED: The expectation that path objects will be arranged |
| as characters mapping to glyphs warrants adopting the object |
| model of display lists. |
| |
| glPathGlyphRangeNV, the instanced commands, and the metric and |
| kerning queries all rely on this assumption. |
| |
| 86. What do the stencil and cover commands do if the specified path |
| name does not refer to an existing path object? |
| |
| RESOLVED: Do nothing (and generate no error). |
| |
| This is useful to avoid rendering unpopulated path objects. |
| |
| This "do nothing" behavior also applies to the instanced |
| stencil and cover routines that are expressed in terms of |
| glStencilFillPathNV, glStencilStrokePathNV, glCoverFillPathNV, |
| and glCoverStrokePathNV. |
| |
| Applications that want some "glyph is missing" for non-existent |
| path objects can use glCopyPathNV to copy some existing path |
| object's "glyph is missing" outline to non-existent paths. |
| Alternatively, glPathGlyphRangeNV (or glPathGlyphsNV) can be used |
| with the GL_STANDARD_FONT_NAME of "Missing" to populate a range |
| (or sequence) of path objects with a standard missing glyph |
| (typically a rectangle). (See issue #89.) |
| |
| Queries (glGetPathParameteriv, etc.) allowing only a single path |
| object to be specified, generate a GL_INVALID_OPERATION error |
| if the path name does not exist. |
| |
| glWeightPaths, glInterpolatePathsNV, and glCopyPathNV generate |
| a GL_INVALID_OPERATION error if any of the named source paths |
| do not exist. |
| |
| Path commands that modify the commands, coordinates, or parameters |
| of existing path objects (as opposed to specifying a path object |
| completely) generate a GL_INVALID_OPERATION error if the path |
| name does not exist. |
| |
| 87. What of this extension's per-context state should apply to |
| glPushAttrib and glPopAttrib? |
| |
| RESOLVED: Apply the existing conventions; see new table 6.X, |
| "Path (state per context)". |
| |
| The path fog generation mode applies to GL_FOG_BIT. |
| |
| The path color generation mode and coefficients apply to |
| GL_LIGHTING_BIT. |
| |
| The path texture coordinate set generation modes and coefficients |
| apply to GL_TEXTURE_BIT. |
| |
| The path error position is not pushed or popped, following the |
| convention of the ARB_vertex_program extension. |
| |
| 88. How should the numCoords parameter to the various path |
| specification commands work? |
| |
| RESOLVED: When there is also a /numCoords/ parameter, |
| the GL_INVALID_OPERATION error is generated if the number of |
| coordinates is not equal to the number of coordinates needed by |
| the command's specified path command sequence. This provides |
| a sanity check. |
| |
| For the glPathSubCoordsNV command, there's no requirement that |
| the range of coordinates "match up" with path command boundaries |
| for coordinates. |
| |
| Some consideration was given to specifically treating a value of |
| zero for /numCoords/ by allowing the number of coordinates to |
| be based on the command's corresponding path command sequence. |
| This would allow an application to bypass the sanity check if |
| the application didn't exactly know how many coordinates a path |
| command sequence required. This was rejected because it is likely |
| error-prone and it means when such commands are compiled into |
| a display list or packed into GLX protocol, the path command |
| sequence would then have the be scanned. This would make the |
| GL client unnecessarily knowledgeable about the supported path |
| commands. So for both "safety" and implementation reasons, |
| the /numCoords/ value of zero is not specially interpreted; |
| it means that the path command sequence really is expected to |
| require zero coordinates (not generally the case except for the |
| GL_CLOSE_PATH_NV command). |
| |
| 89. How can an application guarantee that every glyph in a range |
| of Unicode character codes has /some/ default outline defined? |
| |
| RESOLVED: The "Missing" name with the GL_STANDARD_FONT_NAME_NV |
| target populates the entire sequence or range of path objects |
| with a default outlines. |
| |
| Example: |
| |
| const int allOfUnicode = 1<<21; // Entire 21-bit Unicode range! |
| const GLfloat emScale = 2048; |
| GLuint glyphBase = glGenPathsNV(allOfUnicode); |
| glPathGlyphRangeNV(glyphBase, |
| GL_STANDARD_FONT_NAME_NV, "Missing", GL_NONE, |
| 0, allOfUnicode, emScale); |
| |
| 90. Does the "Missing" font name used for GL_STANDARD_FONT_NAME_NV |
| skip or avoid character codes that Unicode designates as white |
| space, line terminators, etc. |
| |
| RESOLVED: The "Missing" font name populates these with a path |
| object with the missing outline (a box) and corresponding metrics |
| for such spacing characters and all other characters. |
| |
| The assumption is that Unicode fonts will populate various |
| blank space, line and paragraph terminators, and other blank |
| or ignorable character points with appropriate null outlines |
| and zero-width metrics. Because glPathGlyphRangeNV and |
| glPathGlyphsNV don't re-specify existing path objects, these |
| will be left along if the "Missing" standard font is the last |
| font used to specify a given range of path objects. All white |
| space and separator character codes less than 256 (the Latin-1) |
| range will be populated by the "Serif", "Sans", and "Mono" |
| standard fonts if specified because these guarantee the Latin-1 |
| range is populated. These are specifically U+0009..000D, U+0020, |
| U+0085, 0x00A0 but also other blank or ignorable character points |
| such as control characters. |
| |
| For more information: |
| |
| http://unicode.org/faq/unsup_char.html |
| |
| 91. What is the /emScale/ parameter to glPathGlyphRangeNV and |
| glPathGlyphsNV for and how should it be used? |
| |
| RESOLVED: /emScale/ exists to ensure multiple fonts, potentially |
| with distinct font unit scales, can be scaled to a consistent |
| scale. |
| |
| Typically TrueType fonts are authored for 2048 font units per |
| Em while Type1 fonts have been historically authored to 1000 |
| font units per Em. |
| |
| Typically a good value for /emScale/ is 2048 to match the |
| convention of TrueType. This avoid TrueType font metrics from |
| being rescaled. |
| |
| Setting /emScale/ to zero allows the native font units per Em |
| to be used. Be careful because outlines of path objects for |
| glyphs from fonts with different font units per Em will have |
| different scales. |
| |
| 92. Should glWeightPathsNV work for a single path object? |
| |
| RESOLVED: No, two or more paths are required to generate a |
| weighted path. |
| |
| Use glCopyPathNV if copying a single path object is desired. |
| |
| glCopyPathNV copies glyph metrics and kerning information and |
| allows arc commands while glWeightPathsNV does not. |
| |
| While glInterpolatePathsNV can be expressed in terms of |
| glWeightPathsNV, glCopyPathNV cannot. |
| |
| 94. What should the initial join style of a path object be? |
| |
| RESOLVED: GL_MITER_REVERT_NV. This is consistent with the join |
| style used by SVG, PostScript, PDF, and Cairo. |
| |
| Note that Flash, XPS, and Qt use GL_MITER_TRUNCATE_NV instead. |
| |
| Arguably GL_MITER_TRUNCATE_NV is a "nicer" join style because |
| the miter does not "pop" from miter to bevel when the miter limit |
| is exceeded; instead when the miter limit is approached and then |
| exceeded, the miter stops growing further and simply loses its |
| sharp tip. |
| |
| 95. What type of triangle should the GL_TRIANGULAR cap be? |
| |
| RESOLVED: A right triangle. |
| |
| This is consistent with the XPS specification. Other standards |
| don't support triangular caps. |
| |
| 96. Can NV_path_rendering be implemented without *any* dependencies |
| on system specific fonts? |
| |
| RESOLVED: YES. |
| |
| Say a platform had poor or unstable interfaces for accessing |
| system specific fonts (e.g. Linux). In the case of Linux, |
| resolution-independent fonts are typically accessed through a |
| combination of freetype2 and fontconfig. |
| |
| One or both of these standards may be missing from the platform |
| or be unreliable or misconfigured. |
| |
| In such a case, NV_path_rendering could be implemented so |
| that the GL_SYSTEM_FONT_NAME_NV usage for glPathGlyphsNV and |
| glPathGlyphRangeNV would never populate path object names with |
| glyphs. |
| |
| However the GL_STANDARD_FONT_NAME_NV usage would still be |
| guaranteed. The GL_STANDARD_FONT_NAME_NV usage by providing |
| the required set of pre-compiled font outlines built-in into the |
| driver directly (using IP unencumbered font outlines such as |
| the DejaVu fonts). |
| |
| This design means that applications that use the approach |
| (copied from the Overview) will work: |
| |
| glPathGlyphRangeNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Helvetica", GL_BOLD_BIT_NV, |
| 0, numChars, emScale); |
| glPathGlyphRangeNV(glyphBase, |
| GL_SYSTEM_FONT_NAME_NV, "Arial", GL_BOLD_BIT_NV, |
| 0, numChars, emScale); |
| glPathGlyphRangeNV(glyphBase, |
| GL_STANDARD_FONT_NAME_NV, "Sans", GL_BOLD_BIT_NV, |
| 0, numChars, emScale); |
| |
| In this case, the two initial glPathGlyphRangeNV calls |
| will fail to populate the range of path objects from |
| [glyphBase,glyphBase+numChars-1] but the third call will populate |
| the range. |
| |
| This allows NV_path_rendering to be implemented with ZERO |
| dependencies on the system to provide glyphs from system fonts while |
| applications can still utilize fonts in their path rendering. |
| |
| While this is an allowed implementation approach, actual |
| implementations should make reasonable efforts to provide access |
| to system fonts if possible. |
| |
| 96. What is GL_DASH_OFFSET_RESET_NV for? |
| |
| RESOLVED: OpenVG supports the concept of a "dash phase reset" |
| (see VG_DASH_PHASE_RESET) that controls whether or not the dash |
| pattern (with its offset) resets at "move to" command boundaries |
| within a path's command sequence. |
| |
| Rather than use a boolean value (as OpenVG does), the |
| GL_DASH_OFFSET_RESET_NV path parameter takes an enumeration |
| consisting of GL_MOVE_TO_RESETS_NV and GL_MOVE_TO_CONTINUES_NV |
| to be more explicit about how the dash offset reset parameter |
| affects the dash pattern. |
| |
| Technically, what this specification calls the "dash offset" |
| is what OpenVG calls its "dash phase". This specification |
| uses "dash phase" to mean what OpenVG calls "dash phase reset" |
| because the word "reset" is built into the GL token values. |
| |
| When there is a dash phase reset, the dash offset is set to the |
| value of the path's GL_DASH_OFFSET_NV parameter (consistent with |
| OpenVG). |
| |
| 97. What APIs say "dash offset" and what APIs say "dash phase" and |
| why does this extension use "dash offset"? |
| |
| RESOLVED: PostScript, PDF, Cairo, Qt, XPS, SVG, and Silverlight |
| use the "dash offset" for the offset to the dash pattern, same |
| as this extension. |
| |
| OpenVG, Quartz 2D, Java 2D, Illustrator, and Skia use the term |
| "dash phase" for the identical functionality. |
| |
| OFFSET makes more sense in the OpenGL context because lots of |
| OpenGL tokens already use OFFSET in their token names. Core |
| OpenGL 4.0 has 16 such tokens already. |
| |
| 98. What is the motivation for glTransformPathNV? |
| |
| RESOLVED: Sometimes a path should be stroked with a stroke width |
| that is constant in a particular space (such as window space). |
| |
| Once example of this is SVG 1.2 Tiny's "non-scaling stroke" |
| property. The stroke width is supposed to be maintained after |
| transformation into pixel space. |
| |
| This could be implemented with this extension by transforming |
| the path object into the appropriate space so that the user-space |
| stroke width will match the transformed space. |
| |
| 99. Should the specification say more about how arcs are transformed? |
| |
| UNRESOLVED: Certainly yes, but I'm not sure exactly how to |
| specify how arcs are transformed with a suitable level of |
| formalism. |
| |
| I'm not clear if partial elliptical arcs can be subjected to |
| projective transformations and remain partial elliptical arcs. |
| I believe they can. |
| |
| 100. How is glTransformPathNV different from OpenVG's vgTransformPath? |
| |
| RESOLVED: The two commands are similar. |
| |
| The OpenVG 1.1 version always converts vertical and |
| horizontal line commands to generic line to commands where as |
| glTransformPathNV does that only if the resulting transformed |
| line segment is no longer either vertical or horizontal in the |
| new coordinate system. This allows cases such as 90 degree |
| rotations or scaling without rotation to preserve the compactness |
| of vertical and horizontal line segments. |
| |
| In OpenVG 1.1, the VG_MATRIX_PATH_USER_TO_SURFACE matrix |
| used by vgTransformPath is a 3x3 projective matrix where as |
| glTransformPathNV supports up to 4x4 projective matrices. |
| Note that the z component of any transformed coordinate is |
| effectively discarded by glTransformPathNV so the z row and |
| column is not consequential to the resulting transformed path. |
| The rationale for this is to allow the same 4x4 transform matrix |
| array used by 3D to be used by glTransformPathNV. |
| |
| In OpenVG 1.1, the matrix is implicitly supplied by the |
| VG_MATRIX_PATH_UER_TO_SURFACE matrix whereas in glTransformPathNV, |
| the matrix is explicitly specified. |
| |
| XXX Perhaps there should be a special mode that uses the |
| modelview-projection-viewport transform implicitly? |
| |
| 101. Can you provide an example of non-scaling strokes implemented with |
| glTransformPathNV? |
| |
| UNRESOLVED: To be written. |
| |
| 102. What happens if a command that creates a path from existing path |
| objects has the result path name as one of the inputs? |
| |
| RESOLVED: This is expected to just work. The new path object |
| is created from the existing ones, then the new path object |
| replaces any path object with the resulting path object name. |
| |
| 103. Should glTransformPathNV support projective transformations? |
| |
| RESOLVED: No, such projective transformations could result |
| in path commands transitioning from non-rational to rational |
| boundaries. |
| |
| If points on the path boundary are generated by non-rational |
| boundaries, the resulting transformation, assuming a |
| non-projective transformation, also results in non-rational |
| boundaries. |
| |
| 104. Should there be a distinct stencil function state for path |
| stenciling? |
| |
| RESOLVED: YES. glPathStencilFunc sets the state. How the |
| stencil state needs to be configured for path covering is |
| different than how the stencil function is configured typically |
| for path stenciling. |
| |
| For example, stencil covering might use |
| glStencilFunc(GL_NOT_EQUAL,0,~0) while path stenciling would |
| use GL_ALWAYS for the path stenciling stencil test. |
| |
| However there are other situations such as path clipping where it |
| is useful to have the path stencil function configured differently |
| such as glPathStencilFunc(GL_NOT_EQUAL, 0x00, 0x80) or other |
| similar path clipping test. |
| |
| 105. Is there back- and front-facing path stencil function state? |
| |
| RESOLVED: NO. There is a single stencil function, reference |
| value, and read mask. The path stenciling operation doesn't |
| have a sense of front- and back-facing. |
| |
| 106. Does the path stencil function state apply always or only if |
| stencil testing is enabled? |
| |
| RESOLVED: Always. If you want to avoid discarding samples |
| from this test, use the GL_ALWAYS path stencil function (which |
| is the initial context state). |
| |
| 107. Does the glPathStencilFuncNV state affect the operation of |
| the stencil test during path cover operations? |
| |
| RESOLVED: NO, the path stencil state updated by |
| glPathStencilFuncNV only affects the path stencil (not cover) |
| operations. |
| |
| For the path cover operations, the *normal* stencil test applies. |
| For the stencil test to apply to path cover operations, the |
| stencil test (GL_STENCIL_TEST) must be enabled. |
| |
| 108. Should path objects be shared among rendering contexts in the |
| same manner as display lists and texture objects? |
| |
| RESOLVED: Yes. |
| |
| See the "Additions to the AGL/GLX/WGL Specifications" section. |
| |
| Because path objects are not "bound" there are stricter |
| serialization requirements than for "bindable" objects such as |
| programs and textures. |
| |
| Due to NVIDIA driver bug 1315267, path objects were not actually |
| shared among contexts prior to Driver release 320.xx (July 2013). |
| |
| 109. Should the kerning separations be 2D offsets or 1D horizontal |
| translations? |
| |
| UNRESOLVED: The specification is currently written for 1D |
| horizontal translations. |
| |
| TrueType fonts appears to provide 1D horizontal translations |
| for kerning. |
| |
| However a PostScript font can contain 2D offsets for kerning. |
| |
| Are 2D offsets really used? 2D offsets seem like an unnecessary |
| complication when they are unlikely to be common. |
| |
| XXX Need to study this situation further. |
| |
| If 99.99% of fonts never use 2D offsets, it is annoying to have |
| them for the ultra minority that might. Not sure what the real |
| situation is... |
| |
| Perhaps we could provide tokens to query either 1D horizontal |
| translations or the more general 2D offsets. But how would an |
| application know whether a font actually specified 2D offsets |
| or not?? |
| |
| 110. What is the initial miter limit of a path object? |
| |
| RESOLVED: 4 to match the SVG specification. See: |
| |
| http://www.w3.org/TR/SVG/painting.html#StrokeMiterlimitProperty |
| |
| There is a lot of variability in initial miter limit values among |
| path rendering APIs. The SVG initial miter limit is chosen |
| because SVG is an open, web-based standard. |
| |
| For Cairo, the initial miter limit is 10. |
| |
| For Direct2D, the initial miter limit is 10. |
| |
| For Flash, the initial miter limit is 3. |
| |
| For PostScript, the initial miter limit is 10. |
| |
| For Qt, the initial miter limit is 2 units of the stroke width. |
| |
| For Skia, the initial miter limit is 4. |
| |
| 111. Should initial path object state such as miter limit, stroke width, etc. |
| be determined by "latching" per-context initial value state for |
| these parameters? |
| |
| UNRESOLVED |
| |
| Possibly. That would make it easier for a particular path |
| rendering API's conventions initial conventions be consistently used |
| to initialize path object parameters. |
| |
| 112. Should glPathFogGenNV's GL_FRAGMENT_DEPTH mode provide a |
| perspective-divided value? |
| |
| RESOLVED: No, -ze is provided rather than -ze/we. |
| |
| Providing -ze/we would not interpolate properly over the path. |
| Typically the modelview matrix used to compute ze is affine so we |
| will be 1.0 in such cases and the lack of division won't matter. |
| |
| If the modelview matrix is projective, the application can choose |
| to interpolate we as a texture coordinate with glPathTexGenNV's |
| GL_EYE_LINEAR mode and perform the division -ze/we during fragment |
| coloring. |
| |
| 113. How should path color and texture coordinate generation be |
| disabled? |
| |
| RESOLVED: For color: |
| |
| glPathColorGenNV(colorFormat, GL_NONE, GL_NONE/*colorFormat*/, NULL); |
| |
| For texture coordinate generation: |
| |
| glPathTexGenNV(GL_TEXTURE_0+i, GL_NONE, 0/*components*/, NULL); |
| |
| The coeffs array could be an arbitrary pointer because it will |
| only be dereferenced if the genMode is GL_NONE, but NULL is a |
| suitable value to document this fact. |
| |
| Querying the respective coefficients after path color or texture |
| coordinate disabling commands above should return 16 zeros. |
| |
| 114. How should path color and texture coordinate generation interact |
| with the GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV instanced cover |
| mode? |
| |
| RESOLVED: The effective bounding box is the union of all the |
| instanced bounding boxes. |
| |
| This is useful for something such as a line of text rendered as |
| sequence of glyph path objects where the line of text should share |
| a common gradient tied to the bounding box of the line of text. |
| |
| 115. How do I ignore kerning when using glGetPathSpacingNV? |
| |
| RESOLVED: Pass in 0.0 for the kerningScale parameter. |
| |
| 116. How do I query the raw kerning parameters? |
| |
| RESOLVED: Pass in 0.0 for the advanceScale parameter and 1.0 |
| for the kerningScale parameter. |
| |
| 117. Do I need to use GL_TRANSLATE_2D_NV when getting spacing |
| information from glGetPathSpacingNV? |
| |
| RESOLVED: Typically GL_TRANSLATE_X_NV is fine. |
| |
| Typically most kerned fonts (particularly TrueType fonts) using |
| kerning offsets that are horizontal only. PostScript technically |
| allows 2D (x,y) kerning offsets and FreeType 2's FT_Get_Kerning |
| API also returns 2D kerning vectors. |
| |
| To support 2D kerning vectors, glGetPathSpacingNV accepts |
| GL_TRANSLATE_2D_NV as well as GL_TRANSLATE_X_NV. |
| |
| For most fonts, the Y offset can be expected to be zero. |
| |
| 118. Why have the /pathParameterTemplate/ parameter to |
| glPathGlyphRangeNV and glPathGlyphsNV? |
| |
| RESOLVED: Path object specified from glyphs often need parameters |
| specified on a per-font basis that are distinct from the initial |
| path object parameters in table 6.Y. |
| |
| Rather than force an application to respecify the path parameters |
| of all the path objects in a range of path objects for glyphs, |
| it is more efficient for such glyph-initialized path objects |
| to simply use parameters from another existing path object as |
| a template. |
| |
| For example, the default stroke width of 1.0 might need to be |
| respecified for every path object corresponding to a range of |
| glyphs for rendering stroked glyphs. If the emScale for a glyph |
| is 2048 (typical of TrueType fonts), then 1.0 is too thin to be a |
| discernable stroke width. A value such as 10% of the Em scale (so |
| 10% of 2048 would be 20.48) is likely to be a more useful value. |
| |
| Similarly, GL_ROUND_NV or GL_BEVEL_NV are better join styles |
| for stroking glyphs than the standard join style initial value |
| GL_MITER_REVERT_NV. |
| |
| A shared dash pattern for all path objects belonging to a single |
| set of glyphs is much easier to specify from a template path |
| object. |
| |
| 119. Are system font names and file names for fonts case-sensitive? |
| |
| RESOLVED: Standard font names (such as "Mono" and "Missing" |
| are case-sensitive). System font name names and file names for |
| fonts should match the system's policy for case-sensitivity of |
| font names and file names respectively. |
| |
| Linux and other Unix-like operating systems have case-sensitive |
| file names. Windows has case-insensitive file names. Windows and |
| FontConfig-based systems have case-insensitive system font names. |
| |
| 120. Why have PathStencilDepthOffsetNV and PathCoverDepthFuncNV? |
| |
| RESOLVED: These functions minimize the state changes needed |
| to depth test path rendering consisting of several co-planar |
| path layers (as is typical of path rendering content) against |
| conventional depth-tested 3D rendering. |
| |
| To properly depth test path rendering against conventional 3D |
| rendering and other path rendering, particularly when a set of |
| paths layer upon themselves, it is necessary to pull forward |
| slightly the depth values generated during the stenciling step. |
| This avoids Z-fighting when drawing path rendered layers that |
| are logically co-planar. However when covering pixels (assuming |
| the stencil test passed during covering), we unconditionally |
| write un-offset depth values. |
| |
| To depth-test path rendered content in this manner, follow the |
| following pattern: |
| |
| Perform the following initialization: |
| |
| // Conventional initialization for depth testing and using path rendering |
| glEnable(GL_DEPTH_TEST); |
| glStencilFunc(GL_NOT_EQUAL, 0, 0xFF); |
| glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); |
| |
| // The additional calls for depth testing of path-rendering... |
| glPathStencilDepthOffsetNV(-0.05, -1); // push stenciled path depth values slightly closer |
| glPathCoverDepthFuncNV(GL_ALWAYS); |
| |
| Clear the framebuffer, including the depth buffer: |
| |
| // Clearing |
| glClear(GL_COLOR_BUFFER_BIT | |
| GL_STENCIL_BUFFER_BIT | |
| GL_DEPTH_BUFFER_BIT); |
| |
| For each rendered path object... |
| |
| 0) Make sure stencil testing is enabled (in case it was |
| disabled to draw prior conventional 3D objects). |
| |
| glEnable(GL_STENCIL_TEST); |
| |
| 1) Stencil step: |
| |
| glStencilFillPathNV(pathObj, GL_COUNT_UP_NV, 0xFF); |
| |
| 2) Cover step: |
| |
| glCoverFillPathNV(pathObj, GL_COUNT_UP_NV, 0xFF); |
| |
| For conventional 3D objects... |
| |
| 0) Make sure stencil testing is disabled (in case it was |
| enabled to draw prior path rendered objects). |
| |
| glDisable(GL_STENCIL_TEST); |
| |
| 1) Draw normally: |
| |
| draw_3d_object_normally(); |
| |
| With this pattern, conventional and path rendered objects can |
| be rendered in arbitrary order. |
| |
| The above pattern shows path filling, but path stroking works |
| the same. |
| |
| Notice only the initialization calls to |
| glPathStencilDepthOffsetNV and glPathCoverDepthFuncNV are |
| actually "different" than conventional 3D or path rendering. |
| |
| One potential disadvantage of this approach is that other objects |
| with nearly identical depth values to the depth values of the |
| path rendering content may be judged to pass the depth test when |
| technically the other object's depth values are slightly closer. |
| This is because the path stencil depth offset is pushing path |
| rendering depth values slightly closer. While this is possible, |
| this occurs in situations where the proper occlusion was nearly |
| ambiguous because the depth values between the other object and |
| the path rendering are so close. |
| |
| 121. What if the disadvantage of depth values having to be offset closer |
| is deemed unacceptable (this will be rare). |
| |
| RESOLVED: If 100% exact depth occlusion is crucial to the |
| application, this can be achieved at some cost be stenciling |
| a planar conservative bounding region for the path object into |
| the stencil buffer, depth testing the rendering of this plane. |
| This depth-tested plane region should not perform color writes |
| but should set the most-significant bit of the stencil buffer |
| (for an 8-bit stencil buffer, done with GL_REPLACE of 128). |
| Then path rendering, with depth testing DISABLED, can use |
| the glPathStencilFunc to discard stencil values without the |
| most-significant bit set. Finally the plane region must |
| be redrawn again to clear any stencil values left with the |
| most-significant bit set. This approach essentially uses the |
| depth plane region as a depth-tested proxy for the proper depth |
| values for the path rendering. |
| |
| 122. How should the path stencil depth offset be described? |
| |
| RESOLVED: The function is named glPathStencilDepthOffsetNV and |
| the query tokens are GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR and |
| GL_PATH_DEPTH_OFFSET_UNITS. |
| |
| Note that "polygon offset" does not appear in the name. Polygon |
| offset isn't appropriate in the context of path rendering because |
| paths aren't technically polygon primitives. The term "depth |
| offset" is the actual name of the functionality that offsets |
| depth values of polygons (the name of section 3.6.4 specifying |
| glPolygonOffset is actually titled "Depth Offset"). |
| |
| There's no perfect attribute category of state for path stencil |
| depth offset factor and units to belong so the "polygon" category |
| just like the polygon offset state. |
| |
| 123. Does glPointAlongPathNV have anything to do with the path's |
| dashing state? |
| |
| RESOLVED: No. |
| |
| The arc length computation necessary for glPointAlongPathNV |
| computes the arc length along the path (really a subpath) but |
| ignores any gaps created by the dash pattern. |
| |
| Knowing the dash count, pattern, offset, and reset state, you |
| could adjust the distance passed to glPointAlongPathNV to account |
| for dashing gaps, but this is something the application must do. |
| |
| 124. Should PostScript user path parser enforce the same error |
| conditions as PostScript? |
| |
| RESOLVED: No. |
| |
| Section 4.6.1 (User Path Construction) in the PostScript Language |
| Reference Manual explains user paths. |
| |
| The section includes some restrictions. The "ucache" operator |
| is optional but must be the first operator in a user path. |
| The "setbbox" operator is required. The next operator must be an |
| "absolute positioning operator (moveto, arc, or arcn)." |
| |
| The grammar in 5.X.1.2.2 (PostScript Path Grammar) does not |
| enforce these restrictions. In particular, the operators can |
| appear in any order and none are required. |
| |
| The rationale for this relaxed behavior is: 1) to make the |
| parser easier to specify, 2) make the specification of a path |
| object through a PostScript path grammar more consistent with |
| specifying a path using glPathCommandsNV, and 3) not require |
| specification of a user path bounding box that isn't relevant |
| in the context of OpenGL rendering. |
| |
| If a path command is used without a prior absolute positioning |
| command, the initial position is assumed to be (0,0). So a string |
| such as "40 50 lineto" would draw a line from (0,0) to (40,50). |
| |
| 125. The ISO PDF 32000 standard has additional path construction |
| operators for rectangles and cubic Bezier curves with duplicated |
| first or last control points. Should this extension have |
| first-class path commands for these operators? |
| |
| RESOLVED: Yes. These PDF operators correspond |
| to the path commands GL_DUP_FIRST_CUBIC_CURVE_TO_NV, |
| GL_DUP_LAST_CUBIC_CURVE_TO_NV, and GL_RECT_NV, corresponding to |
| the operators "v", "y", and "r" respectively. |
| |
| See Table 59 (Path Construction Operators) in the PDF 32000-1:2008 |
| specification (page 133). See: |
| |
| http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf [[ free version ]] |
| http://www.iso.org/iso/iso_catalogue/catalogue_ics/catalogue_detail_ics.htm?csnumber=51502 |
| |
| These additional operators make path specification and storage |
| more compact, help editing, and better semantically match the |
| important PDF standard. PDF supports just absolute versions of |
| these commands so relative versions are NOT provided. |
| |
| The "m", "l'", "c", and "h" operators correspond to GL_MOVE_TO_NV, |
| GL_LINE_TO_NV, GL_CUBIC_CURVE_TO_NV, and GL_CLOSE_PATH_NV |
| respectively. |
| |
| There is not a string grammar for glPathStringNV to encode |
| PDF commands. |
| |
| 126. What is the GL_RESTART_PATH_NV path command for? |
| |
| RESOLVED: It is useful to be able to concatenate path |
| command sequences as if they are independent from each other. |
| The GL_RESTART_PATH_NV provides a way to reset the state of |
| path command processing back to its initial state when the first |
| command of a path's command sequence is processed. |
| |
| So you could use glPathSubCommandsNV to append a path sequence |
| to an existing path object's sequence. By first appending a |
| GL_RESTART_PATH_NV command, you make sure the result is consistent |
| with drawing the path sequences independently. |
| |
| Specifically, /sp/, /cp/ and /pep/ are re-initialized to (0,0) when |
| a GL_RESTART_PATH_NV path command is encountered. |
| |
| Additionally, this restart also has the effect of causing |
| CIRCULAR_TANGENT_ARC_TO_NV to NOT draw an initial tangent line |
| segment. So if you want to draw multiple independent circular |
| arcs using the GL_CIRCULAR_TANGENT_ARC_TO_NV parameterization, |
| you need a GL_RESTART_PATH_NV command just prior to each |
| GL_CIRCULAR_TANGENT_ARC_TO_NV command. In this respect, |
| GL_RESTART_PATH_NV is different from a GL_MOVE_TO_NV command to |
| (0,0). |
| |
| The GL_RESTART_PATH_NV does not by itself reset the dash |
| offset, but if the path's GL_PATH_DASH_OFFSET_RESET_NV is set |
| to GL_MOVE_TO_RESETS_NV, GL_RESTART_PATH_NV (as with any command |
| that updates /sp/) will reset the dash offset. |
| |
| 127. <<Bogus issue removed.>> |
| |
| 128. How does the "stencil" and "cover" steps operate on a multisample |
| framebuffer when the GL_MULTISAMPLE enabled is disabled? |
| |
| RESOLVED: The "stencil" step respects the disabled GL_MULTISAMPLE |
| enable and rendered aliased stencil coverage. |
| |
| When MULTISAMPLE is disabled, "stencil" step coverage |
| determinations are made at the pixel center. (This will result |
| in an aliased appearance for the determined path coverage so |
| stenciling and covering paths with GL_MULTISAMPLE disabled isn't |
| recommended.) |
| |
| All the (non-masked) stencil samples for the pixel are considered |
| covered or not based on the pixel center's coverage determination. |
| For example, if MULTISAMPLE is disabled for a multisample |
| buffer and the pixel center is determined covered during |
| glStencilFillPathNV or glStencilStrokePathNV (or instanced |
| versions), all the samples are updated (INCR/DECR/INVERT for |
| filling or REPLACE for stroking). |
| |
| "non-masked" means that the glSampleMaskIndexedNV state applies. |
| |
| The "cover" step also respects the disabled GL_MULTISAMPLE enable. |
| |
| To maintain rendering invariances in order to guarantee |
| conservative covering, both the "stencil" and "cover" step should |
| be rendered with the same GL_MULTISAMPLE enable state. |
| |
| 129. What happens when a command or query takes a sequence of path object |
| names and a named path object does not exist? |
| |
| RESOLVED: The non-existent path is "skipped" in instanced |
| commands such as glStencilFillPathInstancedNV (and the transform |
| for the particular path name is skipped over). Notice the |
| pseudo-code for these instanced path commands uses glIsPathNV |
| to test if each path name exists. |
| |
| Queries cannot simply ignore the invalid name as they return |
| information. glGetPathSpacingNV treats the non-existent name as |
| having zero space. glGetPathMetricRangeNV and GetPathMetricsNV |
| return metric values of -1 for the metrics of non-existent |
| path objects (as also occurs if the path object lacks metrics |
| information). |
| |
| No GL error is generated due to a non-existent path name. |
| |
| (Early implementation prior to NVIDIA's OpenGL 4.3 implementation |
| might crash or generate a GL_INVALID_OPERATION error. |
| The behavior was a bug.) |
| |
| 130. Should glCallLists be extended to take the GL_UTF8_NV and |
| GL_UTF16_NV date types? |
| |
| RESOLVED: No. That might make sense in another extension since it |
| would allow complex Unicode text to be rendered by glCallLists. |
| |
| (An early version of this specification did call for supporting |
| UTF sequences for glCallLists, but that behavior was never |
| implemented and is now purged from the specification.) |
| |
| 131. Should glPathTexGenNV and glPathColorGenNV transform the plane |
| equations for GL_EYE_LINEAR by the inverse transpose modelview |
| matrix? |
| |
| RESOLVED: Yes. |
| |
| This matches the way glTexGenfv operates with GL_EYE_LINEAR |
| texgen planes. This allows the eye plane equations to be |
| specified in the current object-space. |
| |
| (Early specifications, prior to revision 9, incorrectly failed |
| to specify this transformation.) |
| |
| 132. Should new commands and queries be used to support generating |
| GLSL fragment inputs? |
| |
| RESOLVED: Add a new command to specify the path fragment |
| input generation state but use the API introduced by the |
| ARB_program_interface_query extension specification to query |
| back the path fragment input generation state. |
| |
| The new command is glProgramPathFragmentInputGenNV. Given a GLSL |
| program object and a GL_FRAGMENT_INPUT_NV resource location, |
| this command provides the linear function state with which to |
| generate the specified interpolated fragment input. |
| |
| The new GL_FRAGMENT_INPUT_NV token names the path fragment input |
| resource. |
| |
| The new program resource properties GL_PATH_GEN_MODE_NV, |
| GL_PATH_GEN_COEFF_NV, and GL_PATH_GEN_COMPONENTS_NV name the |
| path fragment input generation resources. |
| |
| 133. How should this specification interact with a Core profile context? |
| |
| RESOLVED: See "Dependencies on Core Profile and OpenGL ES" |
| section. |
| |
| In summary: |
| |
| Enough modelview and projection functionality from |
| EXT_direct_state_access is required to make transformations of |
| paths possible. |
| |
| Fragment varyings of GLSL programs can be interrogated and these |
| can be generated. |
| |
| Exclude fixed-function fragment varying commands, queries, |
| and GLSL built-in variables. |
| |
| 134. Existing path rendering systems typically specify 2D transforms. |
| Such transforms are cheaper to load, concatenate, and render with. |
| How are 2D transforms specified? |
| |
| RESOLVED: Add new matrix commands. |
| |
| Driver implementations can exploit these more compact matrix |
| representations to accelerate path rendering where often matrix |
| changes are frequent relative to the amount of rendering. The |
| concatenation of two 3x2 matrices is 24 multiply-add operations; |
| while the concatenation of two 4x4 matrices is 64 multiply-add |
| operations, so requiring over 2.5x more math operations. |
| |
| This table shows the correspondence between other path rendering |
| APIs and the corresponding matrix routine so we need only populate |
| the range of matrix representations used by major path rendering |
| standards. |
| |
| Standard Type Component order Corresponding GL load command |
| --------------- ---------------- --------------- ----------------------------- |
| Direct2D D2D_MATRIX_3X2_F [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| Cairo cairo_matrix_t [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| Skia SkMatrix [0,1,2] glMatrixLoadTranspose3x3fNV |
| [3,4,5] |
| [6,7,8] |
| SkScalar [6] [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| Qt QMatrix [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| OpenVG VGfloat [9] [0,3,6] glMatrixLoad3x3fNV |
| [1,4,7] |
| [2,5,8] |
| AGM BRVCoordMatrix [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| Ghostscript gs_matrix [0,2,4] glMatrixLoad3x2fNV |
| [1,3,5] |
| |
| Along with the glMatrixLoad*NV commands, there are corresponding |
| glMatrixMult*NV commands. |
| |
| Queries should be rare so the existing queries returning all 16 |
| values of a current matrix are sufficient. |
| |
| 135. Does the "layout(location=2)", etc. syntax work for fragment inputs? |
| |
| RESOLVED: Yes, assuming separate shader objects support. |
| The ARB_separate_shader_objects functionality (made core in |
| OpenGL 4.1) supports layout qualifiers to annotate locations on |
| arbitrary fragment shader inputs. |
| |
| Example: A fragment shader could include the statement: |
| |
| layout(location=4) in vec4 eye_space; |
| |
| This would ensure that the location queried with |
| GetProgramResourceLocation(program, GL_FRAGMENT_INPUT_NV, |
| "eye_space") will return 4. |
| |
| 136. What data types work with glProgramPathFragmentInputGenNV? |
| |
| RESOLVED: Just floating-point scalars and vectors. |
| |
| Half-precision and double-precision varyings considered |
| floating-point, and hence are allowed, but implementations may |
| interpolate double-precision at single-precision. |
| |
| Matrix, array, structure, boolean, and integer data types are |
| not supported. |
| |
| Generated values are intrinsically floating-point (they are |
| basically interpolants) hence the floating-point restriction. |
| |
| Restricting the generation to floating-point scalars and vectors |
| shouldn't be a hardship. |
| |
| 137. How can a fragment varying (or fragment input for GLSL) be driven |
| to a constant value? |
| |
| RESOLVED: Use the GL_CONSTANT genMode for this. |
| |
| Example: This command: |
| |
| GLfloat float4_constant[4] = { 1, 2, 3, 4 }; |
| glPathTexGenNV(GL_TEXTURE0, GL_CONSTANT, 4, float4_constant); |
| |
| is equivalent to: |
| |
| GLfloat coefficients[3*4] = { 0,0,1, 0,0,2, 0,0,3, 0,0,4 }; |
| glPathTexGenNV(GL_TEXTURE0, GL_OBJECT_LINEAR, 4, coefficients); |
| |
| In the latter form, the zeros in the coefficients array would be |
| multiplied by the object-space X and Y so would always evaluate |
| (s,t,r,q) to (1,2,3,4) just as the former GL_CONSTANT version |
| would. |
| |
| GL_CONSTANT also works with glPathColorGenNV and |
| glProgramPathFragmentInputGenNV. |
| |
| 138. What happens to fragment inputs that are not configured by |
| glProgramPathFragmentInputGenNV? |
| |
| RESOLVED: Such variables are forced to constant zero. |
| |
| The default genMode is GL_NONE and this results in a fragment |
| input outputting sc, tc, rc, and qc for its first, second, |
| third, and fourth components respectively. These values |
| are all zero in the case of fragment input generation with |
| glProgramPathFragmentInputGenNV (whereas with glPathTexGenNV, |
| they take on the value of the respective texture coordinate |
| set's current values). |
| |
| 139. The fragment input generation state includes floating-point coefficients |
| but the ARB_program_interface_query extension provides no way |
| to query floating-point state so how can this state be queried? |
| |
| RESOLVED: This extension adds glProgramResourceIndexfvNV to |
| allow floating-point program resource state to be queried. |
| |
| 140. Can a program object with a vertex shader be used to cover paths? |
| |
| RESOLVED: Yes. |
| |
| 141. Is there a technical explanation of this extension beyond the |
| specification itself? |
| |
| RESOLVED: Yes, check out the SIGGRAPH Asia 2012 paper |
| "GPU-accelerated Path Rendering": |
| |
| https://dl.acm.org/citation.cfm?id=2366145.2366191 |
| http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/opengl/gpupathrender.pdf |
| |
| There is an accompanying annex to this paper titled "Programming |
| NV_path_rendering": |
| |
| http://developer.nvidia.com/sites/default/files/akamai/gamedev/files/nvpr_annex.pdf |
| |
| 142. Should conic sections (rational quadratic Bezier segments) be supported? |
| |
| RESOLVED: Yes, Skia supports these. |
| |
| The GL_CONIC_CURVE_TO_NV and GL_RELATIVE_CONIC_CURVE_TO_NV path |
| commands take five path coordinates: |
| |
| x1,y1, x2,y2, w |
| |
| The first two pairs of coordinates are control points similar to |
| the GL_QUADRATIC_CURVE_TO_NV and GL_RELATIVE_QUADRATIC_CURVE_TO_NV |
| path commands. The fifth coordinate "w" is a homogeneous coordinate |
| that applies to the middle (extrapolating) control point. |
| |
| Skia parameterizes its SkPath::kConic_Verb conic curve path |
| command in the same manner. (See Skia's SkConic class in |
| skia/include/core/SkGeometry.h for details.) |
| |
| When the "w" is 1.0, the behavior of the GL_CONIC_CURVE_TO_NV and |
| GL_RELATIVE_CONIC_CURVE_TO_NV commands behave identically to the |
| GL_QUADRATIC_CURVE_TO_NV and GL_RELATIVE_QUADRATIC_CURVE_TO_NV |
| commands respectively; this case corresponds to a parabolic segment. |
| |
| When "w" is less than 1.0, the resulting conic is a partial |
| elliptical arc. When "w" is greater than 1.0, the resulting |
| conic is a hyperbolic arc. |
| |
| See Table 5.pathEquations (Path Equations) for the specific |
| rational quadratic Bezier equations for the GL_CONIC_CURVE_TO_NV |
| and GL_RELATIVE_CONIC_CURVE_TO_NV path commands. |
| |
| The GL_RELATIVE_CONIC_CURVE_TO_NV path command is not supported |
| by Skia but is trivial to support and maintains a symmetry that |
| general-purpose path commands should have relative versions. |
| |
| 143. What happens when the "w" (5th coordinate) of a conic section |
| path command is non-positive? |
| |
| RESOLVED: Match Skia's behavior and treat the path command as |
| a line segment from the current control point to the interpolating |
| control point (x2,y2). |
| |
| At the limit when w nears zero, partial elliptical arcs would |
| become a line segment. |
| |
| 144. Should "smooth" conic sections be supported similar to |
| GL_SMOOTH_QUADRATIC_CURVE_TO_NV? |
| |
| RESOLVED: No. Conceptually, there's no problem supporting |
| smooth conic sections, however no standard supports smooth conic |
| sections to justify the feature. |
| |
| 145. Should there be a "Character alias" for the absolute and relative |
| conic curve commands? |
| |
| RESOLVED: Yes, "W" for GL_CONIC_CURVE_TO_NV and "w" for |
| GL_RELATIVE_CONIC_CURVE_TO_NV are appropriate. |
| |
| 146. Should there be a rational cubic path command? |
| |
| RESOLVED: No way! |
| |
| Rational cubic segments are subject to topological transitions |
| when transformed projectively (as is possible when a path is |
| transformed by the--potentially projective--modelview-projection |
| transform!). |
| |
| 147. Why are rounded rectangles supported? |
| |
| RESOLVED: Rounded rectangles are popular in web content. The W3C's |
| "CSS Backgrounds and Borders Module Level 3" candidate recommendation |
| specifies rounded rectangles and they are popular in web content. |
| |
| http://www.w3.org/TR/css3-background/ |
| |
| Native paths commands for rounded rectangles allow such content |
| to be specified and rasterized with less overhead than comparable |
| specification of the same path with multiple line and arc (or |
| conic) commands. |
| |
| http://www.w3.org/TR/css3-background/#corners |
| |
| 148. Should multiple parameterization for rounded rectangles be |
| supported? |
| |
| RESOLVED: Yes. |
| |
| Both circular and elliptical corners are supported with either |
| uniform (all corners have the same x- and y-axis radii) or |
| per-corner radii. |
| |
| Also relative and absolute versions are supported (including |
| adding an absolute version of GL_RECT_NV for completeness). |
| |
| 149. Should negative x, y, width, height, and radii parameters be allowed |
| for rectangles and rounded rectangles? |
| |
| RESOLVED: Yes. The formulas operate reasonably with negative values. |
| |
| Negative values allow the winding order to be reversed. |
| |
| GL_RECT_NV already allowed negative values. |
| |
| 150. Should the "stencil" and "cover" path operations be combined |
| into a single command? |
| |
| RESOLVED: Yes, these commands are commonly used in sequence and |
| profiling shows combining the commands can provide a small but |
| measurable CPU efficiency benefit by reducing name translation, |
| object locking overhead, and error checking. |
| See the commands: |
| |
| glStencilThenCoverFillPathNV |
| glStencilThenCoverStrokePathNV |
| |
| These commands are specified to behave like a "stencil" command |
| on a path followed immediately by a "cover" command on the same |
| path. |
| |
| There are also instanced versions: |
| |
| glStencilThenCoverFillPathInstancedNV |
| glStencilThenCoverStrokePathInstancedNV |
| |
| These commands can be display listed. |
| |
| Indeed, one advantage of the Instanced versions of the |
| glStencilThenCover* commands is the instanced array can be copied |
| into the display list once. While a display list optimizer |
| could recognize this same benefit, it is simpler to be explicit |
| that there is a single set of transform values used by both the |
| instanced "stencil" and "cover" operations. |
| |
| 151. Should there be a way to get glyph indices for a particular font face |
| to perform advanced text shaping? |
| |
| RESOLVED: Yes, see glPathGlyphIndexArrayNV, |
| glPathMemoryGlyphIndexArrayNV, and glPathGlyphIndexRangeNV. |
| |
| Advanced text shaping APIs such as HarfBuzz and Pango generate |
| combine text with a font face and provide a sequence of glyph |
| indices with corresponding positions to render the text. |
| |
| Mozilla and Google have both confirmed the requirement for this. |
| |
| Advanced text shaping requires more knowledge of scripts and |
| font metrics than can be expressed through NV_path_rendering. |
| There is no interest to attempt, or even try to attempt, exposing |
| sufficient font metrics for advanced text shaping. Instead |
| the presumption is that one or more higher-level libraries |
| (e.g. HarfBuzz + FreeType 2) are used to perform text shaping. |
| |
| While glGetPathSpacingNV is useful and sufficient for providing |
| basic kerning of Latin and other common scripts, but is |
| well-understood to be insufficient for advanced text shaping. |
| |
| 152. Should glPathGlyphIndexRangeNV take the range of path objects |
| as a parameter or return the base & count of path names created |
| from the specified font's glyph indices? |
| |
| RESOLVED: glPathGlyphIndexRangeNV operates like glGenPathsNV |
| to first get an unassigned range of path object names based on |
| the number of glyph indices in the font face. Then specifies |
| the path object for every glyph index. |
| |
| This requires returning a pair of GLuint values for the base |
| and count. Additionally there is a return value to indicate |
| whether and, if not why not, the path objects for the glyphs |
| are assigned and specified. |
| |
| 153. Why were glPathGlyphIndexArrayNV and glPathMemoryGlyphIndexArrayNV |
| added? |
| |
| RESOLVED: Web browsers such as Chrome and other applications |
| relying on glyph indices rely on arranging glyph indices of |
| several fonts together so controlling the order of glyph index |
| arrangement proves important. glPathGlyphIndexRangeNV returns |
| a dynamically allocated range (implicitly using glGenPathsNV) |
| and this proved not well-suited for actual use of glyph indices. |
| |
| 154. Why glPathMemoryGlyphIndexArrayNV added? |
| |
| RESOLVED: Also web sites today very often provide server-supplied |
| fonts via the Web Open Font Format (WOFF) standard. This means |
| fonts are provided by font representations in system memory |
| rather than accessed by file name or system font name. |
| |
| 155. Why is GL_FONT_NUM_GLYPH_INDICES_NV added? |
| |
| RESOLVED: This is a relevant per-font parameter that is useful |
| to ensure that glyphs used by glyph index know the proper bounds |
| on the glyph indices. |
| |
| This per-font parameter is an integer so is not scaled by the |
| emScale. |
| |
| 156. Why does glPathMemoryGlyphIndexArrayNV take a face index? |
| |
| RESOLVED: Implementations are likely to use FreeType 2's |
| FT_New_Memory_Face to implement this functionality. The first |
| face index is zero so normally zero should be passed for the |
| face index. |
| |
| 157. If a face index for glPathMemoryGlyphIndexArrayNV corresponds to |
| a bitmap font or otherwise isn't suitable for providing path |
| objects, what happens? |
| |
| UNRESOLVED: Probably GL_FONT_UNINTELLIGIBLE_NV should be |
| returned. |
| |
| 158. Is glyph index zero special? |
| |
| RESOLVED: According to SNFT conventions, glyph index zero |
| corresponds to the font face's missing glyph. Therefore at |
| least once glyph outline should always exist. |
| |
| 159. Why as GL_FONT_CORRUPT_NV renamed to GL_FONT_UNINTELLIGIBLE_NV? |
| |
| RESOLVED: Because it is hard to distinguish between a font being |
| corrupt and simply not being supported by the implementation. |
| Unintelligible is less misleading and more honest about the |
| situation. |
| |
| 160. Are there alternatives to STANDARD_FONT_FORMAT_NV? |
| |
| RESOLVED: Not currently. There might be a need in the future |
| to identify fonts or glyph outlines with some other token if |
| the font does use the SNFT format. PostScript, TrueType, and |
| OpenType font formats are all SNFT formats. The Web Open Font |
| Format should be supportable too because it contains a magic |
| number with which to identify the format of the binary data. |
| |
| 161. Is the memory provided by glPathMemoryGlyphIndexArrayNV referenced |
| after the command is issued? |
| |
| RESOLVED: No. The GL implementation is responsible for copying |
| from the system memory buffer provided. This likely requires |
| copying the entire buffer. |
| |
| (Perhaps another font target to allowed referenced access to the |
| font data may be a good idea though it would likely require all |
| path objects specified by glPathMemoryGlyphIndexArrayNV to be |
| deleted before freeing the memory. Referencing client system |
| memory is generally considered taboo for GL implementations |
| beyond the duration of a GL command or query's execution however. |
| Copying the buffer avoids any ambiguity and provides for reliable |
| operation, tracing, and network extensibility.) |
| |
| 162. What if glPathGlyphIndexArrayNV or glPathMemoryGlyphIndexArrayNV |
| attempt to specify more path objects than the font supports |
| glyph indices? |
| |
| RESOLVED: Path objects that would correspond to glyph indices |
| that are beyond the maximum glyph index in the font face are |
| not disturbed. |
| |
| For example, if a font face contains 258 glyph indices, but |
| the numGlyphs parameter to glPathGlyphIndexArrayNV is 300, the |
| command silently acts as if 258 glyph indices were requested. |
| No GL error is generated in this case. Also the path objects |
| named firstPathName+258 and beyond are not disturbed. |
| |
| The rationale for this behavior is to avoid needless errors or |
| complexity if an application overestimates the number of glyph |
| indices a font has. |
| |
| 163. What concrete reasons might GL_FONT_TARGET_UNAVAILABLE_NV be |
| generated? |
| |
| RESOLVED: Here are some situations... |
| |
| The Win32 API lacks a way to load a font from a file name. |
| If FreeType 2 is unavailable (say its DLL is missing or |
| the GL implementation simply does not support it), this |
| would cause use of the GL_FILE_NAME_NV target to return |
| GL_FONT_TARGET_UNAVAILABLE_NV. |
| |
| Linux implementations for the X Window System are likely to use |
| FontConfig to map system font names (such as "Arial") to some |
| font file. If the FontConfig shared library is unavailable, |
| cannot be initialized, is a very old version, or its configuration |
| files are missing or corrupt, the GL_SYSTEM_FONT_NAME_NV font |
| target could return GL_FONT_TARGET_UNAVAILABLE_NV. |
| |
| These situations are possible and so applications should |
| anticipate that GL_FONT_TARGET_UNAVAILABLE_NV might be returned |
| but properly configured systems should not be returning this |
| value. Developers debugging this condition should check |
| ARB_debug_output messages for an explanation. |
| |
| 164. What path glyph specification commands support which font targets? |
| |
| RESOLVED: |
| |
| The FILE_NAME_NV, SYSTEM_FONT_NAME_NV, and STANDARD_FONT_NAME_NV |
| font targets are for glPathGlyphsNV and glPathGlyphRangeNV. |
| |
| The FILE_NAME_NV and SYSTEM_FONT_NAME_NV font targets are for |
| glPathGlyphsNV, glPathGlyphRangeNV, glPathGlyphIndexArrayNV, |
| and glPathGlyphIndexRangeNV. STANARD_FONT_NAME_NV does not |
| apply to these commands because standard font name support |
| Unicode character point access to glyphs but not glyph indices. |
| |
| The STANDARD_FONT_FORMAT_NV font target is just for the |
| glPathMemoryGlyphIndexArrayNV command. |
| |
| 165. Why is the GL_PATH_STROKE_BOUND_NV parameter supported? |
| |
| RESOLVED: The path's stroke approximation bound helps the |
| GL implementation and an application bound the amount of |
| approximation error allowed when cubic Bezier path segments or |
| partial elliptical arcs are stenciled. |
| |
| Theory for offset curves indicates determining if a point is |
| within a given offset of a cubic Bezier curve (the generating |
| curve for the offset curve) amounts to solving a 5th degree |
| polynomial equation. That is not tractable in real-time graphics |
| so some approximation of the actual offset curve is assumed. |
| |
| By comparison solve the point containment problem for a sample |
| position with respect to the offset curve of a quadratic Bezier |
| segment requires solving only a 3rd degree polynomial which is |
| tractable for modern GPUs. The assumption here is that stroke |
| point containment with respect to quadratic Bezier segments |
| and linear segments, as well as capping and join geometry, can |
| be tractably solved without analytical approximation (though |
| numerical issues may still limit the accuracy at the limits of |
| available numerical precision). |
| |
| With this in mind, there should be some intuitive bound on |
| the approximation error allowed. The GL_PATH_STROKE_BOUND_NV |
| path parameter provides such an intuitive limit expressed as a |
| percentage of the path's stroke width. |
| |
| 166. Should the radii passed to the GL_ROUNDED_RECT*_NV and |
| GL_RELATIVE_ROUNDED_RECT*_NV support negative values? |
| |
| RESOLVED: Yes. |
| |
| However, the x or y radii are negated if the width or height |
| respectively is negative. This behavior ensures that a rectangle |
| with reversed winding can be specified (useful for cutting out |
| rounded rectangular "holes" in paths) by simply flipping the |
| width or height sign while leaving the radii values positive. |
| |
| The use of the /sign/ function in the specification of the /rrect/ |
| function enforces this behavior. |
| |
| This is important because the GL_ROUNDED_RECT_NV and |
| GL_ROUNDED_RECT4_NV (and relative versions) specify a single |
| circular radius per-rectangle or per-corner respectively without |
| providing an x & y radii. Without the /sign/ terms, it would |
| not be possible to use the these commands and specify a reverse |
| winding rounded rectangle. |
| |
| Still negative values are allowed for the radii and the formula |
| should be applied as specified. Negative radii permit "fins" |
| and "crossed roundings" to be added rounded rectangles. |
| |
| 167. Should CLOSE_PATH_NV count as specifying the start position |
| (sp) for the purposes of determining if the PostScript path |
| commands CIRCULAR_CCW_ARC_TO_NV or CIRCULAR_CW_ARC_TO_NV should |
| change sp to ncp? |
| |
| RESOLVED: No. The PostScript semantic appears to be that |
| a CLOSE_PATH_NV does not set the "current point" to valid. |
| This is based on inspection of Ghostscript behavior. |
| |
| For this reason, the "other than CLOSE_PATH_NV" phrase is placed |
| in the paragraph describing how when these PostScript arc commands |
| change sp. |
| |
| 168. What is the initial glProgramPathFragmentInputGenNV state for all |
| fragment inputs? |
| |
| RESOLVED: See the "Program Object Resource State" table. |
| |
| The GL_PATH_GEN_MODE_NV initial state for every fragment program |
| resource is GL_NONE. |
| |
| The GL_PATH_GEN_COMPONENTS_NV initial state is zero for the |
| number of path fragment input components. |
| |
| The sixteen PATH_GEN_COEFF_NV coefficient values are initially |
| all zero. |
| |
| 169. If glGetProgramResourceiv or glGetProgramResourcefvNV are used on |
| fragment program resources that are not floating-point scalars |
| are vectors, what happens? |
| |
| RESOLVED: While glProgramPathFragmentInputGenNV cannot be used to |
| change such program resources, their state can be queried but |
| simply always returns the intial values. |
| |
| The rationale for this is that implementations already have |
| to return the initial state for fragment inputs that have |
| not yet been specified. Also the ARB_program_interface_query |
| specification specifies returning innocuous or invalid |
| information in preference to generating errors when the query |
| does not apply to the program resource. |
| |
| Always writing back some data in the absence of an error also |
| makes it easier to notice buffer overflow errors since they are |
| not skipped when GL errors are generated. |
| |
| Note that an error *should* be generated by |
| glGetProgramResourceiv and glGetProgramResourcefvNV if |
| GL_PATH_GEN_*_NV queries are performed on a programInterface |
| other than GL_FRAGMENT_INPUT_NV. |
| |
| 170. Should we allow fragment input generation on half and double |
| precision GLSL attributes? |
| |
| RESOLVED: No, just single-precision fragment inputs can be |
| generated. |
| |
| Double-precision attributes only support flat interpolation and |
| that makes no sense for paths. |
| |
| Half-precision attributes could be supported but have |
| no particular advantage on NVIDIA GPUs as half-precision |
| interpolation actually happens in single-precision anyway. |
| |
| glProgramPathFragmentInputGenNV generates GL_INVALID_OPERATION when |
| passed a double-precision or half-precision fragment input |
| (just as it does for any other inappropriate program resource |
| such as a matrix). |
| |
| 171. With glProgramPathFragmentInputGenNV, what fragment input values are |
| generated when the component would normally be the texture |
| coordinate set component for glPathTexGenNV? |
| |
| RESOLVED: Zero. |
| |
| glProgramPathFragmentInputGenNV is specified in terms of PathTexGenNV |
| but there are no fixed-function way to drive varyings. But |
| this specification language says such under-specified varyings |
| will be zero: "Because there is no associated texture coordinate |
| set, the sc, tc, rc, and qc values when discussing PathTexGenNV |
| are always zero when generating fragment input variables." |
| |
| 172. Should glProgramPathFragmentInputGenNV be able to control the |
| path generation of "gl_" prefixed built-in variables? |
| |
| RESOLVED: No. |
| |
| glProgramPathFragmentInputGenNV operates on only fragment inputs |
| that are user-defined, scalar/vector (not matrices, structures, |
| arrays, or opaque types such as samplers), and single-precsion. |
| |
| Built-ins such as gl_TexCoord[0], gl_Color, gl_FogFragCoord |
| are generated with glPathTexGenNV, glPathColorGenNV, and |
| glPathFogGenNV respectively. |
| |
| 173. How does this extension interact with OpenGL ES 2 and 3? |
| |
| RESOLVED: Same as the Core Profile in complete OpenGL. See Issue |
| 133 and the "Dependencies on Core Profile and OpenGL ES" section. |
| |
| 174. OpenGL ES normally does not use or require double-precision |
| floating-point. Does the OpenGL ES version of this extension support |
| the double-precision entry points MatrixLoaddEXT, etc.)? |
| |
| RESOLVED: Yes. This is a conscious choice, and only |
| double-precision support for CPU-side operations is required. See |
| https://github.com/KhronosGroup/OpenGL-Registry/pull/119#issuecomment-341121022 |
| for background. |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- --------- -------------------------------------------- |
| 2 08/26/11 mjk Initial version |
| 3 05/31/12 mjk Fix glPathStencilDepthOffsetNV to accept |
| a GLfloat second parameter; add _BIT to the |
| FONT_*_NV metric token names |
| 4 07/06/12 mjk Issue #128 |
| 5 07/27/12 mjk Fix getPathName return value sense; |
| Issue #129 and #130; UTF-8 and UTF-16 |
| decoding fixes. |
| 6 05/23/13 mjk Fix typo in Table 5.pathEquations |
| 7 06/25/13 mjk Fix token names missing _BIT_NV suffix |
| 8 08/01/13 mjk Bad argument order in instanced example |
| 9 08/22/13 mjk Fix GL_EYE_LINEAR behavior |
| 10 09/09/13 mjk Add core profile + smaller matrix support |
| 11 09/10/13 mjk Add conic segment path commands |
| 12 09/18/13 mjk Add rounded rectangles, GL_RELATIVE_RECT_NV, |
| missing new matrix language, fix typos |
| 13 10/21/13 mjk <fontStyle> parameter for PathGlyphsNV |
| and PathGlyphRangeNV |
| 14 11/05/13 dsn Use consistent argument names |
| 15 11/08/13 mjk Add StencilThenCover* commands |
| 16 11/11/13 mjk Add PathGlyphIndexRange command |
| 17 01/07/14 mjk Fix typos |
| 18 01/07/14 mjk Add PathGlyphIndexArray and |
| PathMemoryGlyphIndexArray commands and |
| FONT_NUM_GLYPH_INDICES_NV path query; |
| renamed FONT_CORRUPT_NV to FONT_UNINTELLIGIBLE_NV |
| 19 02/12/14 mjk Document GL_PATH_STROKE_BOUND_NV |
| 20 02/14/14 mjk Fix rounded rectangle radii sign behavior |
| (see issue 166) |
| 21 02/19/14 mjk Refashion the rrect function |
| 22 02/22/14 mjk PostScript arc behavior; see issue 167 |
| 23 03/06/14 mjk Document FONT_NUM_GLYPH_INDICES_BIT_NV |
| interactions; STANDARD_FONT_FORMAT_NV only |
| for glPathMemoryGlyphIndexArrayNV |
| 24 03/18/14 mjk Update glPathFragmentInputGenNV state |
| and query specification; issues 168-171 |
| 25 03/19/14 mjk Better NVpr 1.3 explanation |
| 26 03/20/14 mjk Issue 172 |
| 27 04/15/14 mjk ES interactions same as Core Profile |
| 28 05/02/14 mjk Updated status |
| 29 05/15/14 mjk Matrix*Tranpose to Matrix*Transpose |
| 30 05/29/14 mjk Release 1.3 driver details |
| 31 07/02/14 dkoch Fix a variety of typos and inconsistencies |
| Update ES interactions |
| Fix pseudocode (float vs double, renderBoundingBox) |
| 32 07/24/14 mjk Fix Equation 5.generalParametricArc typos, |
| thanks to Chris Hebert |
| 33 08/19/14 mjk Add missing 1.3 additions to revisions section |
| 34 08/27/14 mjk Remove bogus polygon offset issue 127; my mistake |
| 35 09/09/14 mjk Intro: fix translate mode, add StencilThenCover |
| 36 11/01/17 Jon Leech Add issue 174 on double-precision ES support |