VKVG_STATUS_INVALID_FORMAT,
VKVG_STATUS_INVALID_VISUAL,
VKVG_STATUS_FILE_NOT_FOUND,
- VKVG_STATUS_INVALID_DASH
+ VKVG_STATUS_INVALID_DASH,
+ VKVG_STAtUS_NOT_ENOUGH_POINTS_TO_CLOSE_PATH
}vkvg_status_t;
typedef enum {
* @param context pointer
*/
void vkvg_close_path (VkvgContext ctx){
- if (_current_path_is_empty(ctx)){
- ctx->status = VKVG_STATUS_NO_CURRENT_POINT;
+ //check if at least 3 points are present
+ if (ctx->pathes[ctx->pathPtr] < 3){
+ ctx->status = VKVG_STAtUS_NOT_ENOUGH_POINTS_TO_CLOSE_PATH;
return;
}
- //check if at least 3 points are present
- if (ctx->pointCount - (ctx->pathes [ctx->pathPtr-1]&PATH_ELT_MASK) > 2){
- ctx->pathes[ctx->pathPtr] = ctx->pointCount - 1;
- ctx->pathes[ctx->pathPtr-1] |= PATH_CLOSED_BIT;
- _check_pathes_array(ctx);
- ctx->pathPtr += ctx->curvePtr + 1;
- ctx->curvePtr = 0;
- }else
- _finish_path(ctx);
+ //prevent closing on the same point
+ if (vec2_equ(ctx->points[ctx->pointCount-1],
+ ctx->points[ctx->pointCount - ctx->pathes[ctx->pathPtr]]))
+ _remove_last_point(ctx);
+
+ ctx->pathes[ctx->pathPtr] |= PATH_CLOSED_BIT;
+
+ _finish_path(ctx);
}
/**
* @brief draw line with second point coordinates relative to current point
void vkvg_line_to (VkvgContext ctx, float x, float y)
{
vec2 p = {x,y};
- if (_current_path_is_empty(ctx)){
- vkvg_move_to(ctx, x,y);
- return;
- }else if (vec2_equ(_get_current_position(ctx),p))
- return;
-
- _add_point(ctx,x,y);
+ if (!_current_path_is_empty (ctx)){
+ //prevent adding the same point
+ if (vec2_equ (_get_current_position (ctx), p))
+ return;
+ }
+ _add_point (ctx, x, y);
}
/**
* @brief Draw arc in clockwise order following angles of the trigonometric circle.
float step = _get_arc_step(ctx, radius);
float a = a1;
- if (_current_path_is_empty(ctx))
- vkvg_move_to(ctx, v.x, v.y);
- else
+ if (_current_path_is_empty(ctx)){
+ _set_curve_start (ctx);
+ _add_point (ctx, v.x, v.y);
+ }else{
vkvg_line_to(ctx, v.x, v.y);
+ _set_curve_start (ctx);
+ }
a+=step;
if (EQUF(a2, a1))
return;
- _set_curve_start (ctx);
-
while(a < a2){
v.x = cosf(a)*radius + xc;
v.y = sinf(a)*radius + yc;
float step = _get_arc_step(ctx, radius);
float a = a1;
- if (_current_path_is_empty(ctx))
- vkvg_move_to(ctx, v.x, v.y);
- else {
+ if (_current_path_is_empty(ctx)){
+ _set_curve_start (ctx);
+ _add_point (ctx, v.x, v.y);
+ }else{
vkvg_line_to(ctx, v.x, v.y);
+ _set_curve_start (ctx);
}
a-=step;
if (EQUF(a2, a1))
return;
- _set_curve_start (ctx);
-
while(a > a2){
v.x = cosf(a)*radius + xc;
v.y = sinf(a)*radius + yc;
void vkvg_move_to (VkvgContext ctx, float x, float y)
{
_finish_path(ctx);
- _start_sub_path(ctx, x, y);
+ _add_point (ctx, x, y);
}
void vkvg_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
+ _set_curve_start (ctx);
if (_current_path_is_empty(ctx))
- vkvg_move_to(ctx, x1, y1);
+ _add_point(ctx, x1, y1);
vec2 cp = _get_current_position(ctx);
- _set_curve_start (ctx);
_recursive_bezier (ctx, cp.x, cp.y, x1, y1, x2, y2, x3, y3, 0);
/*cp.x = x3;
cp.y = y3;
CmdSetStencilCompareMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
}
void vkvg_fill_preserve (VkvgContext ctx){
- if (ctx->pathPtr == 0) //nothing to fill
+ if (!(ctx->pathPtr || ctx->segmentPtr)) //nothing to fill
return;
_finish_path(ctx);
}
void vkvg_stroke_preserve (VkvgContext ctx)
{
- if (ctx->pathPtr == 0)//nothing to stroke
+ if (ctx->pathPtr == 0 && _current_path_is_empty(ctx))//nothing to stroke
return;
_finish_path(ctx);
curPathPointIdx = lastPathPointIdx = ptrPath = iL = iR = 0;
while (ptrPath < ctx->pathPtr){
- uint32_t ptrCurve = 0;
+ uint32_t ptrSegment = 0, lastSegmentPointIdx = 0;
+ uint32_t firstPathPointIdx = curPathPointIdx;
+ uint32_t pathPointCount = ctx->pathes[ptrPath]&PATH_ELT_MASK;
+ lastPathPointIdx = curPathPointIdx + pathPointCount - 1;
+ if (_path_has_curves (ctx,ptrPath)) {
+ ptrSegment = 1;
+ lastSegmentPointIdx = curPathPointIdx + (ctx->pathes[ptrPath+ptrSegment]&PATH_ELT_MASK)-1;
+ }
VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- curPathPointIdx = ctx->pathes[ptrPath]&PATH_ELT_MASK;
-
- LOG(VKVG_LOG_INFO_PATH, "\tPATH: start=%d end=%d", ctx->pathes[ptrPath]&PATH_ELT_MASK, ctx->pathes[ptrPath+1]&PATH_ELT_MASK);
- lastPathPointIdx = ctx->pathes[ptrPath+1]&PATH_ELT_MASK;
+ //LOG(VKVG_LOG_INFO_PATH, "\tPATH: start=%d end=%d", ctx->pathes[ptrPath]&PATH_ELT_MASK, ctx->pathes[ptrPath+1]&PATH_ELT_MASK);
LOG(VKVG_LOG_INFO_PATH, "end = %d\n", lastPathPointIdx);
if (ctx->dashCount > 0) {
iL = lastPathPointIdx;
} else if (_path_is_closed(ctx,ptrPath)){
- //prevent closing on the same position, this could be generalize
- //to prevent processing of two consecutive point at the same position
- if (vec2_equ(ctx->points[curPathPointIdx], ctx->points[lastPathPointIdx]))
- lastPathPointIdx--;
iL = lastPathPointIdx;
}else{
_draw_stoke_cap(ctx, hw, ctx->points[curPathPointIdx], vec2_line_norm(ctx->points[curPathPointIdx], ctx->points[curPathPointIdx+1]), true);
if (_path_has_curves (ctx,ptrPath)) {
while (curPathPointIdx < lastPathPointIdx){
- if (ptrPath + ptrCurve + 2 < ctx->pathPtr && (ctx->pathes [ptrPath + 2 + ptrCurve] & PATH_ELT_MASK) == curPathPointIdx){
- uint32_t lastCurvePointIdx = ctx->pathes[ptrPath + 3 + ptrCurve]&PATH_ELT_MASK;
- while (curPathPointIdx < lastCurvePointIdx)
- _draw_segment(ctx, hw, true);
- ptrCurve += 2;
- }else
- _draw_segment(ctx, hw, false);
+
+ bool curved = ctx->pathes [ptrPath + ptrSegment] & PATH_IS_CURVE_BIT;
+ if (lastSegmentPointIdx == lastPathPointIdx)//last segment of path, dont draw end point here
+ lastSegmentPointIdx--;
+ while (curPathPointIdx <= lastSegmentPointIdx)
+ _draw_segment(ctx, hw, curved);
+
+ ptrSegment ++;
+ uint32_t cptSegPts = ctx->pathes [ptrPath + ptrSegment]&PATH_ELT_MASK;
+ lastSegmentPointIdx = curPathPointIdx + cptSegPts - 1;
+ if (lastSegmentPointIdx == lastPathPointIdx && cptSegPts == 1) {
+ //single point last segment
+ ptrSegment++;
+ break;
+ }
}
}else while (curPathPointIdx < lastPathPointIdx)
_draw_segment(ctx, hw, false);
if (ctx->dashCount > 0) {
if (_path_is_closed(ctx,ptrPath)){
- iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+ iR = firstPathPointIdx;
_draw_dashed_segment(ctx, hw, ctx->points[iL++], ctx->points[curPathPointIdx++], ctx->points[iR], false);
}
if (!dashOn){
_draw_stoke_cap (ctx, hw, p, normal, false);
}
} else if (_path_is_closed(ctx,ptrPath)){
- iR = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+ iR = firstPathPointIdx;
float cross = _build_vb_step (ctx, hw, ctx->points[iL], ctx->points[curPathPointIdx], ctx->points[iR], false);
VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6];
}else
_draw_stoke_cap (ctx, hw, ctx->points[curPathPointIdx], vec2_line_norm(ctx->points[curPathPointIdx-1], ctx->points[curPathPointIdx]), false);
- ptrPath+=2+ptrCurve;
+ curPathPointIdx = firstPathPointIdx + pathPointCount;
+
+ if (ptrSegment > 0)
+ ptrPath += ptrSegment;
+ else
+ ptrPath++;
}
_record_draw_cmd(ctx);
}
}
ctx->indexCache = tmp;
}
-void _check_pathes_array (VkvgContext ctx){
- if (ctx->sizePathes - ctx->pathPtr - ctx->curvePtr > VKVG_ARRAY_THRESHOLD)
- return;
+//check host path array size, return true if error. pathPtr is already incremented
+bool _check_pathes_array (VkvgContext ctx){
+ if (ctx->sizePathes - ctx->pathPtr - ctx->segmentPtr > VKVG_ARRAY_THRESHOLD)
+ return false;
ctx->sizePathes += VKVG_PATHES_SIZE;
uint32_t* tmp = (uint32_t*) realloc (ctx->pathes, (size_t)ctx->sizePathes * sizeof(uint32_t));
LOG(VKVG_LOG_DBG_ARRAYS, "resize PATH: new size: %u Ptr: %p -> %p\n", ctx->sizePathes, ctx->pathes, tmp);
if (tmp == NULL){
ctx->status = VKVG_STATUS_NO_MEMORY;
LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePathes * sizeof(uint32_t));
- ctx->pathPtr = 0 + (ctx->pathPtr % 2);
- }else
- ctx->pathes = tmp;
+ _clear_path(ctx);
+ return true;
+ }
+ ctx->pathes = tmp;
+ return false;
}
-void _check_point_array (VkvgContext ctx){
+//check host point array size, return true if error
+bool _check_point_array (VkvgContext ctx){
if (ctx->sizePoints - ctx->pointCount > VKVG_ARRAY_THRESHOLD)
- return;
- ctx->sizePoints += VKVG_PATHES_SIZE;
+ return false;
+ ctx->sizePoints += VKVG_PTS_SIZE;
vec2* tmp = (vec2*) realloc (ctx->points, (size_t)ctx->sizePoints * sizeof(vec2));
LOG(VKVG_LOG_DBG_ARRAYS, "resize Points: new size(point): %u Ptr: %p -> %p\n", ctx->sizePoints, ctx->points, tmp);
if (tmp == NULL){
ctx->status = VKVG_STATUS_NO_MEMORY;
LOG(VKVG_LOG_ERR, "resize PATH failed: new size(byte): %zu\n", ctx->sizePoints * sizeof(vec2));
- ctx->pointCount = 0;
- }else
- ctx->points = tmp;
+ _clear_path (ctx);
+ return true;
+ }
+ ctx->points = tmp;
+ return false;
}
-//when empty, ptr is even, else it's odd
-//when empty, no current point is defined.
bool _current_path_is_empty (VkvgContext ctx) {
- return ctx->pathPtr % 2 == 0;
+ return ctx->pathes [ctx->pathPtr] == 0;
}
//this function expect that current point exists
vec2 _get_current_position (VkvgContext ctx) {
}
//set curve start point and set path has curve bit
void _set_curve_start (VkvgContext ctx) {
- ctx->pathes[ctx->pathPtr + ctx->curvePtr + 1] = (ctx->pointCount - 1);
- ctx->pathes[ctx->pathPtr - 1] |= PATH_HAS_CURVES_BIT;
+ if (ctx->segmentPtr > 0) {
+ //check if current segment has points (straight)
+ if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) > 0)
+ ctx->segmentPtr++;
+ }else{
+ //not yet segmented path, first segment length is copied
+ if (ctx->pathes [ctx->pathPtr] > 0){//create first straight segment first
+ ctx->pathes [ctx->pathPtr + 1] = ctx->pathes [ctx->pathPtr];
+ ctx->segmentPtr = 2;
+ }else
+ ctx->segmentPtr = 1;
+ }
+ _check_pathes_array(ctx);
+ ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
}
-//set curve end point and set path is curve bit
+//compute segment length and set is curved bit
void _set_curve_end (VkvgContext ctx) {
- ctx->pathes [ctx->pathPtr + ctx->curvePtr + 2] = (ctx->pointCount - 1) | PATH_IS_CURVE_BIT;
- ctx->curvePtr+=2;
+ //ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = ctx->pathes [ctx->pathPtr] - ctx->pathes [ctx->pathPtr + ctx->segmentPtr];
+ ctx->pathes [ctx->pathPtr + ctx->segmentPtr] |= PATH_IS_CURVE_BIT;
+ ctx->segmentPtr++;
_check_pathes_array(ctx);
+ ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;
}
//path start pointed at ptrPath has curve bit
bool _path_has_curves (VkvgContext ctx, uint32_t ptrPath) {
}
//this function expect that current path is empty
void _start_sub_path (VkvgContext ctx, float x, float y) {
- //set start to current idx in point array
- ctx->pathes[ctx->pathPtr] = ctx->pointCount;
- _add_point(ctx, x, y);
- _check_pathes_array(ctx);
- ctx->pathPtr++;
+ _add_point (ctx, x, y);
}
void _finish_path (VkvgContext ctx){
- if (_current_path_is_empty(ctx))
+ if (ctx->pathes [ctx->pathPtr] == 0)//empty
return;
- if (ctx->pathes[ctx->pathPtr-1] == ctx->pointCount - 1){
+ if ((ctx->pathes [ctx->pathPtr]&PATH_ELT_MASK) < 2){
//only current pos is in path
- ctx->pathPtr--;
+ ctx->pointCount -= ctx->pathes[ctx->pathPtr];//what about the bounds?
+ ctx->pathes[ctx->pathPtr] = 0;
+ ctx->segmentPtr = 0;
return;
}
- //set end index of current path to last point in points array
- ctx->pathes[ctx->pathPtr] = ctx->pointCount - 1;
- _check_pathes_array(ctx);
- ctx->pathPtr += ctx->curvePtr + 1;
- ctx->curvePtr = 0;
+ if (ctx->segmentPtr > 0) {
+ ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT;
+ //if last segment is not a curve and point count > 0
+ if ((ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_IS_CURVE_BIT)==0 &&
+ (ctx->pathes[ctx->pathPtr+ctx->segmentPtr]&PATH_ELT_MASK) > 0)
+ ctx->segmentPtr++;//current segment has to be included
+ ctx->pathPtr += ctx->segmentPtr;
+ }else
+ ctx->pathPtr ++;
+
+ if (_check_pathes_array(ctx))
+ return;
+
+ ctx->pathes[ctx->pathPtr] = 0;
+ ctx->segmentPtr = 0;
}
+//clear path datas in context
void _clear_path (VkvgContext ctx){
ctx->pathPtr = 0;
+ ctx->pathes [ctx->pathPtr] = 0;
ctx->pointCount = 0;
- ctx->curvePtr = 0;
+ ctx->segmentPtr = 0;
_resetMinMax(ctx);
}
+void _remove_last_point (VkvgContext ctx){
+ ctx->pathes[ctx->pathPtr]--;
+ ctx->pointCount--;
+ if (ctx->segmentPtr > 0){//if path is segmented
+ if (!ctx->pathes [ctx->pathPtr + ctx->segmentPtr])//if current segment is empty
+ ctx->segmentPtr--;
+ ctx->pathes [ctx->pathPtr + ctx->segmentPtr]--;//decrement last segment point count
+ if ((ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_ELT_MASK) == 0)//if no point left (was only one)
+ ctx->pathes [ctx->pathPtr + ctx->segmentPtr] = 0;//reset current segment
+ else if (ctx->pathes [ctx->pathPtr + ctx->segmentPtr]&PATH_IS_CURVE_BIT)//if segment is a curve
+ ctx->segmentPtr++;//then segPtr has to be forwarded to new segment
+ }
+}
bool _path_is_closed (VkvgContext ctx, uint32_t ptrPath){
return ctx->pathes[ptrPath] & PATH_CLOSED_BIT;
}
ctx->xMax = ctx->yMax = FLT_MIN;
}
void _add_point (VkvgContext ctx, float x, float y){
- ctx->points[ctx->pointCount] = (vec2){x,y};
- ctx->pointCount++;
+ if (_check_point_array(ctx))
+ return;
- _check_point_array(ctx);
+ ctx->points[ctx->pointCount] = (vec2){x,y};
+ ctx->pointCount++;//total point count of pathes, (for array bounds check)
+ ctx->pathes[ctx->pathPtr]++;//total point count in path
+ if (ctx->segmentPtr > 0)
+ ctx->pathes[ctx->pathPtr + ctx->segmentPtr]++;//total point count in path's segment
//bounds are computed here to scissor the painting operation
//that speed up fill drastically.
CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelinePolyFill);
- uint32_t ptrPath = 0;
Vertex v = {{0},{0,0,-1}};
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
while (ptrPath < ctx->pathPtr){
- if (ctx->pathes[ptrPath+1]&PATH_IS_CURVE_BIT){
- ptrPath += 2;
- continue;
- }
//close path
ctx->pathes[ptrPath] |= PATH_CLOSED_BIT;
- uint32_t firstPtIdx = ctx->pathes [ptrPath] & PATH_ELT_MASK;
- uint32_t lastPtIdx = ctx->pathes [ptrPath+1] & PATH_ELT_MASK;
- uint32_t pathPointCount = lastPtIdx - firstPtIdx + 1;
- uint32_t firstVertIdx = ctx->vertCount;
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
for (uint32_t i = 0; i < pathPointCount; i++) {
v.pos = ctx->points [i+firstPtIdx];
- ctx->vertexCache[ctx->vertCount] = v;
- ctx->vertCount++;
-
+ ctx->vertexCache[ctx->vertCount++] = v;
_check_vertex_cache_size(ctx);
}
LOG(VKVG_LOG_INFO_PATH, "\tpoly fill: point count = %d; 1st vert = %d; vert count = %d\n", pathPointCount, firstVertIdx, ctx->vertCount - firstVertIdx);
CmdDraw (ctx->cmd, pathPointCount, 1, firstVertIdx , 0);
- ptrPath+=2;
+ firstPtIdx += pathPointCount;
+
+ if (_path_has_curves (ctx, ptrPath)) {
+ //skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ }else
+ ptrPath++;
}
ctx->curVertOffset = ctx->vertCount;
}
void _fill_ec (VkvgContext ctx){
- uint32_t ptrPath = 0;;
Vertex v = {0};
v.uv.z = -1;
+ uint32_t ptrPath = 0;
+ uint32_t firstPtIdx = 0;
+
while (ptrPath < ctx->pathPtr){
- if (ctx->pathes[ptrPath+1] & PATH_IS_CURVE_BIT){
- ptrPath += 2;
- continue;
- }
ctx->pathes[ptrPath] |= PATH_CLOSED_BIT;//close path
- uint32_t firstPtIdx = ctx->pathes[ptrPath] &PATH_ELT_MASK;
- uint32_t lastPtIdx = ctx->pathes[ptrPath+1]&PATH_ELT_MASK;
- uint32_t pathPointCount = lastPtIdx - firstPtIdx + 1;
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
+
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
uint32_t ecps_count = pathPointCount;
if (ecps_count == 3)
_add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
- ptrPath+=2;
+ firstPtIdx += pathPointCount;
+ if (_path_has_curves (ctx, ptrPath)) {
+ //skip segments lengths used in stroke
+ ptrPath++;
+ uint32_t totPts = 0;
+ while (totPts < pathPointCount)
+ totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
+ }else
+ ptrPath++;
free (ecps);
}
_record_draw_cmd(ctx);
uint32_t sizePoints; //reserved size
uint32_t pointCount; //effective points count
- //pathes array is a list of couple (start,end) point idx refering to point array
- //it split points list in subpathes and tell if path is closed.
- uint32_t pathPtr; //pointer in the path array, even=start point;odd=end point
+ //pathes array is a list of point count per segment
+ uint32_t pathPtr; //pointer in the path array
uint32_t* pathes;
uint32_t sizePathes;
- //if current path contains curves, curve's start/end points are store next to the path start/stop
- //curve start point = pathPtr + curvePtr
- //when closing of finishing path, pathPtr is incremented by 1 + pathPtr
- //note:number of pathes can no longer be computed from pathPtr/2, the array contains now curves datas
- uint32_t curvePtr;
+ uint32_t segmentPtr; //current segment count in current path having curves
float lineWidth;
uint32_t dashCount; //value count in dash array, 0 if dash not set.
void _check_vertex_cache_size(VkvgContext ctx);
void _resize_vertex_cache (VkvgContext ctx, uint32_t newSize);
void _check_index_cache_size(VkvgContext ctx);
-void _check_pathes_array (VkvgContext ctx);
+bool _check_pathes_array (VkvgContext ctx);
bool _current_path_is_empty (VkvgContext ctx);
void _start_sub_path (VkvgContext ctx, float x, float y);
void _finish_path (VkvgContext ctx);
void _clear_path (VkvgContext ctx);
+void _remove_last_point (VkvgContext ctx);
bool _path_is_closed (VkvgContext ctx, uint32_t ptrPath);
void _set_curve_start (VkvgContext ctx);
void _set_curve_end (VkvgContext ctx);
#endif*/
#define PATH_CLOSED_BIT 0x80000000 /* most significant bit of path elmts is closed/open path state */
-#define PATH_HAS_CURVES_BIT 0x40000000 /* 2d most significant bit of path elmts start = true if curve data are present,
- stored to avoid emiting join in curves */
+#define PATH_HAS_CURVES_BIT 0x40000000 /* 2d most significant bit of path elmts if curve data are present,
+ stored to avoid emiting joins in curves */
#define PATH_IS_CURVE_BIT 0x80000000 /* most significant bit of path elmts end mark curves data in path array */
#define PATH_IS_CONCAVE_BIT 0x40000000 /* 2d most significant bit of path elmts end = true if path is simple concave
- triangulation for fill may be simplified*/
+ triangulation for fill may be simplified (not implemented)*/
#define PATH_ELT_MASK 0x3FFFFFFF /* Bit mask for fetching path element value */
#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))