static void glw_quad_render(glw_t *w, const glw_rctx_t *rc) { glw_quad_t *q = (glw_quad_t *)w; if(q->recompile) { glw_destroy_program(w->glw_root, q->prog); q->prog = glw_make_program(w->glw_root, NULL, rstr_get(q->fs)); q->recompile = 0; } if(!glw_renderer_initialized(&q->r)) { glw_renderer_init_quad(&q->r); glw_renderer_vtx_pos(&q->r, 0, -1, -1, 0); glw_renderer_vtx_pos(&q->r, 1, 1, -1, 0); glw_renderer_vtx_pos(&q->r, 2, 1, 1, 0); glw_renderer_vtx_pos(&q->r, 3, -1, 1, 0); } glw_renderer_draw(&q->r, w->glw_root, rc, NULL, &q->color, NULL, rc->rc_alpha * w->glw_alpha, 0, q->prog); }
static void glw_flicker_layout(glw_t *W, const glw_rctx_t *rc) { glw_flicker_t *gf = (void *)W; int i; if(!gf->gf_gr_initialized) { glw_renderer_init_quad(&gf->gf_gr[0]); glw_renderer_init_quad(&gf->gf_gr[1]); for(i = 0; i < 2; i++) { glw_renderer_vtx_pos(&gf->gf_gr[i], 0, i+-1.0, -1.0, 0.0); glw_renderer_vtx_pos(&gf->gf_gr[i], 1, i+ 0.0, -1.0, 0.0); glw_renderer_vtx_pos(&gf->gf_gr[i], 2, i+ 0.0, 1.0, 0.0); glw_renderer_vtx_pos(&gf->gf_gr[i], 3, i+-1.0, 1.0, 0.0); } } gf->gf_phase = !gf->gf_phase; }
static void glw_bar_layout(glw_t *w, const glw_rctx_t *rc) { glw_bar_t *gb = (void *)w; float r, g, b, x; if(w->glw_alpha < GLW_ALPHA_EPSILON) return; if(!glw_renderer_initialized(&gb->gb_gr)) { glw_renderer_init_quad(&gb->gb_gr); gb->gb_update = 1; } if(gb->gb_update) { gb->gb_update = 0; r = GLW_LERP(gb->gb_fill, gb->gb_col1[0], gb->gb_col2[0]); g = GLW_LERP(gb->gb_fill, gb->gb_col1[1], gb->gb_col2[1]); b = GLW_LERP(gb->gb_fill, gb->gb_col1[2], gb->gb_col2[2]); x = GLW_LERP(gb->gb_fill, -1, 1); glw_renderer_vtx_pos(&gb->gb_gr, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_col(&gb->gb_gr, 0, gb->gb_col1[0], gb->gb_col1[1], gb->gb_col1[2], 1.0); glw_renderer_vtx_pos(&gb->gb_gr, 1, x, -1.0, 0.0); glw_renderer_vtx_col(&gb->gb_gr, 1, r, g, b, 1.0); glw_renderer_vtx_pos(&gb->gb_gr, 2, x, 1.0, 0.0); glw_renderer_vtx_col(&gb->gb_gr, 2, r, g, b, 1.0); glw_renderer_vtx_pos(&gb->gb_gr, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_col(&gb->gb_gr, 3, gb->gb_col1[0], gb->gb_col1[1], gb->gb_col1[2], 1.0); glw_need_refresh(w->glw_root, 0); } }
static void glw_raster_render(glw_t *w, const glw_rctx_t *rc) { glw_raster_t *q = (void *)w; #if 0 printf("RASTER W=%d H=%d\n", rc->rc_width, rc->rc_height); int i; for(i = 0; i < 16; i++) { printf("%f%c", rc->rc_be.gbr_mtx[i], "\t\t\t\n"[i&3]); } #endif if(!glw_is_tex_inited(&q->tex)) glw_tex_upload(w->glw_root, &q->tex, rastermap, GLW_TEXTURE_FORMAT_RGB, RASTER_TILE_SIZE, RASTER_TILE_SIZE, GLW_TEX_REPEAT); if(!glw_renderer_initialized(&q->r)) glw_renderer_init_quad(&q->r); if(q->width != rc->rc_width || q->height != rc->rc_height) { q->width = rc->rc_width; q->height = rc->rc_height; glw_renderer_vtx_pos(&q->r, 0, -1, -1, 0); glw_renderer_vtx_st (&q->r, 0, 0, rc->rc_height / (float)RASTER_TILE_SIZE); glw_renderer_vtx_pos(&q->r, 1, 1, -1, 0); glw_renderer_vtx_st (&q->r, 1, rc->rc_width / (float)RASTER_TILE_SIZE, rc->rc_height / (float)RASTER_TILE_SIZE); glw_renderer_vtx_pos(&q->r, 2, 1, 1, 0); glw_renderer_vtx_st (&q->r, 2, rc->rc_width / (float)RASTER_TILE_SIZE, 0); glw_renderer_vtx_pos(&q->r, 3, -1, 1, 0); glw_renderer_vtx_st (&q->r, 3, 0, 0); } glw_renderer_draw(&q->r, w->glw_root, rc, &q->tex, &q->color, NULL, rc->rc_alpha * w->glw_alpha, 0, NULL); }
static void glw_throbber_render(glw_t *w, const glw_rctx_t *rc) { glw_throbber_t *gt = (glw_throbber_t *)w; glw_rctx_t rc0, rc1; int i; glw_root_t *gr = w->glw_root; float a0 = w->glw_alpha * rc->rc_alpha; int spokes = 16; if(a0 < 0.01) return; if(!glw_renderer_initialized(>->renderer)) { glw_renderer_init_quad(>->renderer); glw_renderer_vtx_pos(>->renderer, 0, -0.05, 0.4, 0); glw_renderer_vtx_pos(>->renderer, 1, 0.05, 0.4, 0); glw_renderer_vtx_pos(>->renderer, 2, 0.05, 1, 0); glw_renderer_vtx_pos(>->renderer, 3, -0.05, 1, 0); } rc0 = *rc; glw_scale_to_aspect(&rc0, 1.0); for(i = 0; i < spokes; i++) { float a = i * 360.0 / 16; float alpha = 1 - (((i + (gt->o / 6)) % spokes) / 16.0); alpha = MAX(alpha, 0.1); rc1 = rc0; glw_Rotatef(&rc1, -gt->angle - a, 0, 0, -1); glw_renderer_draw(>->renderer, gr, &rc1, NULL, >->color, NULL, a0 * alpha, 0, NULL); } }
static void glw_text_bitmap_layout(glw_t *w, const glw_rctx_t *rc) { glw_text_bitmap_t *gtb = (void *)w; glw_root_t *gr = w->glw_root; gr->gr_can_externalize = 0; // Initialize renderers if(unlikely(!glw_renderer_initialized(>b->gtb_text_renderer))) glw_renderer_init_quad(>b->gtb_text_renderer); if(w->glw_class == &glw_text && unlikely(!glw_renderer_initialized(>b->gtb_cursor_renderer))) glw_renderer_init_quad(>b->gtb_cursor_renderer); if(gtb->gtb_background_alpha > GLW_ALPHA_EPSILON && unlikely(!glw_renderer_initialized(>b->gtb_cursor_renderer))) { glw_renderer_init_quad(>b->gtb_background_renderer); glw_renderer_vtx_pos(>b->gtb_background_renderer, 0, -1, -1, 0); glw_renderer_vtx_pos(>b->gtb_background_renderer, 1, 1, -1, 0); glw_renderer_vtx_pos(>b->gtb_background_renderer, 2, 1, 1, 0); glw_renderer_vtx_pos(>b->gtb_background_renderer, 3, -1, 1, 0); } // Upload texture image_component_t *ic = image_find_component(gtb->gtb_image, IMAGE_PIXMAP); if(ic != NULL) { glw_tex_upload(gr, >b->gtb_texture, ic->pm, 0); gtb->gtb_margin = ic->pm->pm_margin; image_clear_component(ic); gtb->gtb_need_layout = 1; } const int tex_width = glw_tex_width(>b->gtb_texture); const int tex_height = glw_tex_height(>b->gtb_texture); ic = image_find_component(gtb->gtb_image, IMAGE_TEXT_INFO); image_component_text_info_t *ti = ic ? &ic->text_info : NULL; // Check if we need to repaint if(gtb->gtb_saved_width != rc->rc_width || gtb->gtb_saved_height != rc->rc_height) { if(ti != NULL && gtb->gtb_state == GTB_VALID) { if(ti->ti_flags & IMAGE_TEXT_WRAPPED) gtb->gtb_state = GTB_NEED_RENDER; if(rc->rc_width > gtb->gtb_saved_width && ti->ti_flags & IMAGE_TEXT_TRUNCATED) gtb->gtb_state = GTB_NEED_RENDER; if(gtb->gtb_flags & GTB_ELLIPSIZE) { if(ti->ti_flags & IMAGE_TEXT_TRUNCATED) { gtb->gtb_state = GTB_NEED_RENDER; } else { if(rc->rc_width - gtb->gtb_padding[2] - gtb->gtb_padding[0] < tex_width - gtb->gtb_margin * 2) gtb->gtb_state = GTB_NEED_RENDER; if(rc->rc_height - gtb->gtb_padding[1] - gtb->gtb_padding[3] < tex_height - gtb->gtb_margin * 2) gtb->gtb_state = GTB_NEED_RENDER; } } } gtb->gtb_saved_width = rc->rc_width; gtb->gtb_saved_height = rc->rc_height; gtb->gtb_update_cursor = 1; gtb->gtb_need_layout = 1; if(gtb->w.glw_flags2 & GLW2_DEBUG) printf(" textbitmap: Parent widget gives us :%d x %d ti=%p\n", rc->rc_width, rc->rc_height, ti); } if(ti != NULL && gtb->gtb_need_layout) { const int margin = gtb->gtb_margin; int left = gtb->gtb_padding[0] - margin; int top = rc->rc_height - gtb->gtb_padding[1] + margin; int right = rc->rc_width - gtb->gtb_padding[2] + margin; int bottom = gtb->gtb_padding[3] - margin; int text_width = tex_width; int text_height = tex_height; float x1, y1, x2, y2; if(gtb->w.glw_flags2 & GLW2_DEBUG) printf(" textbitmap: text_width:%d left:%d right:%d margin:%d\n", text_width, left, right, margin); // Vertical if(text_height > top - bottom) { // Oversized, must cut text_height = top - bottom; } else { switch(w->glw_alignment) { case LAYOUT_ALIGN_CENTER: case LAYOUT_ALIGN_LEFT: case LAYOUT_ALIGN_RIGHT: bottom = (bottom + top - text_height) / 2; top = bottom + text_height; break; case LAYOUT_ALIGN_TOP_LEFT: case LAYOUT_ALIGN_TOP_RIGHT: case LAYOUT_ALIGN_TOP: case LAYOUT_ALIGN_JUSTIFIED: bottom = top - tex_height; break; case LAYOUT_ALIGN_BOTTOM: case LAYOUT_ALIGN_BOTTOM_LEFT: case LAYOUT_ALIGN_BOTTOM_RIGHT: top = bottom + tex_height; break; } } y1 = -1.0f + 2.0f * bottom / (float)rc->rc_height; y2 = -1.0f + 2.0f * top / (float)rc->rc_height; // Horizontal if(text_width > right - left || ti->ti_flags & IMAGE_TEXT_TRUNCATED) { // Oversized, must cut text_width = right - left; if(gtb->w.glw_flags2 & GLW2_DEBUG) printf(" textbitmap: Oversized, must cut. Width is now %d\n", text_width); #if 0 if(!(gtb->gtb_flags & GTB_ELLIPSIZE)) { glw_renderer_vtx_col(>b->gtb_text_renderer, 0, 1,1,1,1+text_width/20); glw_renderer_vtx_col(>b->gtb_text_renderer, 1, 1,1,1,0); glw_renderer_vtx_col(>b->gtb_text_renderer, 2, 1,1,1,0); glw_renderer_vtx_col(>b->gtb_text_renderer, 3, 1,1,1,1+text_width/20); } #endif } else { glw_renderer_vtx_col_reset(>b->gtb_text_renderer); switch(w->glw_alignment) { case LAYOUT_ALIGN_JUSTIFIED: case LAYOUT_ALIGN_CENTER: case LAYOUT_ALIGN_BOTTOM: case LAYOUT_ALIGN_TOP: left = (left + right - text_width) / 2; right = left + text_width; break; case LAYOUT_ALIGN_LEFT: case LAYOUT_ALIGN_TOP_LEFT: case LAYOUT_ALIGN_BOTTOM_LEFT: right = left + tex_width; break; case LAYOUT_ALIGN_RIGHT: case LAYOUT_ALIGN_TOP_RIGHT: case LAYOUT_ALIGN_BOTTOM_RIGHT: left = right - tex_width; break; } } x1 = -1.0f + 2.0f * left / (float)rc->rc_width; x2 = -1.0f + 2.0f * right / (float)rc->rc_width; const float s = text_width / (float)tex_width; const float t = text_height / (float)tex_height; if(gtb->w.glw_flags2 & GLW2_DEBUG) printf(" s=%f t=%f\n", s, t); glw_renderer_vtx_pos(>b->gtb_text_renderer, 0, x1, y1, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 0, 0, t); glw_renderer_vtx_pos(>b->gtb_text_renderer, 1, x2, y1, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 1, s, t); glw_renderer_vtx_pos(>b->gtb_text_renderer, 2, x2, y2, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 2, s, 0); glw_renderer_vtx_pos(>b->gtb_text_renderer, 3, x1, y2, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 3, 0, 0); } if(w->glw_class == &glw_text && gtb->gtb_update_cursor && gtb->gtb_state == GTB_VALID) { int i = gtb->gtb_edit_ptr; int left; float x1, y1, x2, y2; if(ti != NULL && ti->ti_charpos != NULL) { if(i < ti->ti_charposlen) { left = ti->ti_charpos[i*2 ]; } else { left = ti->ti_charpos[2 * ti->ti_charposlen - 1]; } } else { left = 0; } left += gtb->gtb_padding[0]; x1 = -1.0f + 2.0f * (left - 1) / (float)rc->rc_width; x2 = -1.0f + 2.0f * (left ) / (float)rc->rc_width; y1 = -1.0f + 2.0f * gtb->gtb_padding[3] / (float)rc->rc_height; y2 = 1.0f - 2.0f * gtb->gtb_padding[1] / (float)rc->rc_height; glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 0, x1, y1, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 1, x2, y1, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 2, x2, y2, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 3, x1, y2, 0.0); if(w->glw_flags2 & GLW2_DEBUG) { printf("Cursor updated %f %f %f %f rect:%d,%d\n", x1, y1, x2, y2, rc->rc_width, rc->rc_height); } gtb->gtb_update_cursor = 0; } gtb->gtb_paint_cursor = gtb->gtb_flags & GTB_PERMANENT_CURSOR || (w->glw_class == &glw_text && glw_is_focused(w)); if(gtb->gtb_paint_cursor && rc->rc_alpha > GLW_ALPHA_EPSILON) glw_need_refresh(gr, 0); gtb->gtb_need_layout = 0; if(gtb->gtb_state == GTB_VALID && gtb->gtb_deferred_realize) { gtb->gtb_deferred_realize = 0; gtb_realize(gtb); } if(gtb->gtb_state != GTB_NEED_RENDER) return; TAILQ_INSERT_TAIL(&gr->gr_gtb_render_queue, gtb, gtb_workq_link); gtb->gtb_state = GTB_QUEUED_FOR_RENDERING; hts_cond_signal(&gr->gr_gtb_work_cond); }
static void glw_bloom_layout(glw_t *w, glw_rctx_t *rc) { glw_bloom_t *b = (void *)w; glw_root_t *gr = w->glw_root; glw_rctx_t rc0; glw_t *c; int x, y, i, sizx, sizy; TAILQ_FOREACH(c, &w->glw_childs, glw_parent_link) glw_layout0(c, rc); if(b->b_glow < 0.01) { if(b->b_width || b->b_height) bloom_destroy_rtt(gr, b); return; } sizx = rc->rc_width + EDGE_SIZE; sizy = rc->rc_height + EDGE_SIZE; if(b->b_width != sizx || b->b_height != sizy) { if(b->b_width || b->b_height) bloom_destroy_rtt(gr, b); b->b_width = sizx; b->b_height = sizy; if(b->b_width || b->b_height) { for(i = 0; i < BLOOM_COUNT; i++) { x = b->b_width / (2 << i); y = b->b_height / (2 << i); glw_rtt_init(gr, &b->b_rtt[i], x, y, 1); } } } // Initialize output texture if(!b->b_render_initialized) { float xs = gr->gr_normalized_texture_coords ? 1.0 : b->b_width; float ys = gr->gr_normalized_texture_coords ? 1.0 : b->b_height; glw_renderer_init_quad(&b->b_render); glw_renderer_vtx_pos(&b->b_render, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_st (&b->b_render, 0, 0.0, 0); glw_renderer_vtx_pos(&b->b_render, 1, 1.0, -1.0, 0.0); glw_renderer_vtx_st (&b->b_render, 1, xs, 0); glw_renderer_vtx_pos(&b->b_render, 2, 1.0, 1.0, 0.0); glw_renderer_vtx_st (&b->b_render, 2, xs, ys); glw_renderer_vtx_pos(&b->b_render, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_st (&b->b_render, 3, 0.0, ys); } memset(&rc0, 0, sizeof(glw_rctx_t)); rc0.rc_alpha = 1; rc0.rc_width = b->b_width - EDGE_SIZE; rc0.rc_height = b->b_height - EDGE_SIZE; rc0.rc_inhibit_shadows = 1; if(!b->b_need_render) return; for(i = 0; i < BLOOM_COUNT; i++) { glw_rtt_enter(gr, &b->b_rtt[i], &rc0); rc0.rc_width = b->b_width - EDGE_SIZE; rc0.rc_height = b->b_height - EDGE_SIZE; glw_Scalef(&rc0, 1.0 - EDGE_SIZE / b->b_width, 1.0 - EDGE_SIZE / b->b_height, 1.0); TAILQ_FOREACH(c, &w->glw_childs, glw_parent_link) glw_render0(c, &rc0); glw_rtt_restore(gr, &b->b_rtt[i]); } }
static void glw_gradient_layout(glw_t *W, glw_rctx_t *rc) { glw_gradient_t *gg = (void *)W; glw_root_t *gr = W->glw_root; int w, h, i, tiles; w = rc->rc_width; h = rc->rc_height; tiles = gg->gg_image_flags & (GLW_IMAGE_BEVEL_LEFT | GLW_IMAGE_BEVEL_RIGHT) ? 3 : 1; for(i = gg->gg_tiles; i < tiles; i++) { glw_renderer_init_quad(&gg->gg_gr[i]); gg->gg_gr_initialized = tiles; } if(gg->gg_width != w || gg->gg_height != h || gg->gg_tiles != tiles) { gg->gg_width = w; gg->gg_height = h; gg->gg_tiles = tiles; gg->gg_height2 = glw_can_tnpo2(gr) ? h : 1 << (av_log2(h)); float xs = gr->gr_normalized_texture_coords ? 1.0 : TILEWIDTH; float ys = gr->gr_normalized_texture_coords ? 1.0 : gg->gg_height2; glw_renderer_t *r; if(tiles == 1) { r = &gg->gg_gr[0]; float u = xs * rc->rc_width / TILEWIDTH; glw_renderer_vtx_pos(r, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_st (r, 0, 0.0, ys); glw_renderer_vtx_pos(r, 1, 1.0, -1.0, 0.0); glw_renderer_vtx_st (r, 1, u, ys); glw_renderer_vtx_pos(r, 2, 1.0, 1.0, 0.0); glw_renderer_vtx_st (r, 2, u, 0.0); glw_renderer_vtx_pos(r, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_st (r, 3, 0.0, 0.0); } else { r = &gg->gg_gr[0]; float u = xs * (rc->rc_width - TILEWIDTH * 2) / TILEWIDTH; float x1 = -1.0 + 2.0 * TILEWIDTH / gg->gg_width; float x2 = -1.0 + 2.0 * (gg->gg_width - TILEWIDTH) / gg->gg_width; glw_renderer_vtx_pos(r, 0, x1, -1.0, 0.0); glw_renderer_vtx_st (r, 0, 0.0, ys); glw_renderer_vtx_pos(r, 1, x2, -1.0, 0.0); glw_renderer_vtx_st (r, 1, u, ys); glw_renderer_vtx_pos(r, 2, x2, 1.0, 0.0); glw_renderer_vtx_st (r, 2, u, 0.0); glw_renderer_vtx_pos(r, 3, x1, 1.0, 0.0); glw_renderer_vtx_st (r, 3, 0.0, 0.0); r = &gg->gg_gr[1]; glw_renderer_vtx_pos(r, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_st (r, 0, 0.0, ys); glw_renderer_vtx_pos(r, 1, x1, -1.0, 0.0); glw_renderer_vtx_st (r, 1, xs, ys); glw_renderer_vtx_pos(r, 2, x1, 1.0, 0.0); glw_renderer_vtx_st (r, 2, xs, 0.0); glw_renderer_vtx_pos(r, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_st (r, 3, 0.0, 0.0); r = &gg->gg_gr[2]; glw_renderer_vtx_pos(r, 0, x2, -1.0, 0.0); glw_renderer_vtx_st (r, 0, 0.0, ys); glw_renderer_vtx_pos(r, 1, 1.0, -1.0, 0.0); glw_renderer_vtx_st (r, 1, xs, ys); glw_renderer_vtx_pos(r, 2, 1.0, 1.0, 0.0); glw_renderer_vtx_st (r, 2, xs, 0.0); glw_renderer_vtx_pos(r, 3, x2, 1.0, 0.0); glw_renderer_vtx_st (r, 3, 0.0, 0.0); } gg->gg_repaint = 1; } if(gg->gg_repaint) { gg->gg_repaint = 0; repaint(gg, gr, i, TILEWIDTH, gg->gg_height2, gg->gg_tiles); } }
static void glw_image_layout(glw_t *w, glw_rctx_t *rc) { glw_image_t *gi = (void *)w; glw_root_t *gr = w->glw_root; glw_loadable_texture_t *glt; glw_rctx_t rc0; glw_t *c; int hq = (w->glw_class == &glw_icon || w->glw_class == &glw_image); if(gi->gi_pending_url != NULL) { // Request to load int xs = -1, ys = -1; int flags = 0; gi->gi_loading_new_url = 1; if(gi->gi_pending != NULL) { glw_tex_deref(w->glw_root, gi->gi_pending); gi->gi_pending = NULL; } if(rstr_get(gi->gi_pending_url)[0] == 0) { // Empty string, unload all if(gi->gi_current != NULL) { glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = NULL; } gi->gi_update = 1; } else { if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; if(hq) { if(rc->rc_width < rc->rc_height) { xs = rc->rc_width; } else { ys = rc->rc_height; } } if(xs && ys) { if(w->glw_flags & GLW_DEBUG) TRACE(TRACE_DEBUG, "IMG", "Loading texture: %s", rstr_get(gi->gi_pending_url)); gi->gi_pending = glw_tex_create(w->glw_root, gi->gi_pending_url, flags, xs, ys); rstr_release(gi->gi_pending_url); gi->gi_pending_url = NULL; } } } if((glt = gi->gi_pending) != NULL) { glw_tex_layout(gr, glt); if(glw_is_tex_inited(&glt->glt_texture) || glt->glt_state == GLT_STATE_ERROR) { // Pending texture completed, ok or error: transfer to current if(gi->gi_current != NULL) glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = gi->gi_pending; gi->gi_pending = NULL; gi->gi_update = 1; gi->gi_loading_new_url = 0; } } if((glt = gi->gi_current) == NULL) return; if(gi->gi_loading_new_url) { gi->gi_autofade = GLW_LP(8, gi->gi_autofade, 0); } else { gi->gi_autofade = GLW_LP(8, gi->gi_autofade, 1); } glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_ERROR) { if(!gi->gi_is_ready) { gi->gi_is_ready = 1; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } } else if(glw_is_tex_inited(&glt->glt_texture)) { int r = !gi->gi_loading_new_url; if(gi->gi_is_ready != r) { gi->gi_is_ready = r; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } if(gi->gi_update) { gi->gi_update = 0; glw_renderer_free(&gi->gi_gr); switch(gi->gi_mode) { case GI_MODE_NORMAL: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_normal(gr, rc, gi, glt); break; case GI_MODE_BORDER_SCALING: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_alpha_edges(gr, rc, gi, glt); break; case GI_MODE_BORDER_ONLY_SCALING: glw_renderer_init(&gi->gi_gr, 16, 16, borderonlyobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; default: abort(); } } else if(gi->gi_last_width != rc->rc_width || gi->gi_last_height != rc->rc_height) { gi->gi_last_width = rc->rc_width; gi->gi_last_height = rc->rc_height; switch(gi->gi_mode) { case GI_MODE_NORMAL: break; case GI_MODE_BORDER_SCALING: case GI_MODE_BORDER_ONLY_SCALING: glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_image_layout_alpha_edges(gr, rc, gi, glt); break; } gi->gi_need_reload = hq; } if(gi->gi_need_reload && gi->gi_pending == NULL && gi->gi_pending_url == NULL && rc->rc_width && rc->rc_height) { gi->gi_need_reload = 0; int xs = -1, ys = -1, rescale; if(rc->rc_width < rc->rc_height) { rescale = rc->rc_width != glt->glt_xs; xs = rc->rc_width; } else { rescale = rc->rc_height != glt->glt_ys; ys = rc->rc_height; } if(rescale) { int flags = 0; if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; gi->gi_pending = glw_tex_create(w->glw_root, glt->glt_url, flags, xs, ys); } } } else { if(gi->gi_is_ready) { gi->gi_is_ready = 0; glw_signal0(w, GLW_SIGNAL_READINESS, NULL); } } glw_image_update_constraints(gi); if((c = TAILQ_FIRST(&w->glw_childs)) != NULL) { rc0 = *rc; rc0.rc_width -= gi->gi_box_left + gi->gi_box_right; rc0.rc_height -= gi->gi_box_top + gi->gi_box_bottom; if(rc0.rc_height >= 0 && rc0.rc_width >= 0) glw_layout0(c, &rc0); } }
static void glw_fx_texrot_layout(glw_t *w, glw_rctx_t *rc) { glw_fx_texrot_t *fx = (void *)w; glw_loadable_texture_t *glt = fx->fx_tex; glw_root_t *gr = w->glw_root; glw_rctx_t rc0; int width = 512; int height = 512; width = 256; height = 256; if(glt == NULL) return; // Layout the source texture glw_tex_layout(w->glw_root, glt); if(!glw_renderer_initialized(&fx->fx_render)) { float xs = gr->gr_normalized_texture_coords ? 1.0 : glt->glt_xs; float ys = gr->gr_normalized_texture_coords ? 1.0 : glt->glt_ys; glw_renderer_init_quad(&fx->fx_source_render); glw_renderer_vtx_pos(&fx->fx_source_render, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_st (&fx->fx_source_render, 0, 0.0, ys); glw_renderer_vtx_pos(&fx->fx_source_render, 1, 1.0, -1.0, 0.0); glw_renderer_vtx_st (&fx->fx_source_render, 1, xs, ys); glw_renderer_vtx_pos(&fx->fx_source_render, 2, 1.0, 1.0, 0.0); glw_renderer_vtx_st (&fx->fx_source_render, 2, xs, 0.0); glw_renderer_vtx_pos(&fx->fx_source_render, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_st (&fx->fx_source_render, 3, 0.0, 0.0); } // Init render to texture object if(!fx->fx_rtt_initialized) { fx->fx_rtt_initialized = 1; glw_rtt_init(gr, &fx->fx_rtt, width, height, 0); } // Initialize output texture if(!fx->fx_render_initialized) { float xs = gr->gr_normalized_texture_coords ? 1.0 : width; float ys = gr->gr_normalized_texture_coords ? 1.0 : height; glw_renderer_init_quad(&fx->fx_render); glw_renderer_vtx_pos(&fx->fx_render, 0, -1.0, -1.0, 0.0); glw_renderer_vtx_st (&fx->fx_render, 0, 0.0, ys); glw_renderer_vtx_pos(&fx->fx_render, 1, 1.0, -1.0, 0.0); glw_renderer_vtx_st (&fx->fx_render, 1, xs, ys); glw_renderer_vtx_pos(&fx->fx_render, 2, 1.0, 1.0, 0.0); glw_renderer_vtx_st (&fx->fx_render, 2, xs, 0.0); glw_renderer_vtx_pos(&fx->fx_render, 3, -1.0, 1.0, 0.0); glw_renderer_vtx_st (&fx->fx_render, 3, 0.0, 0.0); } if(!fx->fx_need_render) return; // Enter render-to-texture mode glw_rtt_enter(gr, &fx->fx_rtt, &rc0); // Render the gradients glw_fx_texrot_render_internal(gr, &rc0, fx, glt); // Leave render-to-texture mode glw_rtt_restore(gr, &fx->fx_rtt); }
static void glw_text_bitmap_layout(glw_t *w, glw_rctx_t *rc) { glw_text_bitmap_t *gtb = (void *)w; glw_root_t *gr = w->glw_root; pixmap_t *pm = gtb->gtb_pixmap; // Initialize renderers if(!glw_renderer_initialized(>b->gtb_text_renderer)) glw_renderer_init_quad(>b->gtb_text_renderer); if(w->glw_class == &glw_text && !glw_renderer_initialized(>b->gtb_cursor_renderer)) glw_renderer_init_quad(>b->gtb_cursor_renderer); // Upload texture if(pm != NULL && pm->pm_pixels != NULL) { int fmt; fmt = pm->pm_type == PIXMAP_IA ? GLW_TEXTURE_FORMAT_I8A8 : GLW_TEXTURE_FORMAT_BGR32; glw_tex_upload(gr, >b->gtb_texture, pm->pm_pixels, fmt, pm->pm_width, pm->pm_height, 0); free(pm->pm_pixels); pm->pm_pixels = NULL; gtb->gtb_need_layout = 1; } // Check if we need to repaint if((gtb->gtb_saved_width != rc->rc_width || gtb->gtb_saved_height != rc->rc_height)) { if(pm != NULL && gtb->gtb_state == GTB_VALID) { if(pm->pm_flags & PIXMAP_TEXT_WRAPPED) gtb->gtb_state = GTB_NEED_RENDER; if(rc->rc_width > gtb->gtb_saved_width && pm->pm_flags & PIXMAP_TEXT_TRUNCATED) gtb->gtb_state = GTB_NEED_RENDER; if(gtb->gtb_flags & GTB_ELLIPSIZE) { if(pm->pm_flags & PIXMAP_TEXT_TRUNCATED) { gtb->gtb_state = GTB_NEED_RENDER; } else { if(rc->rc_width - gtb->gtb_padding_right - gtb->gtb_padding_left < pm->pm_width - pm->pm_margin * 2) gtb->gtb_state = GTB_NEED_RENDER; if(rc->rc_height - gtb->gtb_padding_top - gtb->gtb_padding_bottom < pm->pm_height - pm->pm_margin * 2) gtb->gtb_state = GTB_NEED_RENDER; } } } gtb->gtb_saved_width = rc->rc_width; gtb->gtb_saved_height = rc->rc_height; gtb->gtb_need_layout = 1; if(gtb->w.glw_flags & GLW_DEBUG) printf(" parent widget gives us :%d x %d\n", rc->rc_width, rc->rc_height); } if(pm != NULL && gtb->gtb_need_layout) { int left = gtb->gtb_padding_left - pm->pm_margin; int top = rc->rc_height - gtb->gtb_padding_top + pm->pm_margin; int right = rc->rc_width - gtb->gtb_padding_right + pm->pm_margin; int bottom = gtb->gtb_padding_bottom - pm->pm_margin; int text_width = pm->pm_width; int text_height = pm->pm_height; float x1, y1, x2, y2; // Horizontal if(text_width > right - left) { // Oversized, must cut text_width = right - left; if(!(gtb->gtb_flags & GTB_ELLIPSIZE)) { glw_renderer_vtx_col(>b->gtb_text_renderer, 0, 1,1,1,1+text_width/20); glw_renderer_vtx_col(>b->gtb_text_renderer, 1, 1,1,1,0); glw_renderer_vtx_col(>b->gtb_text_renderer, 2, 1,1,1,0); glw_renderer_vtx_col(>b->gtb_text_renderer, 3, 1,1,1,1+text_width/20); } } else { glw_renderer_vtx_col(>b->gtb_text_renderer, 0, 1,1,1,1); glw_renderer_vtx_col(>b->gtb_text_renderer, 1, 1,1,1,1); glw_renderer_vtx_col(>b->gtb_text_renderer, 2, 1,1,1,1); glw_renderer_vtx_col(>b->gtb_text_renderer, 3, 1,1,1,1); switch(w->glw_alignment) { case LAYOUT_ALIGN_JUSTIFIED: case LAYOUT_ALIGN_CENTER: case LAYOUT_ALIGN_BOTTOM: case LAYOUT_ALIGN_TOP: left = (left + right - text_width) / 2; right = left + text_width; break; case LAYOUT_ALIGN_LEFT: case LAYOUT_ALIGN_TOP_LEFT: case LAYOUT_ALIGN_BOTTOM_LEFT: right = left + pm->pm_width; break; case LAYOUT_ALIGN_RIGHT: case LAYOUT_ALIGN_TOP_RIGHT: case LAYOUT_ALIGN_BOTTOM_RIGHT: left = right - pm->pm_width; break; } } // Vertical if(text_height > top - bottom) { // Oversized, must cut text_height = top - bottom; } else { switch(w->glw_alignment) { case LAYOUT_ALIGN_CENTER: case LAYOUT_ALIGN_LEFT: case LAYOUT_ALIGN_RIGHT: bottom = (bottom + top - text_height) / 2; top = bottom + text_height; break; case LAYOUT_ALIGN_TOP_LEFT: case LAYOUT_ALIGN_TOP_RIGHT: case LAYOUT_ALIGN_TOP: case LAYOUT_ALIGN_JUSTIFIED: bottom = top - pm->pm_height; break; case LAYOUT_ALIGN_BOTTOM: case LAYOUT_ALIGN_BOTTOM_LEFT: case LAYOUT_ALIGN_BOTTOM_RIGHT: top = bottom + pm->pm_height; break; } } x1 = -1.0f + 2.0f * left / (float)rc->rc_width; y1 = -1.0f + 2.0f * bottom / (float)rc->rc_height; x2 = -1.0f + 2.0f * right / (float)rc->rc_width; y2 = -1.0f + 2.0f * top / (float)rc->rc_height; float s, t; if(gr->gr_normalized_texture_coords) { s = text_width / (float)pm->pm_width; t = text_height / (float)pm->pm_height; } else { s = text_width; t = text_height; } glw_renderer_vtx_pos(>b->gtb_text_renderer, 0, x1, y1, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 0, 0, t); glw_renderer_vtx_pos(>b->gtb_text_renderer, 1, x2, y1, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 1, s, t); glw_renderer_vtx_pos(>b->gtb_text_renderer, 2, x2, y2, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 2, s, 0); glw_renderer_vtx_pos(>b->gtb_text_renderer, 3, x1, y2, 0.0); glw_renderer_vtx_st (>b->gtb_text_renderer, 3, 0, 0); } if(w->glw_class == &glw_text && gtb->gtb_update_cursor && gtb->gtb_state == GTB_VALID) { int i = gtb->gtb_edit_ptr; int left, right; float x1, y1, x2, y2; if(pm != NULL && pm->pm_charpos != NULL) { if(i < pm->pm_charposlen) { left = pm->pm_charpos[i*2 ]; right = pm->pm_charpos[i*2+1]; } else { left = pm->pm_charpos[2*pm->pm_charposlen - 1]; right = left + 10; } left += gtb->gtb_padding_left; right += gtb->gtb_padding_left; } else { left = 0; right = 10; } x1 = -1.0f + 2.0f * left / (float)rc->rc_width; x2 = -1.0f + 2.0f * right / (float)rc->rc_width; y1 = -0.9f; y2 = 0.9f; glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 0, x1, y1, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 1, x2, y1, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 2, x2, y2, 0.0); glw_renderer_vtx_pos(>b->gtb_cursor_renderer, 3, x1, y2, 0.0); gtb->gtb_update_cursor = 0; } gtb->gtb_paint_cursor = w->glw_class == &glw_text && glw_is_focused(w); gtb->gtb_need_layout = 0; if(gtb->gtb_state == GTB_VALID && gtb->gtb_deferred_realize) { gtb->gtb_deferred_realize = 0; gtb_realize(gtb); } if(gtb->gtb_state != GTB_NEED_RENDER) return; TAILQ_INSERT_TAIL(&gr->gr_gtb_render_queue, gtb, gtb_workq_link); gtb->gtb_state = GTB_QUEUED_FOR_RENDERING; hts_cond_signal(&gr->gr_gtb_work_cond); }
static void glw_image_layout(glw_t *w, glw_rctx_t *rc) { glw_image_t *gi = (void *)w; glw_root_t *gr = w->glw_root; glw_loadable_texture_t *glt; glw_rctx_t rc0; glw_t *c; if(gi->gi_pending_filename != NULL) { // Request to load int xs = -1, ys = -1; int flags = 0; if(gi->gi_pending != NULL) glw_tex_deref(w->glw_root, gi->gi_pending); if(gi->gi_pending_filename[0] == 0) { gi->gi_pending = NULL; if(gi->gi_current != NULL) { glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = NULL; } gi->gi_update = 1; } else { if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; if(gi->gi_bitmap_flags & GLW_IMAGE_HQ_SCALING) { if(rc->rc_width < rc->rc_height) { xs = rc->rc_width; } else { ys = rc->rc_height; } } if(xs && ys) { gi->gi_pending = glw_tex_create(w->glw_root, gi->gi_pending_filename, flags, xs, ys); free(gi->gi_pending_filename); gi->gi_pending_filename = NULL; } else { gi->gi_pending = NULL; } } } if((glt = gi->gi_pending) != NULL) { glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_VALID || glt->glt_state == GLT_STATE_ERROR) { // Pending texture completed, ok or error: transfer to current if(gi->gi_current != NULL) glw_tex_deref(w->glw_root, gi->gi_current); gi->gi_current = gi->gi_pending; gi->gi_pending = NULL; gi->gi_update = 1; } } if((glt = gi->gi_current) == NULL) return; glw_tex_layout(gr, glt); if(glt->glt_state == GLT_STATE_ERROR) { if(!gi->gi_was_valid) { glw_signal0(w, GLW_SIGNAL_READY, NULL); gi->gi_was_valid = 1; } } else if(glt->glt_state == GLT_STATE_VALID) { if(!gi->gi_was_valid) { glw_signal0(w, GLW_SIGNAL_READY, NULL); gi->gi_was_valid = 1; } if(gi->gi_update) { gi->gi_update = 0; glw_renderer_free(&gi->gi_gr); switch(gi->gi_mode) { case GI_MODE_NORMAL: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_normal(gr, rc, gi, glt); break; case GI_MODE_BORDER_SCALING: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_renderer_init_quad(&gi->gi_gr); glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_renderer_init(&gi->gi_gr, 16, 18, borderobject); glw_image_layout_alpha_edges(gr, rc, gi, glt); break; case GI_MODE_BORDER_ONLY_SCALING: glw_renderer_init(&gi->gi_gr, 16, 16, borderonlyobject); glw_image_layout_tesselated(gr, rc, gi, glt); break; default: abort(); } } else if(gi->gi_last_width != rc->rc_width || gi->gi_last_height != rc->rc_height) { gi->gi_last_width = rc->rc_width; gi->gi_last_height = rc->rc_height; switch(gi->gi_mode) { case GI_MODE_NORMAL: break; case GI_MODE_BORDER_SCALING: case GI_MODE_BORDER_ONLY_SCALING: glw_image_layout_tesselated(gr, rc, gi, glt); break; case GI_MODE_REPEATED_TEXTURE: glw_image_layout_repeated(gr, rc, gi, glt); break; case GI_MODE_ALPHA_EDGES: glw_image_layout_alpha_edges(gr, rc, gi, glt); break; } if(gi->gi_bitmap_flags & GLW_IMAGE_HQ_SCALING && gi->gi_pending == NULL && gi->gi_pending_filename == NULL && rc->rc_width && rc->rc_height) { int xs = -1, ys = -1, rescale; if(rc->rc_width < rc->rc_height) { rescale = abs(rc->rc_width - glt->glt_xs) > glt->glt_xs / 10; xs = rc->rc_width; } else { rescale = abs(rc->rc_height - glt->glt_ys) > glt->glt_ys / 10; ys = rc->rc_height; } if(rescale) { int flags = 0; if(w->glw_class == &glw_repeatedimage) flags |= GLW_TEX_REPEAT; gi->gi_pending = glw_tex_create(w->glw_root, glt->glt_filename, flags, xs, ys); } } } } glw_image_update_constraints(gi); if((c = TAILQ_FIRST(&w->glw_childs)) != NULL) { rc0 = *rc; rc0.rc_width -= gi->gi_box_left + gi->gi_box_right; rc0.rc_height -= gi->gi_box_top + gi->gi_box_bottom; if(rc0.rc_height >= 0 && rc0.rc_width >= 0) glw_layout0(c, &rc0); } }