void widget_list_onclick(widget *w) { if(!w)return; float height = 0.0f; sth_vmetrics(stash, w->fontface, w->fontsize, NULL,NULL,&height); int2 click; click.x = mouse_x - w->delta.x - w->pos.x; click.y = mouse_y - w->delta.y - w->pos.y; float fullheight = (float)w->count * height; float totalheight = (fullheight - (float)w->size.y) / fullheight; if(click.x < 0)return; if(click.x > w->size.x)return; if(click.y < 0)click.y = 0; if(click.y > w->size.y)click.y = w->size.y; if(click.x > (w->size.x - 20)) { w->clicked = 2; // scrollbar! } else { w->clicked = 1; // selection int i = (float)w->count * (w->percent * totalheight); int offset = (float)click.y / height; offset += i; if(offset > w->count)return; w->selected = offset; } }
void widget_list_click(widget *w) { if(!w)return; float height = 0.0f; sth_vmetrics(stash, w->fontface, w->fontsize, NULL,NULL,&height); int2 click; click.x = mouse_x - w->delta.x - w->pos.x; click.y = mouse_y - w->delta.y - w->pos.y; float fullheight = (float)w->count * height; float totalheight = (fullheight - (float)w->size.y) / fullheight; // if(click.x < 0)return; // if(click.x > w->size.x)return; // if(click.y < 0)click.y = 0; // if(click.y > w->size.y)click.y = w->size.y; if(2 == w->clicked) // scrollbar! { float scrollfactor = w->size.y / fullheight; float barheight = scrollfactor * w->size.y; float offset = w->percent; offset -= (float)mickey_y / (float)(w->size.y-barheight); if(offset < 0.0) offset = 0.0; if(offset > 1.0) offset = 1.0; w->percent = offset; } else { int i = (float)w->count * (w->percent * totalheight); int offset = (float)click.y / height; offset += i; if(offset > w->count)return; w->selected = offset; // char **file = w->data; // printf("this one %s\n", file[offset]); } }
int main(int argc, char *argv[]) { int done; SDL_Event event; int width, height; struct sth_stash* stash = 0; FILE* fp = 0; int datasize; unsigned char* data; float sx,sy,dx,dy,lh; int droidRegular, droidItalic, droidBold, droidJapanese, dejavu; SDL_Surface* surface; GLuint texture; if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); return -1; } // Init OpenGL SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); #ifdef STH_OPENGL3 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); #endif width = 800; height = 600; SDL_Window* window = SDL_CreateWindow("FontStash Demo", 100, 100, width, height, SDL_WINDOW_OPENGL); if (!window) { fprintf(stderr, "Could not initialise SDL opengl\n"); return -1; } SDL_GLContext context = SDL_GL_CreateContext(window); stash = sth_create(512,512); if (!stash) { fprintf(stderr, "Could not create stash.\n"); return -1; } // Load the first truetype font from memory (just because we can). fp = fopen("DroidSerif-Regular.ttf", "rb"); if (!fp) goto error_add_font; fseek(fp, 0, SEEK_END); datasize = (int)ftell(fp); fseek(fp, 0, SEEK_SET); data = (unsigned char*)malloc(datasize); if (data == NULL) goto error_add_font; fread(data, 1, datasize, fp); fclose(fp); fp = 0; if (!(droidRegular = sth_add_font_from_memory(stash, data))) goto error_add_font; // Load the remaining truetype fonts directly. if (!(droidItalic = sth_add_font(stash,"DroidSerif-Italic.ttf"))) goto error_add_font; if (!(droidBold = sth_add_font(stash,"DroidSerif-Bold.ttf"))) goto error_add_font; if (!(droidJapanese = sth_add_font(stash,"DroidSansJapanese.ttf"))) goto error_add_font; // Load a bitmap font surface = IMG_Load("dejavu-sans_0.png"); if (surface == NULL) { fprintf(stderr, "%s.\n", IMG_GetError()); return -1; } glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, surface->w, surface->h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, surface->pixels); if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); SDL_FreeSurface(surface); dejavu = sth_add_bitmap_font(stash, 17, -4, 2); sth_add_glyph_for_char(stash, dejavu, texture, "T", 18, 14, 363, 331, 10, 11, 0, 3, 10); sth_add_glyph_for_char(stash, dejavu, texture, "h", 18, 14, 225, 382, 8, 11, 1, 3, 10); sth_add_glyph_for_char(stash, dejavu, texture, "i", 18, 14, 478, 377, 2, 11, 1, 3, 4); sth_add_glyph_for_char(stash, dejavu, texture, "s", 18, 14, 199, 455, 7, 8, 1, 6, 9); sth_add_glyph_for_char(stash, dejavu, texture, " ", 18, 14, 66, 185, 1, 1, 0, 14, 5); sth_add_glyph_for_char(stash, dejavu, texture, "a", 18, 14, 18, 459, 8, 8, 1, 6, 10); sth_add_glyph_for_char(stash, dejavu, texture, "b", 18, 14, 198, 383, 8, 11, 1, 3, 10); sth_add_glyph_for_char(stash, dejavu, texture, "t", 18, 14, 436, 377, 5, 11, 1, 3, 6); sth_add_glyph_for_char(stash, dejavu, texture, "m", 18, 14, 494, 429, 12, 8, 2, 6, 16); sth_add_glyph_for_char(stash, dejavu, texture, "p", 18, 14, 436, 353, 8, 11, 1, 6, 10); sth_add_glyph_for_char(stash, dejavu, texture, "f", 18, 14, 442, 377, 5, 11, 1, 3, 7); sth_add_glyph_for_char(stash, dejavu, texture, "o", 18, 14, 483, 438, 8, 8, 1, 6, 10); sth_add_glyph_for_char(stash, dejavu, texture, "n", 18, 14, 0, 459, 8, 8, 1, 6, 10); sth_add_glyph_for_char(stash, dejavu, texture, ".", 18, 14, 285, 476, 2, 3, 1, 11, 6); done = 0; while (!done) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_MOUSEMOTION: break; case SDL_MOUSEBUTTONDOWN: break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) done = 1; break; case SDL_QUIT: done = 1; break; default: break; } } // Update and render glViewport(0, 0, width, height); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.3f, 0.3f, 0.32f, 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); #ifdef STH_OPENGL3 std::cout << "OpenGL3" << std::endl; glm::mat4 proj = glm::ortho(0.0f, (GLfloat) width, 0.0f, (GLfloat) height, -1.0f, 1.0f); sth_projection_matrix(stash, glm::value_ptr(proj)); sth_color(stash, 1.0f, 0.0f, 0.0f, 1.0f); #else std::cout << "Immediate OpenGL" << std::endl; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,width,0,height,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor4ub(255,255,255,255); #endif sx = 100; sy = 250; sth_begin_draw(stash); dx = sx; dy = sy; sth_draw_text(stash, droidRegular, 24.0f, dx, dy, "The quick ", &dx); sth_draw_text(stash, droidItalic, 48.0f, dx, dy, "brown ", &dx); sth_draw_text(stash, droidRegular, 24.0f, dx, dy, "fox ", &dx); sth_vmetrics(stash, droidItalic, 24, NULL, NULL, &lh); dx = sx; dy -= lh*1.2f; sth_draw_text(stash, droidItalic, 24.0f, dx, dy, "jumps over ", &dx); sth_draw_text(stash, droidBold, 24.0f, dx, dy, "the lazy ", &dx); sth_draw_text(stash, droidRegular, 24.0f, dx, dy, "dog.", &dx); dx = sx; dy -= lh*1.2f; sth_draw_text(stash, droidRegular, 12.0f, dx, dy, "Now is the time for all good men to come to the aid of the party.", &dx); sth_vmetrics(stash, droidItalic, 12, NULL, NULL, &lh); dx = sx; dy -= lh*1.2f*2; sth_draw_text(stash, droidItalic, 18.0f, dx, dy, "Ég get etið gler án þess að meiða mig.", &dx); sth_vmetrics(stash, droidItalic, 18, NULL, NULL, &lh); dx = sx; dy -= lh*1.2f; sth_draw_text(stash, droidJapanese, 18.0f, dx, dy, "私はガラスを食べられます。それは私を傷つけません。", &dx); dx = sx; dy -= lh*1.2f*2; sth_draw_text(stash, dejavu, 18.0f, dx, dy, "This is a bitmap font.", &dx); sth_end_draw(stash); SDL_GL_SwapWindow(window); } sth_delete(stash); free(data); SDL_GL_DeleteContext(context); SDL_Quit(); return 0; error_add_font: fprintf(stderr, "Could not add font.\n"); return -1; }
void widget_list_draw(widget *w) { if(!w)return; float height = 0.0f; float fascend=0, fdescend=0; sth_vmetrics(stash, w->fontface, w->fontsize, &fascend, &fdescend, &height); float hoff = -fascend; float fullheight = (float)w->count * height; float totalheight = (fullheight - (float)w->size.y) / fullheight; int y = 0; char **names = (char**)w->data; widget_rect_draw(w); glEnable(GL_SCISSOR_TEST); glScissor(w->drawpos.x, vid_height - w->drawpos.y - w->size.y, w->size.x, w->size.y); glColor4f(1,1,1,1); sth_begin_draw(stash); if( fullheight < w->size.y ) { // scrollbar not needed for(int i=0; i<w->count; i++) { if(i == w->selected) { glTranslatef(0, y, 0); glColor4f(1,1,1,0.2); draw_rect(w->size.x, height); glTranslatef(0, -y, 0); } glColor4f(1,1,1,1); sth_draw_text(stash, w->fontface, w->fontsize, 10, y+hoff, names[i], 0); y -= height; } sth_end_draw(stash); } else { float smooth = (float)w->count * (w->percent * totalheight); double mtmp = 0; int ysmooth = modf(smooth, &mtmp) * height; int i = smooth; for(; i<w->count; i++) { if(i == w->selected) { glTranslatef(0, y+ysmooth, 0); glColor4f(1,1,1,0.2); draw_rect(w->size.x-20, height); glTranslatef(0, -(y+ysmooth), 0); } glColor4f(1,1,1,1); sth_draw_text(stash, w->fontface, w->fontsize, 10, y+hoff+ysmooth, names[i], 0); y -= height; if( -y > w->size.y) break; } sth_end_draw(stash); glColor4f(0,0,0,0.5); glTranslatef(w->size.x - 20, 0, 0); draw_rect(20, w->size.y); glColor4f(1,1,1,0.9); float scrollfactor = w->size.y / fullheight; float barheight = scrollfactor * w->size.y; glTranslatef(0, -w->percent*(float)(w->size.y-barheight), 0); draw_rect(20, barheight); glTranslatef(0, w->percent*(float)(w->size.y-barheight), 0); glTranslatef(-w->size.x + 20, 0, 0); } glDisable(GL_SCISSOR_TEST); }