Esempio n. 1
0
static int
repaint(glw_gradient_t *gg, glw_root_t *gr, int tile, int w, int h, int tiles)
{
  int x, y, n = showtime_get_ts(), m = 0;
  uint8_t  *p, *pixmap;
  size_t s = h * w * GRAD_BPP;

  if(w < 1 || h < 1)
    return 0;

  p = pixmap = malloc(s);
  for(y = 0; y < h; y++) {
    float a = (float)y / (float)h;
    int r = 65280 * GLW_LERP(a, gg->gg_col1[0], gg->gg_col2[0]);
    int g = 65280 * GLW_LERP(a, gg->gg_col1[1], gg->gg_col2[1]);
    int b = 65280 * GLW_LERP(a, gg->gg_col1[2], gg->gg_col2[2]);

    for(x = 0; x < w; x++) {
      n = n * 1664525 + 1013904223;
      *p++ = (b + (n & 0xff)) >> 8;

      n = n * 1664525 + 1013904223;
      *p++ = (g + (n & 0xff)) >> 8;

      n = n * 1664525 + 1013904223;
      *p++ = (r + (n & 0xff)) >> 8;
    }
    n = n ^ m;
    m = m * 1664525 + 1013904223;
  }

  if(gg->gg_image_flags & GLW_IMAGE_BEVEL_TOP)
    bevel_top(pixmap, w, h);

  if(gg->gg_image_flags & GLW_IMAGE_BEVEL_BOTTOM)
    bevel_bottom(pixmap, w, h);

  glw_tex_upload(gr, &gg->gg_tex[0], pixmap, GLW_TEXTURE_FORMAT_RGB, w, h, 
		 GLW_TEX_REPEAT);

  if(tiles == 3) {
    p = malloc(s);

    memcpy(p, pixmap, s);
    if(gg->gg_image_flags & GLW_IMAGE_BEVEL_LEFT)
      bevel_left(p, w, h);
    glw_tex_upload(gr, &gg->gg_tex[1], p, GLW_TEXTURE_FORMAT_RGB, w, h, 
		   GLW_TEX_REPEAT);

    memcpy(p, pixmap, s);
    if(gg->gg_image_flags & GLW_IMAGE_BEVEL_RIGHT)
      bevel_right(p, w, h);
    glw_tex_upload(gr, &gg->gg_tex[2], p, GLW_TEXTURE_FORMAT_RGB, w, h, 
		   GLW_TEX_REPEAT);

    free(p);
  }
  free(pixmap);
  return 1;
}
Esempio n. 2
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);
}
Esempio n. 3
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);
}
Esempio n. 4
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);
}