Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
  }
}
Beispiel #4
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);
}
Beispiel #5
0
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(&gt->renderer)) {
    glw_renderer_init_quad(&gt->renderer);

    glw_renderer_vtx_pos(&gt->renderer, 0, -0.05, 0.4, 0);
    glw_renderer_vtx_pos(&gt->renderer, 1,  0.05, 0.4, 0);
    glw_renderer_vtx_pos(&gt->renderer, 2,  0.05, 1, 0);
    glw_renderer_vtx_pos(&gt->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(&gt->renderer, gr, &rc1, 
		      NULL,
		      &gt->color, NULL, a0 * alpha, 0, NULL);
  }
}
Beispiel #6
0
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(&gtb->gtb_text_renderer)))
    glw_renderer_init_quad(&gtb->gtb_text_renderer);

  if(w->glw_class == &glw_text &&
     unlikely(!glw_renderer_initialized(&gtb->gtb_cursor_renderer)))
    glw_renderer_init_quad(&gtb->gtb_cursor_renderer);

  if(gtb->gtb_background_alpha > GLW_ALPHA_EPSILON &&
     unlikely(!glw_renderer_initialized(&gtb->gtb_cursor_renderer))) {
    glw_renderer_init_quad(&gtb->gtb_background_renderer);
    glw_renderer_vtx_pos(&gtb->gtb_background_renderer, 0, -1, -1, 0);
    glw_renderer_vtx_pos(&gtb->gtb_background_renderer, 1,  1, -1, 0);
    glw_renderer_vtx_pos(&gtb->gtb_background_renderer, 2,  1,  1, 0);
    glw_renderer_vtx_pos(&gtb->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, &gtb->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(&gtb->gtb_texture);
  const int tex_height = glw_tex_height(&gtb->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(&gtb->gtb_text_renderer, 0, 1,1,1,1+text_width/20);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 1, 1,1,1,0);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 2, 1,1,1,0);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 3, 1,1,1,1+text_width/20);
      }
#endif
    } else {

      glw_renderer_vtx_col_reset(&gtb->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(&gtb->gtb_text_renderer, 0, x1, y1, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 0, 0, t);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 1, x2, y1, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 1, s, t);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 2, x2, y2, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 2, s, 0);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 3, x1, y2, 0.0);
    glw_renderer_vtx_st (&gtb->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(&gtb->gtb_cursor_renderer, 0, x1, y1, 0.0);
    glw_renderer_vtx_pos(&gtb->gtb_cursor_renderer, 1, x2, y1, 0.0);
    glw_renderer_vtx_pos(&gtb->gtb_cursor_renderer, 2, x2, y2, 0.0);
    glw_renderer_vtx_pos(&gtb->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);
}
Beispiel #7
0
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]);
  }
}
Beispiel #8
0
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);
  }

}
Beispiel #9
0
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);
  }
}
Beispiel #10
0
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);
}
Beispiel #11
0
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(&gtb->gtb_text_renderer))
    glw_renderer_init_quad(&gtb->gtb_text_renderer);

  if(w->glw_class == &glw_text &&
     !glw_renderer_initialized(&gtb->gtb_cursor_renderer))
    glw_renderer_init_quad(&gtb->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, &gtb->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(&gtb->gtb_text_renderer, 0, 1,1,1,1+text_width/20);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 1, 1,1,1,0);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 2, 1,1,1,0);
	glw_renderer_vtx_col(&gtb->gtb_text_renderer, 3, 1,1,1,1+text_width/20);
      }

    } else { 

      glw_renderer_vtx_col(&gtb->gtb_text_renderer, 0, 1,1,1,1);
      glw_renderer_vtx_col(&gtb->gtb_text_renderer, 1, 1,1,1,1);
      glw_renderer_vtx_col(&gtb->gtb_text_renderer, 2, 1,1,1,1);
      glw_renderer_vtx_col(&gtb->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(&gtb->gtb_text_renderer, 0, x1, y1, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 0, 0, t);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 1, x2, y1, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 1, s, t);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 2, x2, y2, 0.0);
    glw_renderer_vtx_st (&gtb->gtb_text_renderer, 2, s, 0);

    glw_renderer_vtx_pos(&gtb->gtb_text_renderer, 3, x1, y2, 0.0);
    glw_renderer_vtx_st (&gtb->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(&gtb->gtb_cursor_renderer, 0, x1, y1, 0.0);
    glw_renderer_vtx_pos(&gtb->gtb_cursor_renderer, 1, x2, y1, 0.0);
    glw_renderer_vtx_pos(&gtb->gtb_cursor_renderer, 2, x2, y2, 0.0);
    glw_renderer_vtx_pos(&gtb->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);
}
Beispiel #12
0
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);
  }
}