VG_API_CALL void vgMultMatrix(const VGfloat * mm) { SHMatrix3x3 *m, mul, temp; VG_GETCONTEXT(VG_NO_RETVAL); VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* TODO: check matrix array alignment */ m = shCurrentMatrix(context); if (context->matrixMode == VG_MATRIX_IMAGE_USER_TO_SURFACE) { SETMAT(mul, mm[0], mm[3], mm[6], mm[1], mm[4], mm[7], mm[2], mm[5], mm[8]); } else { SETMAT(mul, mm[0], mm[3], mm[6], mm[1], mm[4], mm[7], 0.0f, 0.0f, 1.0f); } MULMATMAT((*m), mul, temp); SETMATMAT((*m), temp); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL void vgSetParameteri(VGHandle object, VGint paramType, VGint value) { SHResourceType resType; VG_GETCONTEXT(VG_NO_RETVAL); /* Validate object */ resType = shGetResourceType(context, object); VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID, VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* Check if param vector */ VG_RETURN_ERR_IF(shIsParamVector(paramType), VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* Error code will be set by shSetParam() */ shSetParameter(context, object, resType, paramType, 1, &value, 0); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL VGfloat vgGetParameterf(VGHandle object, VGint paramType) { VGfloat retval = 0.0f; SHResourceType resType; VG_GETCONTEXT(retval); /* Validate object */ resType = shGetResourceType(context, object); VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID, VG_BAD_HANDLE_ERROR, retval); /* Check if param vector */ VG_RETURN_ERR_IF(shIsParamVector(paramType), VG_ILLEGAL_ARGUMENT_ERROR, retval); /* Error code will be set by shGetParameter() */ shGetParameter(context, object, resType, paramType, 1, &retval, 1); VG_RETURN(retval); }
VG_API_CALL void vgPaintPattern(VGPaint paint, VGImage pattern) { VG_GETCONTEXT(VG_NO_RETVAL); /* Check if handle valid */ VG_RETURN_ERR_IF(!shIsValidPaint(context, paint), VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* Check if pattern image valid */ VG_RETURN_ERR_IF(!shIsValidImage(context, pattern), VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* TODO: Check if pattern image is current rendering target */ /* Set pattern image */ ((SHPaint*)paint)->pattern = pattern; VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL void vgSetPaint(VGPaint paint, VGbitfield paintModes) { VG_GETCONTEXT(VG_NO_RETVAL); /* Check if handle valid */ VG_RETURN_ERR_IF(!shIsValidPaint(context, paint) && paint != VG_INVALID_HANDLE, VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* Check for invalid mode */ VG_RETURN_ERR_IF(paintModes & ~(VG_STROKE_PATH | VG_FILL_PATH), VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* Set stroke / fill */ if (paintModes & VG_STROKE_PATH) context->strokePaint = (SHPaint*)paint; if (paintModes & VG_FILL_PATH) context->fillPaint = (SHPaint*)paint; VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL void vgSeti (VGParamType type, VGint value) { VG_GETCONTEXT(VG_NO_RETVAL); /* Check if target vector */ VG_RETURN_ERR_IF(shIsParamVector(type), VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* Error code will be set by shSet */ shSet(context, type, 1, &value, 0); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL VGint vgGeti(VGParamType type) { VGint retval = 0; VG_GETCONTEXT(retval); /* Check if target vector */ VG_RETURN_ERR_IF(shIsParamVector(type), VG_ILLEGAL_ARGUMENT_ERROR, retval); /* Error code will be set by shGet */ shGet(context, type, 1, &retval, 0); VG_RETURN(retval); }
VG_API_CALL void vgDestroyPaint(VGPaint paint) { SHint index; VG_GETCONTEXT(VG_NO_RETVAL); /* Check if handle valid */ index = shPaintArrayFind(&context->paints, (SHPaint*)paint); VG_RETURN_ERR_IF(index == -1, VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* Delete object and remove resource */ SH_DELETEOBJ(SHPaint, (SHPaint*)paint); shPaintArrayRemoveAt(&context->paints, index); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL VGPaint vgCreatePaint(void) { SHPaint *p = NULL; VG_GETCONTEXT(VG_INVALID_HANDLE); /* Create new paint object */ SH_NEWOBJ(SHPaint, p); VG_RETURN_ERR_IF(!p, VG_OUT_OF_MEMORY_ERROR, VG_INVALID_HANDLE); /* Add to resource list */ shPaintArrayPushBack(&context->paints, p); VG_RETURN((VGPaint)p); }
VG_API_CALL void vgGetMatrix(VGfloat * mm) { SHMatrix3x3 *m; int i,j,k=0; VG_GETCONTEXT(VG_NO_RETVAL); VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* TODO: check matrix array alignment */ m = shCurrentMatrix(context); for (i=0; i<3; ++i) for (j=0; j<3; ++j) mm[k++] = m->m[j][i]; VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL void vgGetParameteriv(VGHandle object, VGint paramType, VGint count, VGint * values) { SHResourceType resType; VG_GETCONTEXT(VG_NO_RETVAL); /* Validate object */ resType = shGetResourceType(context, object); VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID, VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* TODO: Check output array alignment */ /* Error code will be set by shGetParameter() */ shGetParameter(context, object, resType, paramType, count, values, 0); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL VGint vgGetParameterVectorSize(VGHandle object, VGint ptype) { int retval = 0; SHResourceType rtype; VG_GETCONTEXT(retval); /* Validate object */ rtype = shGetResourceType(context, object); VG_RETURN_ERR_IF(rtype == SH_RESOURCE_INVALID, VG_BAD_HANDLE_ERROR, retval); switch (rtype) { case SH_RESOURCE_PATH: switch (ptype) { /* Path parameters */ case VG_PATH_FORMAT: case VG_PATH_DATATYPE: case VG_PATH_SCALE: case VG_PATH_BIAS: case VG_PATH_NUM_SEGMENTS: case VG_PATH_NUM_COORDS: retval = 1; break; default: /* Invalid VGParamType */ VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval); } break; case SH_RESOURCE_PAINT: switch (ptype) { /* Paint parameters */ case VG_PAINT_TYPE: retval = 1; break; case VG_PAINT_COLOR: retval = 4; break; case VG_PAINT_COLOR_RAMP_SPREAD_MODE: retval = 1; break; case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: retval = 1; break; case VG_PAINT_COLOR_RAMP_STOPS: retval = ((SHPaint*)object)->stops.size*5; break; case VG_PAINT_LINEAR_GRADIENT: retval = 4; break; case VG_PAINT_RADIAL_GRADIENT: retval = 5; break; case VG_PAINT_PATTERN_TILING_MODE: retval = 1; break; default: /* Invalid VGParamType */ VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval); } break; case SH_RESOURCE_IMAGE: switch (ptype) { /* Image parameters */ case VG_IMAGE_FORMAT: case VG_IMAGE_WIDTH: case VG_IMAGE_HEIGHT: retval = 1; break; default: /* Invalid VGParamType */ VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval); } break; default: /* Invalid resource handle */ SH_ASSERT(rtype!=SH_RESOURCE_INVALID); break; } VG_RETURN(retval); }
VG_API_CALL void vgDrawImage(VGImage image) { SHImage *i; SHfloat mgl[16]; SHfloat texGenS[4] = {0,0,0,0}; SHfloat texGenT[4] = {0,0,0,0}; SHPaint *fill; SHVector2 min, max; SHRectangle *rect; VG_GETCONTEXT(VG_NO_RETVAL); VG_RETURN_ERR_IF(!shIsValidImage(context, image), VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); /* TODO: check if image is current render target */ /* Check whether scissoring is enabled and scissor rectangle is valid */ if (context->scissoring == VG_TRUE) { rect = &context->scissor.items[0]; if (context->scissor.size == 0) VG_RETURN( VG_NO_RETVAL ); if (rect->w <= 0.0f || rect->h <= 0.0f) VG_RETURN( VG_NO_RETVAL ); glScissor( (GLint)rect->x, (GLint)rect->y, (GLint)rect->w, (GLint)rect->h ); glEnable( GL_SCISSOR_TEST ); } /* Apply image-user-to-surface transformation */ i = (SHImage*)image; shMatrixToGL(&context->imageTransform, mgl); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(mgl); /* Clamp to edge for proper filtering, modulate for multiply mode */ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, i->texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); /* Adjust antialiasing to settings */ if (context->imageQuality == VG_IMAGE_QUALITY_NONANTIALIASED) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glDisable(GL_MULTISAMPLE); }else{ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glEnable(GL_MULTISAMPLE); } /* Generate image texture coords automatically */ texGenS[0] = 1.0f / i->texwidth; texGenT[1] = 1.0f / i->texheight; glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, texGenS); glTexGenfv(GL_T, GL_OBJECT_PLANE, texGenT); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); /* Pick fill paint */ fill = (context->fillPaint ? context->fillPaint : &context->defaultPaint); /* Use paint color when multiplying with a color-paint */ if (context->imageMode == VG_DRAW_IMAGE_MULTIPLY && fill->type == VG_PAINT_TYPE_COLOR) glColor4fv((GLfloat*)&fill->color); else glColor4f(1,1,1,1); /* Check image drawing mode */ if (context->imageMode == VG_DRAW_IMAGE_MULTIPLY && fill->type != VG_PAINT_TYPE_COLOR) { /* Draw image quad into stencil */ glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); glBegin(GL_QUADS); glVertex2i(0, 0); glVertex2i(i->width, 0); glVertex2i(i->width, i->height); glVertex2i(0, i->height); glEnd(); /* Setup blending */ updateBlendingStateGL(context, 0); /* Draw gradient mesh where stencil 1*/ glEnable(GL_TEXTURE_2D); glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_ZERO,GL_ZERO,GL_ZERO); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); SET2(min,0,0); SET2(max, (SHfloat)i->width, (SHfloat)i->height); if (fill->type == VG_PAINT_TYPE_RADIAL_GRADIENT) { shDrawRadialGradientMesh(fill, &min, &max, VG_FILL_PATH, GL_TEXTURE1); }else if (fill->type == VG_PAINT_TYPE_LINEAR_GRADIENT) { shDrawLinearGradientMesh(fill, &min, &max, VG_FILL_PATH, GL_TEXTURE1); }else if (fill->type == VG_PAINT_TYPE_PATTERN) { shDrawPatternMesh(fill, &min, &max, VG_FILL_PATH, GL_TEXTURE1); } glActiveTexture(GL_TEXTURE0); glDisable(GL_TEXTURE_2D); glDisable(GL_STENCIL_TEST); }else if (context->imageMode == VG_DRAW_IMAGE_STENCIL) { }else{/* Either normal mode or multiplying with a color-paint */ /* Setup blending */ updateBlendingStateGL(context, 0); /* Draw textured quad */ glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glVertex2i(0, 0); glVertex2i(i->width, 0); glVertex2i(i->width, i->height); glVertex2i(0, i->height); glEnd(); glDisable(GL_TEXTURE_2D); } glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glPopMatrix(); if (context->scissoring == VG_TRUE) glDisable( GL_SCISSOR_TEST ); VG_RETURN(VG_NO_RETVAL); }
VG_API_CALL void vgDrawPath(VGPath path, VGbitfield paintModes) { SHPath *p; SHMatrix3x3 mi; SHfloat mgl[16]; SHPaint *fill, *stroke; SHRectangle *rect; VG_GETCONTEXT(VG_NO_RETVAL); VG_RETURN_ERR_IF(!shIsValidPath(context, path), VG_BAD_HANDLE_ERROR, VG_NO_RETVAL); VG_RETURN_ERR_IF(paintModes & (~(VG_STROKE_PATH | VG_FILL_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL); /* Check whether scissoring is enabled and scissor rectangle is valid */ if (context->scissoring == VG_TRUE) { rect = &context->scissor.items[0]; if (context->scissor.size == 0) VG_RETURN( VG_NO_RETVAL ); if (rect->w <= 0.0f || rect->h <= 0.0f) VG_RETURN( VG_NO_RETVAL ); glScissor( (GLint)rect->x, (GLint)rect->y, (GLint)rect->w, (GLint)rect->h ); glEnable( GL_SCISSOR_TEST ); } p = (SHPath*)path; /* If user-to-surface matrix invertible tessellate in surface space for better path resolution */ if (shIsTessCacheValid( context, p ) == VG_FALSE) { if (shInvertMatrix(&context->pathTransform, &mi)) { shFlattenPath(p, 1); shTransformVertices(&mi, p); }else shFlattenPath(p, 0); shFindBoundbox(p); } /* TODO: Turn antialiasing on/off */ glDisable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH); glEnable(GL_MULTISAMPLE); /* Pick paint if available or default*/ fill = (context->fillPaint ? context->fillPaint : &context->defaultPaint); stroke = (context->strokePaint ? context->strokePaint : &context->defaultPaint); /* Apply transformation */ shMatrixToGL(&context->pathTransform, mgl); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixf(mgl); if (paintModes & VG_FILL_PATH) { /* Tesselate into stencil */ glEnable(GL_STENCIL_TEST); /* Clear the stencil buffer first */ glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawBoundBox(context, p, VG_FILL_PATH); glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawVertices(p, GL_TRIANGLE_FAN); /* Setup blending */ updateBlendingStateGL(context, fill->type == VG_PAINT_TYPE_COLOR && fill->color.a == 1.0f); /* Draw paint where stencil odd */ glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); shDrawPaintMesh(context, &p->min, &p->max, VG_FILL_PATH, GL_TEXTURE0); /* Reset state */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); } /* TODO: Turn antialiasing on/off */ glDisable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH); glEnable(GL_MULTISAMPLE); if ((paintModes & VG_STROKE_PATH) && context->strokeLineWidth > 0.0f) { if (1) {/*context->strokeLineWidth > 1.0f) {*/ if (shIsStrokeCacheValid( context, p ) == VG_FALSE) { /* Generate stroke triangles in user space */ shVector2ArrayClear(&p->stroke); shStrokePath(context, p); } /* Stroke into stencil */ glEnable(GL_STENCIL_TEST); /* Clear the stencil buffer first */ glStencilFunc(GL_ALWAYS, 0, 0); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawBoundBox(context, p, VG_STROKE_PATH); glStencilFunc(GL_NOTEQUAL, 1, 1); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); shDrawStroke(p); /* Setup blending */ updateBlendingStateGL(context, stroke->type == VG_PAINT_TYPE_COLOR && stroke->color.a == 1.0f); /* Draw paint where stencil odd */ glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); shDrawPaintMesh(context, &p->min, &p->max, VG_STROKE_PATH, GL_TEXTURE0); /* Reset state */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); }else{ /* Simulate thin stroke by alpha */ SHColor c = stroke->color; if (context->strokeLineWidth < 1.0f) c.a *= context->strokeLineWidth; /* Draw contour as a line */ glDisable(GL_MULTISAMPLE); glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4fv((GLfloat*)&c); shDrawVertices(p, GL_LINE_STRIP); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); } } glDisable(GL_MULTISAMPLE); glPopMatrix(); if (context->scissoring == VG_TRUE) glDisable( GL_SCISSOR_TEST ); VG_RETURN(VG_NO_RETVAL); }