/************************************************************************* * Copyright (c) 2011 AT&T Intellectual Property * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v10.html * * Contributors: Details at https://graphviz.org *************************************************************************/ #include #include #include #include #include #include #include static glCompTex *glCompSetAddNewTexture(glCompSet *s, int width, int height, const unsigned char *data, bool is2D) { int offset, ind; unsigned char *tarData; if (!data) return NULL; glCompTex *t = gv_alloc(sizeof(glCompTex)); if (!is2D) { /*use opengl texture */ glEnable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &t->id); //get next id if (glGetError() != GL_NO_ERROR) { /*for some opengl based error , texture couldnt be created */ /* drain the OpenGL error queue */ while (glGetError() != GL_NO_ERROR); free(t); return NULL; } else { glBindTexture(GL_TEXTURE_2D, t->id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glDisable(GL_TEXTURE_2D); } } if (is2D) { assert(width >= 0); assert(height >= 0); t->data = gv_calloc(4 * (unsigned)width * (unsigned)height, sizeof(unsigned char)); offset = 4; //RGBA mod,TO DO implement other modes /*data upside down because of pango gl coord system */ for (ind = 0; ind < height; ind++) { const unsigned char *srcData = data + (height - 1 - ind) * offset * width; tarData = t->data + ind * offset * width; memcpy(tarData, srcData, 4 * (unsigned)width); } } t->userCount = 1; t->width = width; t->height = height; if(s) { s->textures = gv_recalloc(s->textures, s->textureCount, s->textureCount + 1, sizeof(glCompTex *)); s->textureCount++; s->textures[s->textureCount - 1] = t; } return t; } glCompTex *glCompSetAddNewTexImage(glCompSet *s, int width, int height, const unsigned char *data, bool is2D) { glCompTex *t; if (!data) return NULL; t = glCompSetAddNewTexture(s, width, height, data, is2D); if (!t) return NULL; t->type = glTexImage; return t; } glCompTex *glCompSetAddNewTexLabel(glCompSet *s, char *def, int fs, char *text, bool is2D) { int width, height; glCompTex *t; cairo_surface_t *surface = NULL; unsigned char *data = NULL; if (!def) return NULL; /*first check if the same label with same font def created before if it was , return its id */ for (size_t ind = 0; ind < s->textureCount; ind++) { if (s->textures[ind]->type == glTexLabel) { if (streq(def, s->textures[ind]->def) && s->textures[ind]->type == glTexLabel && streq(text, s->textures[ind]->text) && s->textures[ind]->fontSize==fs) { s->textures[ind]->userCount++; return s->textures[ind]; } } } data = glCompCreatePangoTexture(def, fs, text, &surface, &width, &height); if (!data) /*pango error , */ return NULL; t = glCompSetAddNewTexture(s, width, height, data, is2D); cairo_surface_destroy(surface); if (!t) { free(data); return NULL; } t->def = gv_strdup(def); t->text = gv_strdup(text); t->type = glTexLabel; return t; } void glCompDeleteTexture(glCompTex * t) { if (!t) return; t->userCount--; if (!t->userCount) { free(t->data); free(t->def); free(t->text); free(t); } }