Beispiel #1
0
void
gimp_display_shell_render (GimpDisplayShell *shell,
                           cairo_t          *cr,
                           gint              x,
                           gint              y,
                           gint              w,
                           gint              h)
{
  GimpImage       *image;
  GeglBuffer      *buffer;
#ifdef USE_NODE_BLIT
  GeglNode        *node;
#endif
  gdouble          scale_x       = 1.0;
  gdouble          scale_y       = 1.0;
  gdouble          buffer_scale  = 1.0;
  gint             viewport_offset_x;
  gint             viewport_offset_y;
  gint             viewport_width;
  gint             viewport_height;
  gint             scaled_x;
  gint             scaled_y;
  gint             scaled_width;
  gint             scaled_height;
  cairo_surface_t *xfer;
  gint             xfer_src_x;
  gint             xfer_src_y;
  gint             mask_src_x = 0;
  gint             mask_src_y = 0;
  gint             cairo_stride;
  guchar          *cairo_data;
  GeglBuffer      *cairo_buffer;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (cr != NULL);
  g_return_if_fail (w > 0 && h > 0);

  image  = gimp_display_get_image (shell->display);
  buffer = gimp_pickable_get_buffer (GIMP_PICKABLE (image));
#ifdef USE_NODE_BLIT
  node   = gimp_projectable_get_graph (GIMP_PROJECTABLE (image));
#endif

#ifdef GIMP_DISPLAY_RENDER_ENABLE_SCALING
  /* if we had this future API, things would look pretty on hires (retina) */
  scale_x = gdk_window_get_scale_factor (gtk_widget_get_window (gtk_widget_get_toplevel (GTK_WIDGET (shell))));
#endif

  scale_x = MIN (scale_x, GIMP_DISPLAY_RENDER_MAX_SCALE);
  scale_y = scale_x;

  if (shell->scale_x > shell->scale_y)
    {
      scale_y *= (shell->scale_x / shell->scale_y);

      buffer_scale = shell->scale_y * scale_y;
    }
  else if (shell->scale_y > shell->scale_x)
    {
      scale_x *= (shell->scale_y / shell->scale_x);

      buffer_scale = shell->scale_x * scale_x;
    }
  else
    {
      buffer_scale = shell->scale_x * scale_x;
    }

  gimp_display_shell_scroll_get_scaled_viewport (shell,
                                                 &viewport_offset_x,
                                                 &viewport_offset_y,
                                                 &viewport_width,
                                                 &viewport_height);

  scaled_x      = floor ((x + viewport_offset_x) * scale_x);
  scaled_y      = floor ((y + viewport_offset_y) * scale_y);
  scaled_width  = ceil (w * scale_x);
  scaled_height = ceil (h * scale_y);

  if (shell->rotate_transform)
    {
      xfer = cairo_surface_create_similar_image (cairo_get_target (cr),
                                                 CAIRO_FORMAT_ARGB32,
                                                 scaled_width,
                                                 scaled_height);
      cairo_surface_mark_dirty (xfer);
      xfer_src_x = 0;
      xfer_src_y = 0;
    }
  else
    {
      xfer = gimp_display_xfer_get_surface (shell->xfer,
                                            scaled_width,
                                            scaled_height,
                                            &xfer_src_x,
                                            &xfer_src_y);
    }

  cairo_stride = cairo_image_surface_get_stride (xfer);
  cairo_data   = cairo_image_surface_get_data (xfer) +
                 xfer_src_y * cairo_stride + xfer_src_x * 4;

  cairo_buffer = gegl_buffer_linear_new_from_data (cairo_data,
                                                   babl_format ("cairo-ARGB32"),
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height),
                                                   cairo_stride,
                                                   NULL, NULL);

  if (shell->profile_transform ||
      gimp_display_shell_has_filter (shell))
    {
      gboolean can_convert_to_u8;

      /*  if there is a profile transform or a display filter, we need
       *  to use temp buffers
       */

      can_convert_to_u8 = gimp_display_shell_profile_can_convert_to_u8 (shell);

      /*  create the filter buffer if we have filters
       */
      if ((gimp_display_shell_has_filter (shell) || ! can_convert_to_u8) &&
          ! shell->filter_buffer)
        {
          gint w = GIMP_DISPLAY_RENDER_BUF_WIDTH  * GIMP_DISPLAY_RENDER_MAX_SCALE;
          gint h = GIMP_DISPLAY_RENDER_BUF_HEIGHT * GIMP_DISPLAY_RENDER_MAX_SCALE;

          shell->filter_data =
            gegl_malloc (w * h * babl_format_get_bytes_per_pixel (shell->filter_format));

          shell->filter_stride =
            w * babl_format_get_bytes_per_pixel (shell->filter_format);

          shell->filter_buffer =
            gegl_buffer_linear_new_from_data (shell->filter_data,
                                              shell->filter_format,
                                              GEGL_RECTANGLE (0, 0, w, h),
                                              GEGL_AUTO_ROWSTRIDE,
                                              (GDestroyNotify) gegl_free,
                                              shell->filter_data);
        }

      if (shell->profile_transform)
        {
          /*  if there is a profile transform, load the projection
           *  pixels into the profile_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                           shell->profile_data, shell->profile_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          gimp_projectable_get_format (GIMP_PROJECTABLE (image)),
                          shell->profile_data, shell->profile_stride,
                          GEGL_BLIT_CACHE);
#endif

          if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
            {
              /*  if there are filters, convert the pixels from the
               *  profile_buffer to the filter_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         shell->filter_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
          else
            {
              /*  otherwise, convert the profile_buffer directly into
               *  the cairo_buffer
               */
              gimp_display_shell_profile_convert_buffer (shell,
                                                         shell->profile_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height),
                                                         cairo_buffer,
                                                         GEGL_RECTANGLE (0, 0,
                                                                         scaled_width,
                                                                         scaled_height));
            }
        }
      else
        {
          /*  otherwise, load the projection pixels directly into the
           *  filter_buffer
           */
#ifndef USE_NODE_BLIT
          gegl_buffer_get (buffer,
                           GEGL_RECTANGLE (scaled_x, scaled_y,
                                           scaled_width, scaled_height),
                           buffer_scale,
                           shell->filter_format,
                           shell->filter_data, shell->filter_stride,
                           GEGL_ABYSS_CLAMP);
#else
          gegl_node_blit (node,
                          buffer_scale,
                          GEGL_RECTANGLE (scaled_x, scaled_y,
                                          scaled_width, scaled_height),
                          shell->filter_format,
                          shell->filter_data, shell->filter_stride,
                          GEGL_BLIT_CACHE);
#endif
        }

      if (gimp_display_shell_has_filter (shell))
        {
          /*  convert the filter_buffer in place
           */
          gimp_color_display_stack_convert_buffer (shell->filter_stack,
                                                   shell->filter_buffer,
                                                   GEGL_RECTANGLE (0, 0,
                                                                   scaled_width,
                                                                   scaled_height));
        }

      if (gimp_display_shell_has_filter (shell) || ! can_convert_to_u8)
        {
          /*  finally, copy the filter buffer to the cairo-ARGB32 buffer
           */
          gegl_buffer_get (shell->filter_buffer,
                           GEGL_RECTANGLE (0, 0,
                                           scaled_width,
                                           scaled_height),
                           1.0,
                           babl_format ("cairo-ARGB32"),
                           cairo_data, cairo_stride,
                           GEGL_ABYSS_CLAMP);
        }
    }
  else
    {
      /*  otherwise we can copy the projection pixels straight to the
       *  cairo-ARGB32 buffer
       */
#ifndef USE_NODE_BLIT
      gegl_buffer_get (buffer,
                       GEGL_RECTANGLE (scaled_x, scaled_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("cairo-ARGB32"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_CLAMP);
#else
      gegl_node_blit (node,
                      buffer_scale,
                      GEGL_RECTANGLE (scaled_x, scaled_y,
                                      scaled_width, scaled_height),
                      babl_format ("cairo-ARGB32"),
                      cairo_data, cairo_stride,
                      GEGL_BLIT_CACHE);
#endif
    }

  g_object_unref (cairo_buffer);

  if (shell->mask)
    {
      if (! shell->mask_surface)
        {
          shell->mask_surface =
            cairo_image_surface_create (CAIRO_FORMAT_A8,
                                        GIMP_DISPLAY_RENDER_BUF_WIDTH  *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE,
                                        GIMP_DISPLAY_RENDER_BUF_HEIGHT *
                                        GIMP_DISPLAY_RENDER_MAX_SCALE);
        }

      cairo_surface_mark_dirty (shell->mask_surface);

      cairo_stride = cairo_image_surface_get_stride (shell->mask_surface);
      cairo_data   = cairo_image_surface_get_data (shell->mask_surface) +
                     mask_src_y * cairo_stride + mask_src_x * 4;

      gegl_buffer_get (shell->mask,
                       GEGL_RECTANGLE (scaled_x - shell->mask_offset_x,
                                       scaled_y - shell->mask_offset_y,
                                       scaled_width, scaled_height),
                       buffer_scale,
                       babl_format ("Y u8"),
                       cairo_data, cairo_stride,
                       GEGL_ABYSS_NONE);

      if (shell->mask_inverted)
        {
          gint mask_height = scaled_height;

          while (mask_height--)
            {
              gint    mask_width = scaled_width;
              guchar *d          = cairo_data;

              while (mask_width--)
                {
                  guchar inv = 255 - *d;

                  *d++ = inv;
                }

              cairo_data += cairo_stride;
            }
        }
    }

  /*  put it to the screen  */
  cairo_save (cr);

  cairo_rectangle (cr, x, y, w, h);

  cairo_scale (cr, 1.0 / scale_x, 1.0 / scale_y);

  cairo_set_source_surface (cr, xfer,
                            x * scale_x - xfer_src_x,
                            y * scale_y - xfer_src_y);

  if (shell->rotate_transform)
    {
      cairo_pattern_t *pattern;

      pattern = cairo_get_source (cr);
      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

      cairo_set_line_width (cr, 1.0);
      cairo_stroke_preserve (cr);

      cairo_surface_destroy (xfer);
    }

  cairo_clip (cr);
  cairo_paint (cr);

  if (shell->mask)
    {
      gimp_cairo_set_source_rgba (cr, &shell->mask_color);
      cairo_mask_surface (cr, shell->mask_surface,
                          (x - mask_src_x) * scale_x,
                          (y - mask_src_y) * scale_y);
    }

  cairo_restore (cr);
}
unsigned char* LcCairoPainter::data() {
    return cairo_image_surface_get_data(_surface);
}
Beispiel #3
0
static void cdcreatecanvas(cdCanvas* canvas, void* data)
{
  cdCtxCanvas* ctxcanvas;
  cairo_surface_t *surface;
  int w = 0, h = 0, use_alpha = 0;
  double res = 3.78;
  unsigned char *rgb = NULL;
  char* str_data = (char*)data;
  char* res_ptr = NULL;
  cairo_format_t format = CAIRO_FORMAT_RGB24;

  /* Starting parameters */
  if (str_data == NULL) 
    return;

  if (strstr(str_data, "-a"))
    use_alpha = 1;

  res_ptr = strstr(str_data, "-r");
  if (res_ptr)
    sscanf(res_ptr+2, "%lg", &res);

  /* size and rgb */
#ifdef SunOS_OLD
  sscanf(str_data, "%dx%d %d", &w, &h, &rgb);
#else
  sscanf(str_data, "%dx%d %p", &w, &h, &rgb);
#endif

  if (w == 0) w = 1;
  if (h == 0) h = 1;

  canvas->w = w;
  canvas->h = h;
  canvas->yres = res;
  canvas->xres = res;
  canvas->w_mm = ((double)w) / res;
  canvas->h_mm = ((double)h) / res;
  if (use_alpha)
  {
    canvas->bpp = 32;
    format = CAIRO_FORMAT_ARGB32;
  }
  else
    canvas->bpp = 24;  /* fake value, image bpp is always 32 */

  if (rgb)
    surface = cairo_image_surface_create_for_data(rgb, format, w, h, w*32);
  else
  	surface = cairo_image_surface_create(format, canvas->w, canvas->h);

  /* Starting Cairo driver */
  ctxcanvas = cdcairoCreateCanvas(canvas, cairo_create(surface));
  cairo_surface_destroy(surface);

  if (rgb)
  {
    ctxcanvas->user_image = 1;
    ctxcanvas->rgb = rgb;
  }
  else
  {
    ctxcanvas->user_image = 0;
    ctxcanvas->rgb = cairo_image_surface_get_data(cairo_get_target(ctxcanvas->cr));

    /* fill with white */
    /* transparent, this is the normal alpha coding */
    cairo_set_source_rgba(ctxcanvas->cr, 1.0, 1.0, 1.0, 0.0);
    cairo_rectangle(ctxcanvas->cr, 0, 0, canvas->w, canvas->h);
    cairo_fill(ctxcanvas->cr);
  }
                                      
  cdRegisterAttribute(canvas, &stride_attrib);
  cdRegisterAttribute(canvas, &write2png_attrib);
  cdRegisterAttribute(canvas, &data_attrib);
}
Beispiel #4
0
	double lime_cairo_image_surface_get_data (double handle) {
		
		return (intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)(intptr_t)handle);
		
	}
Beispiel #5
0
gboolean
draw_page_cairo (GtkPrintContext *context,
                 PrintData       *data)
{
  GimpDrawable    *drawable = gimp_drawable_get (data->drawable_id);
  GimpPixelRgn     region;
  cairo_t         *cr;
  cairo_surface_t *surface;
  guchar          *pixels;
  gdouble          cr_width;
  gdouble          cr_height;
  gdouble          cr_dpi_x;
  gdouble          cr_dpi_y;
  gint             width;
  gint             height;
  gint             stride;
  gint             y;
  gdouble          scale_x;
  gdouble          scale_y;

  width  = drawable->width;
  height = drawable->height;

  gimp_tile_cache_ntiles (width / gimp_tile_width () + 1);

  cr = gtk_print_context_get_cairo_context (context);

  cr_width  = gtk_print_context_get_width  (context);
  cr_height = gtk_print_context_get_height (context);
  cr_dpi_x  = gtk_print_context_get_dpi_x  (context);
  cr_dpi_y  = gtk_print_context_get_dpi_y  (context);

  scale_x = cr_dpi_x / data->xres;
  scale_y = cr_dpi_y / data->yres;

#if 0
  /* print header if it is requested */
  if (data->show_info_header)
    {
      draw_info_header (context, cr, data);

/* In points */
#define HEADER_HEIGHT (20 * 72.0 / 25.4)
      cairo_translate (cr, 0, HEADER_HEIGHT);
      cr_height -= HEADER_HEIGHT;
    }
#endif

  cairo_translate (cr,
                   data->offset_x / cr_dpi_x * 72.0,
                   data->offset_y / cr_dpi_y * 72.0);
  cairo_scale (cr, scale_x, scale_y);

  gimp_pixel_rgn_init (&region, drawable, 0, 0, width, height, FALSE, FALSE);

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);

  pixels = cairo_image_surface_get_data (surface);
  stride = cairo_image_surface_get_stride (surface);

  for (y = 0; y < height; y++, pixels += stride)
    {
      gimp_pixel_rgn_get_row (&region, pixels, 0, y, width);

      switch (drawable->bpp)
        {
        case 3:
          convert_from_rgb (pixels, width);
          break;
        case 4:
          convert_from_rgba (pixels, width);
          break;
        }

      if (y % 16 == 0)
        gimp_progress_update ((gdouble) y / (gdouble) height);
    }

  cairo_set_source_surface (cr, surface, 0, 0);
  cairo_rectangle (cr, 0, 0, width, height);
  cairo_fill (cr);
  cairo_surface_destroy (surface);

  gimp_progress_update (1.0);

  gimp_drawable_detach (drawable);

  return TRUE;
}
Beispiel #6
0
static inline
cairo_region_t *
get_cairo_region_create_from_surface(struct qp_graph *gr,
    cairo_surface_t *surface, int width, int height)
{
  /* TODO: this is a resource pig.  Make it better. */

  cairo_rectangle_int_t rect;
  cairo_surface_t *image;
  cairo_region_t *region;
  cairo_t *cr;
  uint32_t *data, bg;
  int x, y, stride;

  if(!gr->x11)
    /* Creates region that covers the area where the
     * given surface is more than 50% opaque.
     * The below code copies this method.  This GDK
     * code is a pig too. */
    return gdk_cairo_region_create_from_surface(surface);

  if(!gr->x11->background_set)
  {
    /* We need to see what the background color is when it is
     * applied to an image.  A small image. */
    image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 1, 1);
    cr = cairo_create(image);
    cairo_set_source_rgba(cr, gr->background_color.r,
        gr->background_color.g, gr->background_color.b,
        gr->background_color.a);
    cairo_paint (cr);
    cairo_destroy (cr);
    data = (void *) cairo_image_surface_get_data(image);
    gr->x11->background = (data[0] & 0x00FFFFFF);
    cairo_surface_destroy(image);
    gr->x11->background_set = 1;
  }

  bg = gr->x11->background;

  image = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
  cr = cairo_create(image);
  cairo_set_source_surface(cr, surface, 0, 0);
  cairo_paint (cr);
  cairo_destroy (cr);

  data = (void *) cairo_image_surface_get_data(image);
  stride = cairo_image_surface_get_stride(image);

  region = cairo_region_create();

  for(y=0; y < height; y++)
    {
      for(x=0; x < width; x++)
        {
          /* Search for a continuous range of "background pixels"*/
          gint x0=x;
          while(x < width)
            {
              if((data[x] & 0x00FFFFFF) == bg)
                /* This pixel is the background color */
                break;
              x++;
            }

          if(x > x0)
            {
              /* Add the pixels (x0, y) to (x, y+1) as a new rectangle
               * in the region
               */
              rect.x = x0;
              rect.width = x - x0;
              rect.y = y;
              rect.height = 1;

              cairo_region_union_rectangle(region, &rect);
            }
        }
      data += stride/4;
    }

  cairo_surface_destroy(image);

  return region;
}
Beispiel #7
0
int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
{

#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
  struct svg_symbol_cache *svg_cache;
  symbolStyleObj pixstyle;
  symbolObj pixsymbol;
  int status;

  if(MS_SUCCESS != msPreloadSVGSymbol(symbol))
    return MS_FAILURE;
  svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache;

  //already rendered at the right size and scale? return
  if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) {
    cairo_t *cr;
    cairo_surface_t *surface;
    unsigned char *pb;
    int width, height, surface_w, surface_h;
    /* need to recompute the pixmap */
    if(svg_cache->pixmap_buffer) {
      msFreeRasterBuffer(svg_cache->pixmap_buffer);
    } else {
      svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj));
    }

    //increase pixmap size to accomodate scaling/rotation
    if (style->scale != 1.0) {
      width = surface_w = (symbol->sizex * style->scale + 0.5);
      height = surface_h = (symbol->sizey * style->scale + 0.5);
    } else {
      width = surface_w = symbol->sizex;
      height = surface_h = symbol->sizey;
    }
    if (style->rotation != 0) {
      surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415);
    }

    surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h);
    cr = cairo_create(surface);

    if (style->rotation != 0) {
      cairo_translate(cr, surface_w / 2, surface_h / 2);
      cairo_rotate(cr, -style->rotation);
      cairo_translate(cr, -width / 2, -height / 2);
    }
    if (style->scale != 1.0) {
      cairo_scale(cr, style->scale, style->scale);
    }
#ifdef USE_SVG_CAIRO
    if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) {
      return MS_FAILURE;
    }
#else
  rsvg_handle_render_cairo(svg_cache->svgc, cr);
#endif
    pb = cairo_image_surface_get_data(surface);

    //set up raster
    initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0);
    memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char));
    svg_cache->scale = style->scale;
    svg_cache->rotation = style->rotation;
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
  }
  assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width);

  pixstyle = *style;
  pixstyle.rotation = 0.0;
  pixstyle.scale = 1.0;

  pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer;
  pixsymbol.type = MS_SYMBOL_PIXMAP;

  status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle);
  MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol);
  return status;
#else
  msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo",
             "renderSVGSymbolCairo()");
  return MS_FAILURE;
#endif
}
Beispiel #8
0
static void draw_page_cairo(GtkPrintContext *context, PrintData *data)
{
  cairo_t         *cr;
  GdkPixbuf       *pixbuf_to_draw; 
  cairo_surface_t *surface;
  guchar          *surface_pixels;
  guchar          *pixbuf_pixels;
  gint             stride;
  gint             pixbuf_stride;
  gint             pixbuf_n_channels;
  gdouble          cr_dpi_x;
  gdouble          cr_dpi_y;
  gdouble          scale_x;
  gdouble          scale_y;
  gint             y;

  cr = gtk_print_context_get_cairo_context(context);
  pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL,
                               GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)),
                               NULL, 0, 0, 0, 0, data->width, data->height);
  surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
                                       data->width, data->height);
  
  cr_dpi_x  = gtk_print_context_get_dpi_x  (context);
  cr_dpi_y  = gtk_print_context_get_dpi_y  (context);

  scale_x = cr_dpi_x / data->xres;
  scale_y = cr_dpi_y / data->yres;

  cairo_translate (cr,
                   data->offset_x / cr_dpi_x * 72.0,
                   data->offset_y / cr_dpi_y * 72.0);
  cairo_scale (cr, scale_x, scale_y);

  surface_pixels = cairo_image_surface_get_data (surface);
  stride = cairo_image_surface_get_stride (surface);
  pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw);
  pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw);
  pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw);

  // fprintf(stderr, "DEBUG: %s() surface_pixels=%p pixbuf_pixels=%p size=%d surface_width=%d surface_height=%d stride=%d data_height=%d pixmap_stride=%d pixmap_nchannels=%d pixmap_bit_per_Sample=%d\n", __PRETTY_FUNCTION__, surface_pixels, pixbuf_pixels, stride * data->height, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), stride, data->height, gdk_pixbuf_get_rowstride(pixbuf_to_draw), gdk_pixbuf_get_n_channels(pixbuf_to_draw), gdk_pixbuf_get_bits_per_sample(pixbuf_to_draw));

  /* Assume the pixbuf has 8 bits per channel */
  for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) {
    switch (pixbuf_n_channels) {
      case 3:
        copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width);
        break;
      case 4:
        copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width);
        break;
    }
  }

  g_object_unref(G_OBJECT(pixbuf_to_draw));

  cairo_set_source_surface(cr, surface, 0, 0);
  cairo_rectangle(cr, 0, 0, data->width, data->height);
  cairo_fill(cr);
  cairo_surface_destroy(surface);
}
Beispiel #9
0
TGUIFont *Alloc_GUIFont(const char *AFontName, float AHeight)
{
  TGUIFont *BFont = (TGUIFont *)malloc(sizeof(TGUIFont));
  BFont->FGridWidth = 0;
  BFont->FGridHeight = 0;
  BFont->FHeight = AHeight;
  BFont->FExtents = (TGUIFontExtent *)malloc(sizeof(TGUIFontExtent) * 256);
  TGUIFontExtent *BCharExtent = BFont->FExtents;
  cairo_text_extents_t *BExtents = (cairo_text_extents_t *)malloc(sizeof(cairo_text_extents_t));
  int BRow = 0;
  int BColumn = 0;
  GUIFont_GetGreaterSize(AFontName, AHeight, &BFont->FGridWidth, &BFont->FGridHeight);
  printf("[MESSAGE] Font grid of size (%i, %i).\n", BFont->FGridWidth, BFont->FGridHeight);
  BFont->FTextureWidth = Get_NextP2(BFont->FGridWidth * 16);
  BFont->FTextureHeight = Get_NextP2(BFont->FGridHeight * 16);
  printf("[MESSAGE] Font texture of size (%i, %i).\n", BFont->FTextureWidth, BFont->FTextureHeight);
  
  unsigned char *BData = NULL;
  unsigned char *BText = (unsigned char *)malloc(sizeof(unsigned char) * 2);
  BText[0] = 0;
  BText[1] = '\0';

  // Create texture data .
  cairo_surface_t *BSurface = cairo_image_surface_create(CAIRO_FORMAT_A8,
                                                         BFont->FTextureWidth,
                                                         BFont->FTextureHeight);
  cairo_t *BContext = cairo_create(BSurface);
  
  cairo_set_antialias(BContext, CAIRO_ANTIALIAS_NONE);
  cairo_set_operator(BContext, CAIRO_OPERATOR_OVER);
  cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 0.0);
  
  cairo_font_options_t *cfo = cairo_font_options_create();
  cairo_font_options_set_antialias(cfo, CAIRO_ANTIALIAS_SUBPIXEL);
  cairo_set_font_options(BContext, cfo);
  cairo_set_source_rgba(BContext, 0.0, 0.0, 0.0, 1.0);
  cairo_select_font_face(BContext, AFontName, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_font_size(BContext, AHeight);
  
  for (BText[0] = 0; BText[0] < 255; BText[0]++)
  {
    cairo_text_extents(BContext, BText, BExtents);
    if (BExtents)
    {
      BCharExtent->FAdvanceX = BExtents->x_advance;
      if (BText[0] == 32)
      {
        //BCharExtent->FAdvanceX = BFont->FGridWidth;
      };
      BCharExtent->FAdvanceY = BExtents->y_advance;
      BCharExtent->FBearingX = BExtents->x_bearing;
      BCharExtent->FBearingY = BExtents->y_bearing;
      BCharExtent->FWidth = BExtents->width;
      BCharExtent->FHeight = BExtents->height;
      BRow = BText[0] / 16;
      BColumn = BText[0] % 16;
      cairo_move_to(BContext, -BExtents->x_bearing + (BColumn * BFont->FGridWidth), -BExtents->y_bearing + (BRow * BFont->FGridHeight));
      cairo_show_text(BContext, BText);
    } else
    {
      printf("[MESSAGE] Fail to create font. Extents of char %i returned as null.\n", BText[0]);
      return NULL;
    };
    BCharExtent++;
  };
  cairo_surface_flush(BSurface);
  //cairo_surface_write_to_png(BSurface, "/home/felipefs/Desktop/texture.png");
  BData = cairo_image_surface_get_data(BSurface);
  glGenTextures(1, &BFont->FTexture);
  glBindTexture(GL_TEXTURE_2D, BFont->FTexture);
  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
  //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BFont->FTextureWidth, BFont->FTextureHeight,
               0, GL_ALPHA, GL_UNSIGNED_BYTE, BData);
  
  cairo_destroy(BContext);
  cairo_surface_destroy(BSurface);
  //free(BData);
  if (glIsTexture(BFont->FTexture) == GL_FALSE)
  {
    printf("[ERROR] Fail to create character texture of size %ix%i.\n", BFont->FTextureWidth, BFont->FTextureHeight);
  };
  printf("[MESSAGE] Font created.\n");
  return BFont;
};
Beispiel #10
0
bool
TextAsset::load()
{
    // Set up a temporary Cairo surface/context for text measurement
    cairo_surface_t* probeSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);

    if (cairo_surface_status(probeSurface) != CAIRO_STATUS_SUCCESS) {
        fprintf(stderr, "Could not create Cairo surface\n");
        _error = true;
        return false;
    }

    cairo_t* probeContext = cairo_create(probeSurface);
    if (cairo_status(probeContext) != CAIRO_STATUS_SUCCESS) {
        fprintf(stderr, "Could not create Cairo context\n");
        _error = true;
        return false;
    }

    // Text rectangle drawn within border
    const int idealWidth = _maxSize.width - _marginLeft - _marginRight;

    const Size textRegion(idealWidth, _maxSize.height - _marginTop - _marginBottom);
    const float fontSize = primaryFontSize(probeContext, textRegion);

    const std::string fontDesc = _fontName + " " + boost::lexical_cast<std::string>(fontSize);
    PangoFontDescription* fontDescription = pango_font_description_from_string(fontDesc.c_str());

    const std::string req_desc_str(pango_font_description_to_string(fontDescription));
    PangoFontMap* fontMap = pango_cairo_font_map_new_for_font_type(CAIRO_FONT_TYPE_FT);
    PangoContext* pango_context = pango_font_map_create_context(fontMap);

    // TODO: Does this need to be freed or does the context take it with it?
    PangoFont* pangoFont = pango_font_map_load_font(fontMap, pango_context, fontDescription);
    PangoFontDescription* reverseDescription = pango_font_describe(pangoFont);
    const std::string match_desc_str(pango_font_description_to_string(reverseDescription));
    pango_font_description_free(reverseDescription);
    g_object_unref(pango_context);

    if (req_desc_str.find(match_desc_str) == std::string::npos) {
        fprintf(stderr, "Warning: Unable to correctly match font \"%s\", using "
                "\"%s\" instead.\n", req_desc_str.c_str(), match_desc_str.c_str());
    }

    float shadowXOffset = 0;
    float shadowYOffset = 0;
    if (_dropShadow) {
        shadowXOffset = _dropShadowOffset.x() * CLIENT_TO_SERVER_SCALE * fontSize;
        shadowYOffset = _dropShadowOffset.y() * CLIENT_TO_SERVER_SCALE * fontSize;
    }

    Rect tight;
    const Size textSize = computeSizeOfText(probeContext, _textContent, idealWidth, fontDescription, &tight);
    const Size imageSize = imageSizeForTextSize(tight.size, shadowXOffset, shadowYOffset);

    // Tear down scratch contexts
    cairo_destroy(probeContext);
    cairo_surface_destroy(probeSurface);

    const int width = imageSize.width;
    const int height = imageSize.height;

    // Configure the actual Cairo drawing surface/context now that we know the final resolution
    cairo_surface_t* cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
    if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) {
        fprintf(stderr, "Could not create Cairo surface\n");
        _error = true;
        return false;
    }

    cairo_t* cairoContext = cairo_create(cairoSurface);

    // Flip the context like in the iOS version.
    // This fixes flipped filters associated with text assets.
    cairo_translate(cairoContext, 0.0, height);
    cairo_scale(cairoContext, 1.0, -1.0);

    if (cairo_status(cairoContext) != CAIRO_STATUS_SUCCESS) {
        fprintf(stderr, "Could not create Cairo context\n");
        _error = true;
        return false;
    }

    // Fill the box with the background color
    cairo_save(cairoContext);
    cairo_set_operator(cairoContext, CAIRO_OPERATOR_SOURCE);

    const mf::Color& bgColor(_style->getBackgroundColor());
    cairo_set_source_rgba(cairoContext, bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha);

    if (_shape == 0) {
        if (_cornerWidth > 0 && _cornerHeight > 0) {
            // TODO: Support independent corner width and height
            drawRoundedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _cornerWidth);
        } else {
            cairo_paint(cairoContext);
            if (_strokeThickness > 0.0f) {
                drawStrokedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness);
            }
        }
    } else if (_shape == 1) {
        strokeFillBezier(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness);
    }

    cairo_restore(cairoContext);

    const Rect textRect = textRectForTextSize(textSize, imageSize, tight);

    if (_dropShadow) {
        const Rect shadowRect(textRect.x + shadowXOffset,
                              textRect.y + shadowYOffset,
                              textRect.size.width,
                              textRect.size.height);
        cairo_set_source_rgba(cairoContext,
                              _dropShadowColor.red,
                              _dropShadowColor.green,
                              _dropShadowColor.blue,
                              _dropShadowColor.alpha);

        drawText(cairoContext, _textContent, shadowRect, fontDescription, false);
    }

    cairo_set_source_rgba(cairoContext, _textColor.red, _textColor.green, _textColor.blue, _textColor.alpha);

    if (_textColor.alpha > 0.0) {
        drawText(cairoContext, _textContent, textRect, fontDescription, true);
    }

    // DEBUG: Dump rendered text to an image
    // cairo_surface_write_to_png(cairoSurface, "text.png");

    // Transfer Cairo surface to OpenGL texture
    GLubyte* imageData = static_cast<GLubyte *>(cairo_image_surface_get_data(cairoSurface));

    glGenTextures(1, &_texture.textureID);
    glBindTexture(GL_TEXTURE_2D, _texture.textureID);

    _texture.width = width;
    _texture.height = height;
    _texture.s = 1.0;
    _texture.t = 1.0;
    _texture.aspect = static_cast<GLfloat>(_texture.width) / _texture.height;
    _texture.flipImage = true;

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

#ifdef GL_BGRA
    // Allocate and transfer data into texture (allow OpenGL swizzling)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData);
#else
    // Cairo uses a BGRA layout, OpenGL ES 2.0 does not support GL_BGRA as a
    // source format so manually perform swizzling.
    for (size_t i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) {
        std::swap(imageData[i], imageData[i + 2]);
    }

    // Allocate and transfer data into texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
#endif

    // Clean up
    pango_font_description_free(fontDescription);
    cairo_destroy(cairoContext);
    cairo_surface_destroy(cairoSurface);
    g_object_unref(pangoFont);

    _loading = false;
    _loaded = !_loading && !_error;

    return true;
}
Beispiel #11
0
/* Print text scale */
void RenderText() {
	int i = 0;
	cairo_surface_t *surface;
        cairo_t *cr;
	const unsigned char* surfaceData;

	if (viewType == TWO_D){
		xX = -0.1, yY = 0.05, zZ = 0;
		}
	else {
		xX = -0.02, yY = 0, zZ = 0;
		}
	
	glColor3f(1, 1, 1);
	
	for (i = 0 + (zoom * hzStep); i <= ((hzStep * bandsNumber *zoomFactor) + (zoom * hzStep)); i+= ((hzStep * bandsNumber * zoomFactor)/10)) {
			
		sprintf(textToRender, "%d", i);
		
		surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 32, 32);
		cr = cairo_create (surface);
		//cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL,  CAIRO_FONT_WEIGHT_BOLD);
		cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
		if (viewType == TWO_D){
			cairo_set_font_size (cr, 8.0);
			cairo_move_to (cr, 0, 12);
			}
		else {
			cairo_set_font_size (cr, 10.0);
			cairo_move_to (cr, 0, 18);
			}		
		cairo_show_text (cr, textToRender);
		cairo_surface_flush(surface);
		surfaceData = cairo_image_surface_get_data (surface);
	
		unsigned Texture = 0;

		glGenTextures(1, &Texture);
		glBindTexture(GL_TEXTURE_2D, Texture);

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), 0, GL_BGRA, GL_UNSIGNED_BYTE, surfaceData);
		
		glBegin(GL_QUADS);
		glColor4f(1, 1, 1, 1);
		glTexCoord2d(0, 0); glVertex3d(xX, yY, 0.01);
		glTexCoord2d(1, 0); glVertex3d(xX+0.1, yY, 0.01);
		glTexCoord2d(1, 1); glVertex3d(xX+0.1, yY-0.2, 0.01);
		glTexCoord2d(0, 1); glVertex3d(xX, yY-0.2, 0.01);
		glEnd();
		
		glDeleteTextures(1, &Texture);
		cairo_destroy (cr);
                cairo_surface_destroy (surface);
		
		if (viewType == TWO_D){
			yY += y_2d/10;
			}
		else {
			xX += x/10;
			}
	}
}
bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
{
    // This implementation is taken from GraphicsContext3DCairo.

    if (!m_image)
        return false;

    // We need this to stay in scope because the native image is just a shallow copy of the data.
    m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);

    if (!m_decoder)
        return false;

    ImageSource& decoder = *m_decoder;
    m_alphaOp = AlphaDoNothing;

    if (m_image->data()) {
        decoder.setData(m_image->data(), true);

        if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
            return false;

        m_imageSurface = decoder.createFrameAtIndex(0);
    } else {
        m_imageSurface = m_image->nativeImageForCurrentFrame();
        // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,
        // which is true at present and may be changed in the future and needs adjustment accordingly.
        // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
        // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
        if (!premultiplyAlpha && m_imageHtmlDomSource != HtmlDomVideo)
            m_alphaOp = AlphaDoUnmultiply;
    }

    if (!m_imageSurface)
        return false;

    m_imageWidth = cairo_image_surface_get_width(m_imageSurface.get());
    m_imageHeight = cairo_image_surface_get_height(m_imageSurface.get());

    if (!m_imageWidth || !m_imageHeight)
        return false;

    if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32)
        return false;

    uint srcUnpackAlignment = 1;
    size_t bytesPerRow = cairo_image_surface_get_stride(m_imageSurface.get());
    size_t bitsPerPixel = 32;
    unsigned padding = bytesPerRow - bitsPerPixel / 8 * m_imageWidth;

    if (padding) {
        srcUnpackAlignment = padding + 1;
        while (bytesPerRow % srcUnpackAlignment)
            ++srcUnpackAlignment;
    }

    m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get());
    m_imageSourceFormat = DataFormatBGRA8;
    m_imageSourceUnpackAlignment = srcUnpackAlignment;

    return true;
}
Beispiel #13
0
static gboolean
gimp_color_bar_expose (GtkWidget      *widget,
                       GdkEventExpose *event)
{
  GimpColorBar    *bar = GIMP_COLOR_BAR (widget);
  cairo_t         *cr;
  GtkAllocation    allocation;
  cairo_surface_t *surface;
  cairo_pattern_t *pattern;
  guchar          *src;
  guchar          *dest;
  gint             x, y;
  gint             width, height;
  gint             i;

  cr = gdk_cairo_create (event->window);

  gdk_cairo_region (cr, event->region);
  cairo_clip (cr);

  gtk_widget_get_allocation (widget, &allocation);

  x = y = gtk_container_get_border_width (GTK_CONTAINER (bar));

  width  = allocation.width  - 2 * x;
  height = allocation.height - 2 * y;

  if (width < 1 || height < 1)
    return TRUE;

  cairo_translate (cr, allocation.x + x, allocation.y + y);
  cairo_rectangle (cr, 0, 0, width, height);
  cairo_clip (cr);

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1);

  for (i = 0, src = bar->buf, dest = cairo_image_surface_get_data (surface);
       i < 256;
       i++, src += 3, dest += 4)
    {
      GIMP_CAIRO_RGB24_SET_PIXEL(dest, src[0], src[1], src[2]);
    }

  cairo_surface_mark_dirty (surface);

  pattern = cairo_pattern_create_for_surface (surface);
  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
  cairo_surface_destroy (surface);

  if (bar->orientation == GTK_ORIENTATION_HORIZONTAL)
    {
      cairo_scale (cr, (gdouble) width / 256.0, 1.0);
    }
  else
    {
      cairo_translate (cr, 0, height);
      cairo_scale (cr, 1.0, (gdouble) height / 256.0);
      cairo_rotate (cr, - G_PI / 2);
    }

  cairo_set_source (cr, pattern);
  cairo_pattern_destroy (pattern);

  cairo_paint (cr);

  cairo_destroy (cr);

  return TRUE;
}
Beispiel #14
0
static const char *
write_ppm (cairo_surface_t *surface, int fd)
{
    char buf[4096];
    cairo_format_t format;
    const char *format_str;
    const unsigned char *data;
    int len;
    int width, height, stride;
    int i, j;

    data = cairo_image_surface_get_data (surface);
    height = cairo_image_surface_get_height (surface);
    width = cairo_image_surface_get_width (surface);
    stride = cairo_image_surface_get_stride (surface);
    format = cairo_image_surface_get_format (surface);
    if (format == CAIRO_FORMAT_ARGB32) {
	/* see if we can convert to a standard ppm type and trim a few bytes */
	const unsigned char *alpha = data;
	for (j = height; j--; alpha += stride) {
	    for (i = 0; i < width; i++) {
		if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000)
		    goto done;
	    }
	}
	format = CAIRO_FORMAT_RGB24;
 done: ;
    }

    switch (format) {
    case CAIRO_FORMAT_ARGB32:
	/* XXX need true alpha for svg */
	format_str = "P7";
	break;
    case CAIRO_FORMAT_RGB24:
	format_str = "P6";
	break;
    case CAIRO_FORMAT_A8:
	format_str = "P5";
	break;
    case CAIRO_FORMAT_A1:
    case CAIRO_FORMAT_RGB16_565:
    case CAIRO_FORMAT_RGB30:
    case CAIRO_FORMAT_INVALID:
    default:
	return "unhandled image format";
    }

    len = sprintf (buf, "%s %d %d 255\n", format_str, width, height);
    for (j = 0; j < height; j++) {
	const unsigned int *row = (unsigned int *) (data + stride * j);

	switch ((int) format) {
	case CAIRO_FORMAT_ARGB32:
	    len = _cairo_write (fd,
			  buf, sizeof (buf), len,
			  (unsigned char *) row, 4 * width);
	    break;
	case CAIRO_FORMAT_RGB24:
	    for (i = 0; i < width; i++) {
		unsigned char rgb[3];
		unsigned int p = *row++;
		rgb[0] = (p & 0xff0000) >> 16;
		rgb[1] = (p & 0x00ff00) >> 8;
		rgb[2] = (p & 0x0000ff) >> 0;
		len = _cairo_write (fd,
			      buf, sizeof (buf), len,
			      rgb, 3);
	    }
	    break;
	case CAIRO_FORMAT_A8:
	    len = _cairo_write (fd,
			  buf, sizeof (buf), len,
			  (unsigned char *) row, width);
	    break;
	}
	if (len < 0)
	    return "write failed";
    }

    if (len && ! _cairo_writen (fd, buf, len))
	return "write failed";

    return NULL;
}
Beispiel #15
0
static bool_t to_ninepatch(cairo_surface_t * surface, struct lninepatch_t * patch)
{
	cairo_surface_t * cs;
	cairo_t * cr;
	unsigned char * data;
	int width, height;
	int stride;
	int w, h;
	int i;

	if(!surface || !patch)
		return FALSE;

	width = cairo_image_surface_get_width(surface);
	height = cairo_image_surface_get_height(surface);
	if(width < 3 || height < 3)
		return FALSE;

	/* Nine patch chunk */
	cs = cairo_surface_create_similar_image(surface, CAIRO_FORMAT_ARGB32, width, height);
	cr = cairo_create(cs);
	cairo_set_source_surface(cr, surface, 0, 0);
	cairo_paint(cr);
	cairo_destroy(cr);
	data = cairo_image_surface_get_data(cs);
	stride = cairo_image_surface_get_stride(cs);

	/* Nine patch default size */
	width = width - 2;
	height = height - 2;
	patch->width = width;
	patch->height = height;

	/* Stretch information */
	patch->left = 0;
	patch->right = 0;
	patch->top = 0;
	patch->right = 0;

	for(i = 0; i < width; i++)
	{
		if(detect_black_pixel(&data[(i + 1) * 4]))
		{
			patch->left = i;
			break;
		}
	}
	for(i = width - 1; i >= 0; i--)
	{
		if(detect_black_pixel(&data[(i + 1) * 4]))
		{
			patch->right = width - 1 - i;
			break;
		}
	}
	for(i = 0; i < height; i++)
	{
		if(detect_black_pixel(&data[stride * (i + 1)]))
		{
			patch->top = i;
			break;
		}
	}
	for(i = height - 1; i >= 0; i--)
	{
		if(detect_black_pixel(&data[stride * (i + 1)]))
		{
			patch->bottom = height - 1 - i;
			break;
		}
	}
	cairo_surface_destroy(cs);

	/* Left top */
	w = patch->left;
	h = patch->top;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), patch->left, patch->top);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -1, -1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->lt = cs;
	}
	else
	{
		patch->lt = NULL;
	}

	/* Middle top */
	w = width - patch->left - patch->right;
	h = patch->top;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -patch->left - 1, -1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->mt = cs;
	}
	else
	{
		patch->mt = NULL;
	}

	/* Right top */
	w = patch->right;
	h = patch->top;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->rt = cs;
	}
	else
	{
		patch->rt = NULL;
	}

	/* Left Middle */
	w = patch->left;
	h = height - patch->top - patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -1, -patch->top - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->lm = cs;
	}
	else
	{
		patch->lm = NULL;
	}

	/* Middle Middle */
	w = width - patch->left - patch->right;
	h = height - patch->top - patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -patch->left - 1, -patch->top - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->mm = cs;
	}
	else
	{
		patch->mm = NULL;
	}

	/* Right middle */
	w = patch->right;
	h = height - patch->top - patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -patch->top - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->rm = cs;
	}
	else
	{
		patch->rm = NULL;
	}

	/* Left bottom */
	w = patch->left;
	h = patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -1, -(height - patch->bottom) - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->lb = cs;
	}
	else
	{
		patch->lb = NULL;
	}

	/* Middle bottom */
	w = width - patch->left - patch->right;
	h = patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -patch->left - 1, -(height - patch->bottom) - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->mb = cs;
	}
	else
	{
		patch->mb = NULL;
	}

	/* Right bottom */
	w = patch->right;
	h = patch->bottom;
	if(w > 0 && h > 0)
	{
		cs = cairo_surface_create_similar(surface, cairo_surface_get_content(surface), w, h);
		cr = cairo_create(cs);
		cairo_set_source_surface(cr, surface, -(width - patch->right) - 1, -(height - patch->bottom) - 1);
		cairo_paint(cr);
		cairo_destroy(cr);
		patch->rb = cs;
	}
	else
	{
		patch->rb = NULL;
	}

	ninepatch_stretch(patch, width, height);
	return TRUE;
}
Beispiel #16
0
static double find_signed_distance(
	int              px,
	int              py,
	cairo_surface_t* surface,
	int              scan_width,
	int              scan_height
) {
	int            width         = cairo_image_surface_get_width(surface);
	unsigned char* data          = cairo_image_surface_get_data(surface);
	unsigned char  base          = data[(px * width) + py];
	int            base_solid    = base > 0;
	double         closest       = MAX_VALUE;
	int            closest_valid = 0;
	int            start_x       = px - (scan_width / 2);
	int            end_x         = start_x + scan_width;
	int            start_y       = py - (scan_height / 2);
	int            end_y         = start_y + scan_height;

	int x;
	int y;

	for(x = start_x; x < end_x; x++) {
		if(x < 0 || x >= width) continue;

		for(y = start_y; y < end_y; y++) {
			unsigned char c;

			if(y < 0 || y >= width) continue;

			c = data[(x * width) + y];

			if(base_solid) {
				if(c == 0) {
					double dist = separation(px, py, x, y);

					if (dist < closest) {
						closest       = dist;
						closest_valid = 1;
					}
				}
			}

			else {
				if(c > 0) {
					double dist = separation(px, py, x, y);

					if(dist < closest) {
						closest       = dist;
						closest_valid = 1;
					}
				}
			}
		}
	}

	if(base_solid) {
		if(closest_valid) return closest;

		else return MAX_VALUE;
	}

	else {
		if(closest_valid) return -closest;

		else return MIN_VALUE;
	}
}
void TileEngine::renderPixels(
    cairo_surface_t *destSurf,
    cairo_surface_t *cmapSurf,
    PyObject *tileFunction,
    PyObject *tileMap,
    int renderCol,
    int renderRow,
    int renderCols,
    int renderRows)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	return;
    }

    // The tileMap should be None, or an array of 4 byte integers,
    // mapping virtual tiles indices to absolute tile numbers.

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

        if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    return;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    return;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	  PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileMap read buffer of 4 byte integers");
	  return;
	}
    }

    unsigned char *destData = cairo_image_surface_get_data(destSurf);
    int destStride = cairo_image_surface_get_stride(destSurf);

    unsigned char *cmapData = cairo_image_surface_get_data(cmapSurf);
    int cmapWidth = cairo_image_surface_get_width(cmapSurf);
    int cmapStride = cairo_image_surface_get_stride(cmapSurf);

    int r;
    for (r = 0; r < renderRows; r++) {
	int c;
	for (c = 0; c  < renderCols; c++) {
	    int col = (renderCol + c) % width;
	    int row = (renderRow + r) % height;

	    unsigned long tile = 
		getValue(
		    col,
		    row,
		    tileFunction,
		    tileMapData,
		    tileMapCount);

	    int sourceX = tile % cmapWidth;
	    int sourceY = tile / cmapWidth;

	    unsigned char *sourcePixel =
		cmapData +
		(sourceX * 4) +
		(sourceY * cmapStride);

	    unsigned char *destPixel =
		destData +
		(c * 4) +
		(r * destStride);

	    *(long *)destPixel = *(long *)sourcePixel;
	}
    }
}
static void pango_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, boolean filled)
{
    cairo_surface_t *surface; 	/* source surface */
    cairo_format_t format;
    int X, Y, x, y, stride;
    unsigned char *data, *ix, alpha, red, green, blue;

    surface = cairo_loadimage(job, us);
    if (surface) {
       	format = cairo_image_surface_get_format(surface);
        if ((format != CAIRO_FORMAT_ARGB32) && (format != CAIRO_FORMAT_RGB24))
	    return;

	X = cairo_image_surface_get_width(surface);
	Y = cairo_image_surface_get_height(surface);
	stride = cairo_image_surface_get_stride(surface);
	data = cairo_image_surface_get_data(surface);

        gvputs(job, "save\n");

	/* define image data as string array (one per raster line) */
	/* see parallel code in gd_loadimage_ps().  FIXME: refactor... */
        gvputs(job, "/myctr 0 def\n");
        gvputs(job, "/myarray [\n");
        for (y = 0; y < Y; y++) {
	    gvputs(job, "<");
	    ix = data + y * stride;
            for (x = 0; x < X; x++) {
		/* FIXME - this code may have endian problems */
		blue = *ix++;
		green = *ix++;
		red = *ix++;
		alpha = *ix++;
		if (alpha < 0x7f)
		    gvputs(job, "ffffff");
		else
                    gvprintf(job, "%02x%02x%02x", red, green, blue);
            }
	    gvputs(job, ">\n");
        }
	gvputs(job, "] def\n");
        gvputs(job,"/myproc { myarray myctr get /myctr myctr 1 add def } def\n");

        /* this sets the position of the image */
        gvprintf(job, "%g %g translate\n",
		(b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.),
		(b.LL.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.));

        /* this sets the rendered size to fit the box */
        gvprintf(job,"%g %g scale\n",
		((b.UR.x - b.LL.x) * 72. / 96.),
		((b.UR.y - b.LL.y) * 72. / 96.));

        /* xsize ysize bits-per-sample [matrix] */
        gvprintf(job, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);

        gvputs(job, "{myproc} false 3 colorimage\n");

        gvputs(job, "restore\n");
    }
}
Beispiel #19
0
static void
byzanz_encoder_gstreamer_need_data (GstAppSrc *src, guint length, gpointer data)
{
  ByzanzEncoder *encoder = data;
  ByzanzEncoderGStreamer *gst = data;
  GstBuffer *buffer;
  cairo_t *cr;
  cairo_surface_t *surface;
  cairo_region_t *region;
  GError *error = NULL;
  guint64 msecs;
  int i, num_rects;

  if (!byzanz_deserialize (encoder->input_stream, &msecs, &surface, &region, encoder->cancellable, &error)) {
    gst_element_message_full (GST_ELEMENT (src), GST_MESSAGE_ERROR,
        error->domain, error->code, g_strdup (error->message), NULL, __FILE__, GST_FUNCTION, __LINE__);
    g_error_free (error);
    return;
  }

  if (surface == NULL) {
    gst_app_src_end_of_stream (gst->src);
    if (gst->audiosrc)
      gst_element_send_event (gst->audiosrc, gst_event_new_eos ());
    return;
  }

  if (cairo_surface_get_reference_count (gst->surface) > 1) {
    cairo_surface_t *copy = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
        cairo_image_surface_get_width (gst->surface), cairo_image_surface_get_height (gst->surface));
    
    cr = cairo_create (copy);
    cairo_set_source_surface (cr, gst->surface, 0, 0);
    cairo_paint (cr);
    cairo_destroy (cr);

    cairo_surface_destroy (gst->surface);
    gst->surface = copy;
  }
  cr = cairo_create (gst->surface);
  cairo_set_source_surface (cr, surface, 0, 0);

  num_rects = cairo_region_num_rectangles (region);
  for (i = 0; i < num_rects; i++) {
    cairo_rectangle_int_t rect;
    cairo_region_get_rectangle (region, i, &rect);
    cairo_rectangle (cr, rect.x, rect.y,
                     rect.width, rect.height);
  }

  cairo_fill (cr);
  cairo_destroy (cr);

  /* create a buffer and send it */
  /* FIXME: stride just works? */
  cairo_surface_reference (gst->surface);
  buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
                                        cairo_image_surface_get_data (gst->surface),
                                        cairo_image_surface_get_stride (gst->surface) * cairo_image_surface_get_height (gst->surface),
                                        0,
                                        cairo_image_surface_get_stride (gst->surface) * cairo_image_surface_get_height (gst->surface),
                                        gst->surface,
                                        (GDestroyNotify) cairo_surface_destroy);
  GST_BUFFER_TIMESTAMP (buffer) = msecs * GST_MSECOND;
  gst_app_src_push_buffer (gst->src, buffer);
}
Beispiel #20
0
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte,
	long ix1, long ix2, long x1DC, long x2DC,
	long iy1, long iy2, long y1DC, long y2DC,
	double minimum, double maximum,
	long clipx1, long clipx2, long clipy1, long clipy2, int interpolate)
{
	/*long t=clock();*/
	long nx = ix2 - ix1 + 1;   /* The number of cells along the horizontal axis. */
	long ny = iy2 - iy1 + 1;   /* The number of cells along the vertical axis. */
	double dx = (double) (x2DC - x1DC) / (double) nx;   /* Horizontal pixels per cell. Positive. */
	double dy = (double) (y2DC - y1DC) / (double) ny;   /* Vertical pixels per cell. Negative. */
	double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale;
	if (x2DC <= x1DC || y1DC <= y2DC) return;
	trace ("scale %f", scale);
	/* Clip by the intersection of the world window and the outline of the cells. */
	//Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2);
	if (clipx1 < x1DC) clipx1 = x1DC;
	if (clipx2 > x2DC) clipx2 = x2DC;
	if (clipy1 > y1DC) clipy1 = y1DC;
	if (clipy2 < y2DC) clipy2 = y2DC;
	/*
	 * The first decision is whether we are going to use the standard rectangle drawing
	 * (cellArray only), or whether we are going to write into a bitmap.
	 * The standard drawing is best for small numbers of cells,
	 * provided that some cells are larger than a pixel.
	 */
	if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) {
		try {
			/*unsigned int cellWidth = (unsigned int) dx + 1;*/
			unsigned int cellHeight = (unsigned int) (- (int) dy) + 1;
			long ix, iy;
			#if cairo
				cairo_pattern_t *grey [256];
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) {
					double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0);
					grey [igrey] = cairo_pattern_create_rgb (v, v, v);
				}
			#elif win
				static HBRUSH greyBrush [256];
				RECT rect;
				if (! greyBrush [0])
					for (int igrey = 0; igrey <= 255; igrey ++)
						greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey));   // once
			#elif mac
				GraphicsQuartz_initDraw (me);
				CGContextSetAlpha (my d_macGraphicsContext, 1.0);
				CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal);
			#endif
			autoNUMvector <long> lefts (ix1, ix2 + 1);
			for (ix = ix1; ix <= ix2 + 1; ix ++)
				lefts [ix] = x1DC + (long) ((ix - ix1) * dx);
			for (iy = iy1; iy <= iy2; iy ++) {
				long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight;
				if (top > clipy1 || bottom < clipy2) continue;
				if (top < clipy2) top = clipy2;
				if (bottom > clipy1) bottom = clipy1;
				#if win
					rect. bottom = bottom; rect. top = top;
				#endif
				for (ix = ix1; ix <= ix2; ix ++) {
					long left = lefts [ix], right = lefts [ix + 1];
					if (right < clipx1 || left > clipx2) continue;
					if (left < clipx1) left = clipx1;
					if (right > clipx2) right = clipx2;
					if (z_rgbt) {
						#if cairo
							// NYI
						#elif win
							// NYI
						#elif mac
							double red          = z_rgbt [iy] [ix]. red;
							double green        = z_rgbt [iy] [ix]. green;
							double blue         = z_rgbt [iy] [ix]. blue;
							double transparency = z_rgbt [iy] [ix]. transparency;
							red =   ( red   <= 0.0 ? 0.0 : red   >= 1.0 ? 1.0 : red   );
							green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green );
							blue =  ( blue  <= 0.0 ? 0.0 : blue  >= 1.0 ? 1.0 : blue  );
							CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					} else {
						#if cairo
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]);
							cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top);
							cairo_fill (my d_cairoGraphicsContext);
						#elif win
							long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							rect. left = left; rect. right = right;
							FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]);
						#elif mac
							double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] );
							double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0;
							CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0);
							CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top));
						#endif
					}
				}
			}
			
			#if cairo
				for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++)
					cairo_pattern_destroy (grey [igrey]);
			#elif mac
				CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0);
				GraphicsQuartz_exitDraw (me);
			#endif
		} catch (MelderError) { }
	} else {
		long xDC, yDC;
		long undersampling = 1;
		/*
		 * Prepare for off-screen bitmap drawing.
		 */
		#if cairo
			long arrayWidth = clipx2 - clipx1;
			long arrayHeight = clipy1 - clipy2;
			trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight);
			cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight);
			unsigned char *bits = cairo_image_surface_get_data (sfc);
			int scanLineLength = cairo_image_surface_get_stride (sfc);
			unsigned char grey [256];
			trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey));
			for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++)
				grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1));
		#elif win
			long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2;
			int igrey;
			/*
			 * Create a device-independent bitmap, 32 bits deep.
			 */
			struct { BITMAPINFOHEADER header; } bitmapInfo;
			long scanLineLength = bitmapWidth * 4;   // for 24 bits: (bitmapWidth * 3 + 3) & ~3L;
			HBITMAP bitmap;
			unsigned char *bits;   // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection ()
			bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER);
			bitmapInfo. header.biWidth = bitmapWidth;   // scanLineLength;
			bitmapInfo. header.biHeight = bitmapHeight;
			bitmapInfo. header.biPlanes = 1;
			bitmapInfo. header.biBitCount = 32;
			bitmapInfo. header.biCompression = 0;
			bitmapInfo. header.biSizeImage = 0;
			bitmapInfo. header.biXPelsPerMeter = 0;
			bitmapInfo. header.biYPelsPerMeter = 0;
			bitmapInfo. header.biClrUsed = 0;
			bitmapInfo. header.biClrImportant = 0;
			bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo,
				DIB_RGB_COLORS, (VOID **) & bits, NULL, 0);
		#elif mac
			long bytesPerRow = (clipx2 - clipx1) * 4;
			Melder_assert (bytesPerRow > 0);
			long numberOfRows = clipy1 - clipy2;
			Melder_assert (numberOfRows > 0);
			unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows);
		#endif
		/*
		 * Draw into the bitmap.
		 */
		#if cairo
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif win
			#define ROW_START_ADDRESS  (bits + (clipy1 - 1 - yDC) * scanLineLength)
			#define PUT_PIXEL \
				if (1) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				}
		#elif mac
			#define ROW_START_ADDRESS  (imageData + (clipy1 - 1 - yDC) * bytesPerRow)
			#define PUT_PIXEL \
				if (my colourScale == kGraphics_colourScale_GREY) { \
					unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = kar; \
					*pixelAddress ++ = 0; \
				} else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \
					if (value < 0.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
					} else if (value < 64.0) { \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = (int) (value * 3 + 63.999); \
						*pixelAddress ++ = 0; \
					} else if (value < 128.0) { \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = (int) (value * 4 - 256.0); \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = 0; \
					} else if (value < 192.0) { \
						*pixelAddress ++ = 255; \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \
						*pixelAddress ++ = 0; \
					} else if (value < 256.0) { \
						*pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} else { \
						*pixelAddress ++ = 63; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
						*pixelAddress ++ = 0; \
					} \
				}
		#else
			#define ROW_START_ADDRESS  NULL
			#define PUT_PIXEL
		#endif
		if (interpolate) {
			try {
				autoNUMvector <long> ileft (clipx1, clipx2);
				autoNUMvector <long> iright (clipx1, clipx2);
				autoNUMvector <double> rightWeight (clipx1, clipx2);
				autoNUMvector <double> leftWeight (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
					double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC);
					ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1;
					rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC];
					if (ileft [xDC] < ix1) ileft [xDC] = ix1;
					if (iright [xDC] > ix2) iright [xDC] = ix2;
				}
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC);
					long itop = ceil (iy_real), ibottom = itop - 1;
					double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight;
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					if (itop > iy2) itop = iy2;
					if (ibottom < iy1) ibottom = iy1;
					if (z_float) {
						double *ztop = z_float [itop], *zbottom = z_float [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					} else if (z_rgbt) {
						double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double red =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. red + bottomWeight * zbottom [ileft  [xDC]]. red);
							double green =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. green + bottomWeight * zbottom [ileft  [xDC]]. green);
							double blue =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. blue + bottomWeight * zbottom [ileft  [xDC]]. blue);
							double transparency =
								rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) +
								leftWeight  [xDC] * (topWeight * ztop [ileft  [xDC]]. transparency + bottomWeight * zbottom [ileft  [xDC]]. transparency);
							if (red          < 0.0) red          = 0.0; else if (red          > 1.0) red          = 1.0;
							if (green        < 0.0) green        = 0.0; else if (green        > 1.0) green        = 1.0;
							if (blue         < 0.0) blue         = 0.0; else if (blue         > 1.0) blue         = 1.0;
							if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0;
							#if win
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = 0;
							#elif mac
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#elif cairo
								*pixelAddress ++ = blue         * 255.0;
								*pixelAddress ++ = green        * 255.0;
								*pixelAddress ++ = red          * 255.0;
								*pixelAddress ++ = transparency * 255.0;
							#endif
						}
					} else {
						unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double interpol =
								rightWeight [xDC] *
									(topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) +
								leftWeight [xDC] *
									(topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]);
							double value = offset - scale * interpol;
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		} else {
			try {
				autoNUMvector <long> ix (clipx1, clipx2);
				for (xDC = clipx1; xDC < clipx2; xDC += undersampling)
					ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC));
				for (yDC = clipy2; yDC < clipy1; yDC += undersampling) {
					long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC));
					unsigned char *pixelAddress = ROW_START_ADDRESS;
					Melder_assert (iy >= iy1 && iy <= iy2);
					if (z_float) {
						double *ziy = z_float [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					} else {
						unsigned char *ziy = z_byte [iy];
						for (xDC = clipx1; xDC < clipx2; xDC += undersampling) {
							double value = offset - scale * ziy [ix [xDC]];
							PUT_PIXEL
						}
					}
				}
			} catch (MelderError) { Melder_clearError (); }
		}
		/*
		 * Copy the bitmap to the screen.
		 */
		#if cairo
			cairo_matrix_t clip_trans;
			cairo_matrix_init_identity (& clip_trans);
			cairo_matrix_scale (& clip_trans, 1, -1);		// we painted in the reverse y-direction
			cairo_matrix_translate (& clip_trans, - clipx1, - clipy1);
			cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc);
			trace ("bitmap pattern %p", bitmap_pattern);
			if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) {
				Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status));
			} else {
				cairo_pattern_set_matrix (bitmap_pattern, & clip_trans);
				cairo_save (my d_cairoGraphicsContext);
				cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern);
				cairo_paint (my d_cairoGraphicsContext);
				cairo_restore (my d_cairoGraphicsContext);
			}
			cairo_pattern_destroy (bitmap_pattern);
		#elif win
			SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
				bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS);
			//StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight,
			//	bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
		#elif mac
			CGImageRef image;
			static CGColorSpaceRef colourSpace = NULL;
			if (colourSpace == NULL) {
				colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);   // used to be kCGColorSpaceUserRGB
				Melder_assert (colourSpace != NULL);
			}
			if (1) {
				CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL,
					imageData,
					bytesPerRow * numberOfRows,
					_mac_releaseDataCallback   // we need this because we cannot release the image data immediately after drawing,
						// because in PDF files the imageData has to stay available through EndPage
				);
				Melder_assert (dataProvider != NULL);
				image = CGImageCreate (clipx2 - clipx1, numberOfRows,
					8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault);
				CGDataProviderRelease (dataProvider);
			} else if (0) {
				Melder_assert (CGBitmapContextCreate != NULL);
				CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100,
					8, 800, colourSpace, 0);
				Melder_assert (bitmaptest != NULL);
				CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows,
					8, bytesPerRow, colourSpace, kCGImageAlphaLast);
				Melder_assert (bitmap != NULL);
				image = CGBitmapContextCreateImage (bitmap);
				// release bitmap?
			}
			Melder_assert (image != NULL);
			GraphicsQuartz_initDraw (me);
			CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image);
			GraphicsQuartz_exitDraw (me);
			//CGColorSpaceRelease (colourSpace);
			CGImageRelease (image);
		#endif
		/*
		 * Clean up.
		 */
		#if cairo
			cairo_surface_destroy (sfc);
		#elif win
			DeleteBitmap (bitmap);
		#endif
	}
Beispiel #21
0
cairo_surface_t *
cairo_boilerplate_image_surface_create_from_ppm_stream (FILE *file)
{
    char format;
    int width, height, stride;
    int x, y;
    unsigned char *data;
    cairo_surface_t *image = NULL;

    if (fscanf (file, "P%c %d %d 255\n", &format, &width, &height) != 3)
	goto FAIL;

    switch (format) {
    case '7': /* XXX */
	image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
	break;
    case '6':
	image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
	break;
    case '5':
	image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
	break;
    default:
	goto FAIL;
    }
    if (cairo_surface_status (image))
	return image;

    data = cairo_image_surface_get_data (image);
    stride = cairo_image_surface_get_stride (image);
    for (y = 0; y < height; y++) {
	unsigned char *buf = data + y*stride;
	switch (format) {
	case '7':
	    if (! freadn (buf, 4 * width, file))
		goto FAIL;
	    break;
	case '6':
	    if (! freadn (buf, 3*width, file))
		goto FAIL;
	    buf += 3*width;
	    for (x = width; x--; ) {
		buf -= 3;
		((uint32_t *) (data + y*stride))[x] =
		    (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
	    }
	    break;
	case '5':
	    if (! freadn (buf, width, file))
		goto FAIL;
	    break;
	}
    }
    cairo_surface_mark_dirty (image);

    return image;

FAIL:
    cairo_surface_destroy (image);
    return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
}
Beispiel #22
0
GtkWidget *CreateImageButton(
	const char* image_file_path,
	const gchar* label,
	const char* font_file
)
{
#define DISPLAY_FONT_HEIGHT 8.5
	// 貼り付けるイメージ
	cairo_surface_t *image =
		cairo_image_surface_create_from_png(image_file_path);
	// 文字描画用
	cairo_t *cairo_p = cairo_create(image);
	// 画像のフォーマット
	cairo_format_t format = cairo_image_surface_get_format(image);
	// 画像の幅と高さ
	int32 width = cairo_image_surface_get_width(image);
	int32 height = cairo_image_surface_get_height(image);
	// 画像の一列分のバイト数
	int32 stride = width * ((format == CAIRO_FORMAT_ARGB32) ? 4 : 3);
	// 文字表示のY座標
	gdouble draw_y = 9.0;
	GtkWidget *image_widget;
	// ピクセルバッファ
	GdkPixbuf *pixbuf;
	// 返り値
	GtkWidget *button;
	// 改行処理用のバッファ
	gchar* str = (label == NULL) ? NULL : MEM_STRDUP_FUNC(label);
	gchar* show_text = str;
	// 改行処理用
	gchar *now, *next;

	// 文字列を描画
	if(label != NULL && *label != '\0')
	{
		// フォントサイズセット
		cairo_select_font_face(cairo_p, font_file, CAIRO_FONT_SLANT_NORMAL,
			CAIRO_FONT_WEIGHT_NORMAL);
		cairo_set_font_size(cairo_p, DISPLAY_FONT_HEIGHT);

		// 改行を処理しながら表示
		now = show_text = str;
		next = g_utf8_next_char(show_text);
		while(*now != '\0' && *next != '\0')
		{
			if((uint8)*now == 0x5c && *next == 'n')
			{
				*now = '\0';
				cairo_move_to(cairo_p, 0.0, draw_y);
				cairo_show_text(cairo_p, show_text);
				show_text = now = g_utf8_next_char(next);
				next = g_utf8_next_char(now);
				draw_y += DISPLAY_FONT_HEIGHT;
			}
			else if((next - now) >= 2 && (uint8)*now == 0xc2
				&& (uint8)(*(now+1)) == 0xa5 && (uint8)*next == 'n')
			{
				*now = '\0';
				cairo_move_to(cairo_p, 0.0, draw_y);
				cairo_show_text(cairo_p, show_text);
				show_text = now = g_utf8_next_char(next);
				next = g_utf8_next_char(now);
				draw_y += DISPLAY_FONT_HEIGHT;
			}
			else
			{
				now = next;
				next = g_utf8_next_char(next);
			}
		}
		cairo_move_to(cairo_p, 0.0, draw_y);
		cairo_show_text(cairo_p, show_text);
	}

	// イメージからピクセルバッファを生成
	pixbuf = gdk_pixbuf_new_from_data(
		cairo_image_surface_get_data(image),
		GDK_COLORSPACE_RGB,
		(format == CAIRO_FORMAT_ARGB32) ? TRUE : FALSE,
		8,
		width,
		height,
		stride,
		NULL,
		NULL
	);

#if defined(USE_BGR_COLOR_SPACE) && USE_BGR_COLOR_SPACE != 0
	{
		// WindowsならばBGR→RGBの変換を行う
		uint8* pix = cairo_image_surface_get_data(image);
		uint8 b;
		int32 channel = (format == CAIRO_FORMAT_ARGB32) ? 4 : 3;
		int32 i, j;

		for(i=0; i<height; i++)
		{
			for(j=0; j<width; j++)
			{
				b = pix[i*stride+j*channel];
				pix[i*stride+j*channel] = pix[i*stride+j*channel+2];
				pix[i*stride+j*channel+2] = b;
			}
		}
	}
#endif	// #if defined(DISPLAY_BGR) && DISPLAY_BGR != 0

	image_widget = gtk_image_new_from_pixbuf(pixbuf);

	button = gtk_toggle_button_new();

	// ボタンにイメージデータを載せる
	gtk_container_add(GTK_CONTAINER(button), image_widget);

	cairo_destroy(cairo_p);

	MEM_FREE_FUNC(str);

	return button;
}
Beispiel #23
0
/* Compares two CAIRO_FORMAT_ARGB32 buffers, returning NULL if the
 * buffers are equal or a surface containing a diff between the two
 * surfaces.
 *
 * This function should be rewritten to compare all formats supported by
 * cairo_format_t instead of taking a mask as a parameter.
 *
 * This function is originally from cairo:test/buffer-diff.c.
 * Copyright © 2004 Richard D. Worth
 */
static cairo_surface_t *
buffer_diff_core (const guchar *buf_a,
                  int           stride_a,
		  const guchar *buf_b,
                  int           stride_b,
		  int		width,
		  int		height)
{
  int x, y;
  guchar *buf_diff = NULL;
  int stride_diff = 0;
  cairo_surface_t *diff = NULL;

  for (y = 0; y < height; y++)
    {
      const guint32 *row_a = (const guint32 *) (buf_a + y * stride_a);
      const guint32 *row_b = (const guint32 *) (buf_b + y * stride_b);
      guint32 *row = (guint32 *) (buf_diff + y * stride_diff);

      for (x = 0; x < width; x++)
        {
          int channel;
          guint32 diff_pixel = 0;

          /* check if the pixels are the same */
          if (row_a[x] == row_b[x])
            continue;
        
          if (diff == NULL)
            {
              diff = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
                                                 width,
                                                 height);
              g_assert (cairo_surface_status (diff) == CAIRO_STATUS_SUCCESS);
              buf_diff = cairo_image_surface_get_data (diff);
              stride_diff = cairo_image_surface_get_stride (diff);
              row = (guint32 *) (buf_diff + y * stride_diff);
            }

          /* calculate a difference value for all 4 channels */
          for (channel = 0; channel < 4; channel++)
            {
              int value_a = (row_a[x] >> (channel*8)) & 0xff;
              int value_b = (row_b[x] >> (channel*8)) & 0xff;
              guint diff;

              diff = ABS (value_a - value_b);
              diff *= 4;  /* emphasize */
              if (diff)
                diff += 128; /* make sure it's visible */
              if (diff > 255)
                diff = 255;
              diff_pixel |= diff << (channel*8);
            }

          if ((diff_pixel & 0x00ffffff) == 0)
            {
              /* alpha only difference, convert to luminance */
              guint8 alpha = diff_pixel >> 24;
              diff_pixel = alpha * 0x010101;
            }
          
          row[x] = diff_pixel;
      }
  }
Beispiel #24
0
unsigned char *
_cairo_image_surface_flush_and_get_data (cairo_surface_t *surface)
{
	cairo_surface_flush (surface);
	return cairo_image_surface_get_data (surface);
}
Beispiel #25
0
/**
 * _st_create_shadow_cairo_pattern:
 * @shadow_spec: the definition of the shadow
 * @src_pattern: surface pattern for which we create the shadow
 *               (must be a surface pattern)
 *
 * This is a utility function for creating shadows used by
 * st-theme-node.c; it's in this file to share the gaussian
 * blur implementation. The usage of this function is quite different
 * depending on whether shadow_spec->inset is %TRUE or not. If
 * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern
 * which is the <i>inverse</i> of what they want shadowed, and must take
 * care of the spread and offset from the shadow spec themselves. If
 * shadow_spec->inset is %FALSE then the caller should pass in what they
 * want shadowed directly, and this function takes care of the spread and
 * the offset.
 */
cairo_pattern_t *
_st_create_shadow_cairo_pattern (StShadow        *shadow_spec,
                                 cairo_pattern_t *src_pattern)
{
    static cairo_user_data_key_t shadow_pattern_user_data;
    cairo_t *cr;
    cairo_surface_t *src_surface;
    cairo_surface_t *surface_in;
    cairo_surface_t *surface_out;
    cairo_pattern_t *dst_pattern;
    guchar          *pixels_in, *pixels_out;
    gint             width_in, height_in, rowstride_in;
    gint             width_out, height_out, rowstride_out;
    cairo_matrix_t   shadow_matrix;
    int i, j;

    g_return_val_if_fail (shadow_spec != NULL, NULL);
    g_return_val_if_fail (src_pattern != NULL, NULL);

    cairo_pattern_get_surface (src_pattern, &src_surface);

    width_in  = cairo_image_surface_get_width  (src_surface);
    height_in = cairo_image_surface_get_height (src_surface);

    /* We want the output to be a color agnostic alpha mask,
     * so we need to strip the color channels from the input
     */
    if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8)
    {
        surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8,
                     width_in, height_in);

        cr = cairo_create (surface_in);
        cairo_set_source_surface (cr, src_surface, 0, 0);
        cairo_paint (cr);
        cairo_destroy (cr);
    }
    else
    {
        surface_in = cairo_surface_reference (src_surface);
    }

    pixels_in = cairo_image_surface_get_data (surface_in);
    rowstride_in = cairo_image_surface_get_stride (surface_in);

    pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                              shadow_spec->blur,
                              &width_out, &height_out, &rowstride_out);
    cairo_surface_destroy (surface_in);

    /* Invert pixels for inset shadows */
    if (shadow_spec->inset)
    {
        for (j = 0; j < height_out; j++)
        {
            guchar *p = pixels_out + rowstride_out * j;
            for (i = 0; i < width_out; i++, p++)
                *p = ~*p;
        }
    }

    surface_out = cairo_image_surface_create_for_data (pixels_out,
                  CAIRO_FORMAT_A8,
                  width_out,
                  height_out,
                  rowstride_out);
    cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data,
                                 pixels_out, (cairo_destroy_func_t) g_free);

    dst_pattern = cairo_pattern_create_for_surface (surface_out);
    cairo_surface_destroy (surface_out);

    cairo_pattern_get_matrix (src_pattern, &shadow_matrix);

    if (shadow_spec->inset)
    {
        /* For inset shadows, offsets and spread radius have already been
         * applied to the original pattern, so all left to do is shift the
         * blurred image left, so that it aligns centered under the
         * unblurred one
         */
        cairo_matrix_translate (&shadow_matrix,
                                (width_out - width_in) / 2.0,
                                (height_out - height_in) / 2.0);
        cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);
        return dst_pattern;
    }

    /* Read all the code from the cairo_pattern_set_matrix call
     * at the end of this function to here from bottom to top,
     * because each new affine transformation is applied in
     * front of all the previous ones */

    /* 6. Invert the matrix back */
    cairo_matrix_invert (&shadow_matrix);

    /* 5. Adjust based on specified offsets */
    cairo_matrix_translate (&shadow_matrix,
                            shadow_spec->xoffset,
                            shadow_spec->yoffset);

    /* 4. Recenter the newly scaled image */
    cairo_matrix_translate (&shadow_matrix,
                            - shadow_spec->spread,
                            - shadow_spec->spread);

    /* 3. Scale up the blurred image to fill the spread */
    cairo_matrix_scale (&shadow_matrix,
                        (width_in + 2.0 * shadow_spec->spread) / width_in,
                        (height_in + 2.0 * shadow_spec->spread) / height_in);

    /* 2. Shift the blurred image left, so that it aligns centered
     * under the unblurred one */
    cairo_matrix_translate (&shadow_matrix,
                            - (width_out - width_in) / 2.0,
                            - (height_out - height_in) / 2.0);

    /* 1. Invert the matrix so we can work with it in pattern space
     */
    cairo_matrix_invert (&shadow_matrix);

    cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);

    return dst_pattern;
}
static void
gimp_view_renderer_palette_render (GimpViewRenderer *renderer,
                                   GtkWidget        *widget)
{
  GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer);
  GimpPalette             *palette;
  guchar                  *row;
  guchar                  *dest;
  GList                   *list;
  gdouble                  cell_width;
  gint                     grid_width;
  gint                     dest_stride;
  gint                     y;

  palette = GIMP_PALETTE (renderer->viewable);

  if (palette->n_colors < 1)
    return;

  grid_width = renderpal->draw_grid ? 1 : 0;

  if (renderpal->cell_size > 0)
    {
      if (palette->n_columns > 0)
        cell_width = MAX ((gdouble) renderpal->cell_size,
                          (gdouble) (renderer->width - grid_width) /
                          (gdouble) palette->n_columns);
      else
        cell_width = renderpal->cell_size;
    }
  else
    {
      if (palette->n_columns > 0)
        cell_width = ((gdouble) (renderer->width - grid_width) /
                      (gdouble) palette->n_columns);
      else
        cell_width = (gdouble) (renderer->width - grid_width) / 16.0;
    }

  cell_width = MAX (4.0, cell_width);

  renderpal->cell_width = cell_width;

  renderpal->columns = (gdouble) (renderer->width - grid_width) / cell_width;

  renderpal->rows = palette->n_colors / renderpal->columns;
  if (palette->n_colors % renderpal->columns)
    renderpal->rows += 1;

  renderpal->cell_height = MAX (4, ((renderer->height - grid_width) /
                                    renderpal->rows));

  if (! renderpal->draw_grid)
    renderpal->cell_height = MIN (renderpal->cell_height,
                                  renderpal->cell_width);

  list = palette->colors;

  if (! renderer->surface)
    renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
                                                    renderer->width,
                                                    renderer->height);

  cairo_surface_flush (renderer->surface);

  row = g_new (guchar, renderer->width * 4);

  dest        = cairo_image_surface_get_data (renderer->surface);
  dest_stride = cairo_image_surface_get_stride (renderer->surface);

  for (y = 0; y < renderer->height; y++)
    {
      if ((y % renderpal->cell_height) == 0)
        {
          guchar  r, g, b;
          gint    x;
          gint    n = 0;
          guchar *d = row;

          memset (row, renderpal->draw_grid ? 0 : 255, renderer->width * 4);

          r = g = b = (renderpal->draw_grid ? 0 : 255);

          for (x = 0; x < renderer->width; x++, d += 4)
            {
              if ((x % renderpal->cell_width) == 0)
                {
                  if (list && n < renderpal->columns &&
                      renderer->width - x >= renderpal->cell_width)
                    {
                      GimpPaletteEntry *entry = list->data;

                      list = g_list_next (list);
                      n++;

                      gimp_rgb_get_uchar (&entry->color, &r, &g, &b);
                    }
                  else
                    {
                      r = g = b = (renderpal->draw_grid ? 0 : 255);
                    }
                }

              if (renderpal->draw_grid && (x % renderpal->cell_width) == 0)
                {
                  GIMP_CAIRO_RGB24_SET_PIXEL (d, 0, 0, 0);
                }
              else
                {
                  GIMP_CAIRO_RGB24_SET_PIXEL (d, r, g, b);
                }
            }
        }

      if (renderpal->draw_grid && (y % renderpal->cell_height) == 0)
        {
          memset (dest, 0, renderer->width * 4);
        }
      else
        {
          memcpy (dest, row, renderer->width * 4);
        }

      dest += dest_stride;
    }

  g_free (row);

  cairo_surface_mark_dirty (renderer->surface);

  renderer->needs_render = FALSE;
}
Beispiel #27
0
static void _lib_modulelist_populate_callback(gpointer instance, gpointer user_data)
{
    dt_lib_module_t *self = (dt_lib_module_t *)user_data;
    if(!self || !(self->data)) return;

    GtkListStore *store;
    GtkTreeIter iter;
    GtkWidget *view = GTK_WIDGET(((dt_lib_modulelist_t *)self->data)->tree);
    GtkCellRenderer *pix_renderer, *fav_renderer, *text_renderer;
    GdkRGBA color;
    GtkStyleContext *context = gtk_widget_get_style_context(view);
    gboolean color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color);
    if(!color_found)
    {
        color.red = 1.0;
        color.green = 0.0;
        color.blue = 0.0;
        color.alpha = 1.0;
    }

    store = gtk_list_store_new(NUM_COLS, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
    gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
    g_object_unref(store);

    gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), COL_MODULE, _lib_modulelist_gui_sort, NULL, NULL);
    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COL_MODULE, GTK_SORT_ASCENDING);

    pix_renderer = gtk_cell_renderer_pixbuf_new();
    g_object_set(pix_renderer, "cell-background-rgba", &color, NULL);

    fav_renderer = gtk_cell_renderer_pixbuf_new();
    cairo_surface_t *fav_cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, ICON_SIZE, ICON_SIZE);
    cairo_t *fav_cr = cairo_create(fav_cst);
    cairo_set_source_rgb(fav_cr, 0.7, 0.7, 0.7);
    dtgtk_cairo_paint_modulegroup_favorites(fav_cr, 0, 0, ICON_SIZE, ICON_SIZE, 0);
    guchar *data = cairo_image_surface_get_data(fav_cst);
    dt_draw_cairo_to_gdk_pixbuf(data, ICON_SIZE, ICON_SIZE);
    ((dt_lib_modulelist_t *)self->data)->fav_pixbuf
        = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, ICON_SIZE, ICON_SIZE,
                                   cairo_image_surface_get_stride(fav_cst), NULL, NULL);
    g_object_set(fav_renderer, "cell-background-rgba", &color, NULL);
    g_object_set(fav_renderer, "width", gdk_pixbuf_get_width(((dt_lib_modulelist_t *)self->data)->fav_pixbuf),
                 NULL);

    text_renderer = gtk_cell_renderer_text_new();
    g_object_set(text_renderer, "cell-background-rgba", &color, NULL);

    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
    gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(view), FALSE);
    GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
    gtk_tree_selection_set_mode(selection, GTK_SELECTION_NONE);

    GtkTreeViewColumn *col;
    col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 0);
    if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col);
    gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 0, "favorite", fav_renderer,
            favorite_renderer_function, NULL, NULL);
    col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 1);
    if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col);
    gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 1, "image", pix_renderer,
            image_renderer_function, NULL, NULL);
    col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), 2);
    if(col) gtk_tree_view_remove_column(GTK_TREE_VIEW(view), col);
    gtk_tree_view_insert_column_with_data_func(GTK_TREE_VIEW(view), 2, "name", text_renderer,
            text_renderer_function, NULL, NULL);

    /* go thru list of iop modules and add them to the list */
    GList *modules = g_list_last(darktable.develop->iop);

    char datadir[PATH_MAX] = { 0 };
    dt_loc_get_datadir(datadir, sizeof(datadir));

    while(modules)
    {
        dt_iop_module_t *module = (dt_iop_module_t *)(modules->data);
        if(!dt_iop_is_hidden(module) && !(module->flags() & IOP_FLAGS_DEPRECATED) && module->multi_priority == 0)
        {
            GdkPixbuf *pixbuf;
            char filename[PATH_MAX] = { 0 };

            snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/%s.svg", datadir, module->op);
            pixbuf = load_image(filename);
            if(pixbuf) goto end;

            snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/%s.png", datadir, module->op);
            pixbuf = load_image(filename);
            if(pixbuf) goto end;

            snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/template.svg", datadir);
            pixbuf = load_image(filename);
            if(pixbuf) goto end;

            snprintf(filename, sizeof(filename), "%s/pixmaps/plugins/darkroom/template.png", datadir);
            pixbuf = load_image(filename);
            if(pixbuf) goto end;

            // wow, we could neither load the SVG nor the PNG files. something is f****d up.
            pixbuf = gdk_pixbuf_new_from_data(fallback_pixel, GDK_COLORSPACE_RGB, TRUE, 8, 1, 1, 4, NULL, NULL);

end:
            gtk_list_store_append(store, &iter);
            gtk_list_store_set(store, &iter, COL_IMAGE, pixbuf, COL_MODULE, module, -1);
            g_object_unref(pixbuf);
        }

        modules = g_list_previous(modules);
    }
}
Beispiel #28
0
uint8_t* SurfaceImage::getData() 
{
	return cairo_image_surface_get_data( mCairoSurface );
}
Beispiel #29
0
	double lime_cairo_image_surface_get_data (value handle) {
		
		return (intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)val_data (handle));
		
	}
Beispiel #30
0
 static uint8_t const* read(data_type_t const& data_in) {
   return cairo_image_surface_get_data(data_in);
 }