static void shDrawPaintMesh(VGContext *c, SHVector2 *min, SHVector2 *max, VGPaintMode mode, GLenum texUnit) { SHPaint *p; SHVector2 pmin, pmax; SHfloat K = 1.0f; /* Pick the right paint */ if (mode == VG_FILL_PATH) { p = (c->fillPaint ? c->fillPaint : &c->defaultPaint); }else if (mode == VG_STROKE_PATH) { p = (c->strokePaint ? c->strokePaint : &c->defaultPaint); K = SH_CEIL(c->strokeMiterLimit * c->strokeLineWidth) + 1.0f; } /* We want to be sure to cover every pixel of this path so better take a pixel more than leave some out (multisampling is tricky). */ SET2V(pmin, (*min)); SUB2(pmin, K,K); SET2V(pmax, (*max)); ADD2(pmax, K,K); /* Construct appropriate OpenGL primitives so as to fill the stencil mask with select paint */ switch (p->type) { case VG_PAINT_TYPE_LINEAR_GRADIENT: shDrawLinearGradientMesh(p, min, max, mode, texUnit); break; case VG_PAINT_TYPE_RADIAL_GRADIENT: shDrawRadialGradientMesh(p, min, max, mode, texUnit); break; case VG_PAINT_TYPE_PATTERN: if (p->pattern != VG_INVALID_HANDLE) { shDrawPatternMesh(p, min, max, mode, texUnit); break; }/* else behave as a color paint */ case VG_PAINT_TYPE_COLOR: glColor4fv((GLfloat*)&p->color); glBegin(GL_QUADS); glVertex2f(pmin.x, pmin.y); glVertex2f(pmax.x, pmin.y); glVertex2f(pmax.x, pmax.y); glVertex2f(pmin.x, pmax.y); glEnd(); break; } }
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); }
static void shDrawPaintMesh(VGContext *c, SHVector2 *min, SHVector2 *max, VGPaintMode mode, GLenum texUnit) { SHPaint *p; SHVector2 pmin, pmax; SHfloat K = 1.0f; #ifdef ANDROIDVG SHColor *color; GLfloat v[6][2]; #endif /* Pick the right paint */ if (mode == VG_FILL_PATH) { p = (c->fillPaint ? c->fillPaint : &c->defaultPaint); }else if (mode == VG_STROKE_PATH) { p = (c->strokePaint ? c->strokePaint : &c->defaultPaint); K = SH_CEIL(c->strokeMiterLimit * c->strokeLineWidth) + 1.0f; } /* We want to be sure to cover every pixel of this path so better take a pixel more than leave some out (multisampling is tricky). */ SET2V(pmin, (*min)); SUB2(pmin, K,K); SET2V(pmax, (*max)); ADD2(pmax, K,K); /* Construct appropriate OpenGL primitives so as to fill the stencil mask with select paint */ switch (p->type) { case VG_PAINT_TYPE_LINEAR_GRADIENT: shDrawLinearGradientMesh(p, min, max, mode, texUnit); break; case VG_PAINT_TYPE_RADIAL_GRADIENT: shDrawRadialGradientMesh(p, min, max, mode, texUnit); break; case VG_PAINT_TYPE_PATTERN: if (p->pattern != VG_INVALID_HANDLE) { shDrawPatternMesh(p, min, max, mode, texUnit); break; }/* else behave as a color paint */ case VG_PAINT_TYPE_COLOR: #ifdef ANDROIDVG v[0][0] = pmin.x; v[0][1] = pmin.y; v[1][0] = pmax.x; v[1][1] = pmin.y; v[2][0] = pmax.x; v[2][1] = pmax.y; v[3][0] = pmin.x; v[3][1] = pmin.y; v[4][0] = pmax.x; v[4][1] = pmax.y; v[5][0] = pmin.x; v[5][1] = pmax.y; color = &p->color; glColor4f(color->r, color->g, color->b, color->a); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, v); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableClientState(GL_VERTEX_ARRAY); #else glColor4fv((GLfloat*)&p->color); glBegin(GL_QUADS); glVertex2f(pmin.x, pmin.y); glVertex2f(pmax.x, pmin.y); glVertex2f(pmax.x, pmax.y); glVertex2f(pmin.x, pmax.y); glEnd(); #endif break; } }