예제 #1
0
/* 
 * functions to create different wrapmodes.
 */
static GpStatus
draw_tile_texture (cairo_t *ct, GpBitmap *bitmap, GpTexture *brush)
{
	cairo_surface_t *original = NULL;
	cairo_surface_t *texture;
	cairo_pattern_t *pat;
	GpStatus	status;
	GpRect		*rect = &brush->rectangle;
	cairo_t		*ct2;
	BYTE *premul = NULL;

	if (!rect)
		return InvalidParameter;

	gdip_bitmap_ensure_surface (bitmap);

	if (gdip_bitmap_format_needs_premultiplication (bitmap)) {
		premul = gdip_bitmap_get_premultiplied_scan0 (bitmap);
		if (premul) {
			ActiveBitmapData *data = bitmap->active_bitmap;
			original = cairo_image_surface_create_for_data (premul, CAIRO_FORMAT_ARGB32, 
				data->width, data->height, data->stride);
		}
	}

	/* if premul isn't required (or couldn't be computed, e.g. out of memory) */
	if (!original)
		original = bitmap->surface;

	/* Use the original as a pattern */
	pat = cairo_pattern_create_for_surface (original);
	status = gdip_get_pattern_status (pat);
	if (status != Ok)
		goto cleanup;

	cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);

	/* texture surface to be created */
	texture = cairo_surface_create_similar (original, from_cairoformat_to_content (bitmap->cairo_format),
						rect->Width, rect->Height);
	status = gdip_get_status (cairo_surface_status (texture));
	if (status != Ok) {
		cairo_pattern_destroy (pat);
		goto cleanup;
	}

	/* Draw the texture */
	ct2 = cairo_create (texture);
	cairo_set_source (ct2, pat);
	cairo_rectangle (ct2, 0, 0, rect->Width, rect->Height);
	cairo_fill (ct2);
	cairo_destroy (ct2);

	brush->pattern = cairo_pattern_create_for_surface (texture);
	status = gdip_get_pattern_status (brush->pattern);
	if (status == Ok)
		cairo_pattern_set_extend (brush->pattern, CAIRO_EXTEND_REPEAT);

	cairo_pattern_destroy (pat);
	cairo_surface_destroy (texture);

	status = gdip_get_status (cairo_status (ct));

cleanup:
	if (premul) {
		cairo_surface_destroy (original);
		GdipFree (premul);
	}
	return status;
}
예제 #2
0
static cairo_int_status_t
_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
				  cairo_scaled_glyph_t *scaled_glyph)
{
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;

    cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);

    cairo_image_surface_t *surface = NULL;

    CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);

    int advance;
    CGRect bbox;
    double width, height;
    double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);

    CGContextRef cgContext = NULL;
    CGAffineTransform textMatrix;
    CGRect glyphRect, glyphRectInt;
    CGPoint glyphOrigin;

    //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);

    /* Create blank 2x2 image if we don't have this character.
     * Maybe we should draw a better missing-glyph slug or something,
     * but this is ok for now.
     */
    if (glyph == INVALID_GLYPH) {
	surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
	status = cairo_surface_status ((cairo_surface_t *) surface);
	if (status)
	    return status;

	_cairo_scaled_glyph_set_surface (scaled_glyph,
					 &font->base,
					 surface);
	return CAIRO_STATUS_SUCCESS;
    }

    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
    {
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    /* scale(1,-1) * font->base.scale * scale(1,-1) */
    textMatrix = CGAffineTransformMake (font->base.scale.xx,
					-font->base.scale.yx,
					-font->base.scale.xy,
					font->base.scale.yy,
					0, -0);
    glyphRect = CGRectMake (bbox.origin.x / emscale,
			    bbox.origin.y / emscale,
			    bbox.size.width / emscale,
			    bbox.size.height / emscale);

    glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);

    /* Round the rectangle outwards, so that we don't have to deal
     * with non-integer-pixel origins or dimensions.
     */
    glyphRectInt = CGRectIntegral (glyphRect);

#if 0
    fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
	     glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
    fprintf (stderr, "glyphRectInt: %f %f %f %f\n",
	     glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height);
#endif

    glyphOrigin = glyphRectInt.origin;

    //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));

    width = glyphRectInt.size.width;
    height = glyphRectInt.size.height;

    //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);

    surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
    if (surface->base.status)
	return surface->base.status;

    if (surface->width != 0 && surface->height != 0) {
	cgContext = CGBitmapContextCreate (surface->data,
					   surface->width,
					   surface->height,
					   8,
					   surface->stride,
					   NULL,
					   kCGImageAlphaOnly);

	if (cgContext == NULL) {
	    cairo_surface_destroy (&surface->base);
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
	}

	CGContextSetFont (cgContext, font_face->cgFont);
	CGContextSetFontSize (cgContext, 1.0);
	CGContextSetTextMatrix (cgContext, textMatrix);

	switch (font->base.options.antialias) {
	case CAIRO_ANTIALIAS_SUBPIXEL:
	case CAIRO_ANTIALIAS_BEST:
	    CGContextSetShouldAntialias (cgContext, TRUE);
	    CGContextSetShouldSmoothFonts (cgContext, TRUE);
	    if (CGContextSetAllowsFontSmoothingPtr &&
		!CGContextGetAllowsFontSmoothingPtr (cgContext))
		CGContextSetAllowsFontSmoothingPtr (cgContext, TRUE);
	    break;
	case CAIRO_ANTIALIAS_NONE:
	    CGContextSetShouldAntialias (cgContext, FALSE);
	    break;
	case CAIRO_ANTIALIAS_GRAY:
	case CAIRO_ANTIALIAS_GOOD:
	case CAIRO_ANTIALIAS_FAST:
	    CGContextSetShouldAntialias (cgContext, TRUE);
	    CGContextSetShouldSmoothFonts (cgContext, FALSE);
	    break;
	case CAIRO_ANTIALIAS_DEFAULT:
	default:
	    /* Don't do anything */
	    break;
	}

	CGContextSetAlpha (cgContext, 1.0);
	CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1);

	CGContextRelease (cgContext);
    }

    cairo_surface_set_device_offset (&surface->base,
				     - glyphOrigin.x,
				     height + glyphOrigin.y);

    _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);

    return status;
}
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    cairo_t *cr;
    cairo_test_status_t ret = CAIRO_TEST_UNTESTED;
    struct {
	double x, y;
    } ppi[] = {
	{ 600, 600 },
	{ 600, 72 },

	{ 300, 300 },
	{ 300, 72 },

	{ 150, 150 },
	{ 150, 72 },

	{ 75, 75 },
	{ 75, 72 },

	{ 72, 600 },
	{ 72, 300 },
	{ 72, 150 },
	{ 72, 75 },
	{ 72, 72 },
	{ 72, 37.5 },

	{ 37.5, 72 },
	{ 37.5, 37.5 },
    };
    unsigned int i;
    int n, num_ppi;

    num_ppi = sizeof (ppi) / sizeof (ppi[0]);

#if GENERATE_REFERENCE
    for (n = 0; n < num_ppi; n++) {
	char *ref_name;
	xasprintf (&ref_name, "fallback-resolution.ppi%gx%g.ref.png",
		   ppi[n].x, ppi[n].y);
	generate_reference (ppi[n].x, ppi[n].y, ref_name);
	free (ref_name);
    }
#endif

    for (i = 0; i < ctx->num_targets; i++) {
	const cairo_boilerplate_target_t *target = ctx->targets_to_test[i];
	cairo_surface_t *surface = NULL;
	char *base_name;
	void *closure;
	const char *format;
	cairo_status_t status;

	if (! target->is_vector)
	    continue;

	if (! cairo_test_is_target_enabled (ctx, target->name))
	    continue;

	format = cairo_boilerplate_content_name (target->content);
	xasprintf (&base_name, "fallback-resolution.%s.%s",
		   target->name,
		   format);

	surface = (target->create_surface) (base_name,
					    target->content,
					    SIZE, SIZE,
					    SIZE, SIZE,
					    CAIRO_BOILERPLATE_MODE_TEST,
					    0,
					    &closure);

	if (surface == NULL) {
	    free (base_name);
	    continue;
	}

	if (ret == CAIRO_TEST_UNTESTED)
	    ret = CAIRO_TEST_SUCCESS;

	cairo_surface_destroy (surface);
	if (target->cleanup)
	    target->cleanup (closure);
	free (base_name);

	/* we need to recreate the surface for each resolution as we include
	 * SVG in testing which does not support the paginated interface.
	 */
	for (n = 0; n < num_ppi; n++) {
	    char *test_name;
	    cairo_bool_t pass;

	    xasprintf (&test_name, "fallback-resolution.ppi%gx%g",
		       ppi[n].x, ppi[n].y);
	    xasprintf (&base_name, "%s.%s.%s",
		       test_name,
		       target->name,
		       format);

	    surface = (target->create_surface) (base_name,
						target->content,
						SIZE + 25, SIZE + 25,
						SIZE + 25, SIZE + 25,
						CAIRO_BOILERPLATE_MODE_TEST,
						0,
						&closure);
	    if (surface == NULL || cairo_surface_status (surface)) {
		cairo_test_log (ctx, "Failed to generate surface: %s.%s\n",
				target->name,
				format);
		free (base_name);
		free (test_name);
		ret = CAIRO_TEST_FAILURE;
		continue;
	    }

	    cairo_test_log (ctx,
			    "Testing fallback-resolution %gx%g with %s target\n",
			    ppi[n].x, ppi[n].y, target->name);
	    printf ("%s:\t", base_name);
	    fflush (stdout);

	    if (target->force_fallbacks != NULL)
		target->force_fallbacks (surface, ~0U);
	    cr = cairo_create (surface);
#if SET_TOLERANCE
	    cairo_set_tolerance (cr, 3.0);
#endif

	    cairo_surface_set_device_offset (surface, 25, 25);
	    cairo_surface_set_fallback_resolution (surface,
						   ppi[n].x, ppi[n].y);

	    cairo_save (cr); {
		cairo_set_source_rgb (cr, 1, 1, 1);
		cairo_paint (cr);
	    } cairo_restore (cr);

	    /* First draw the top half in a conventional way. */
	    cairo_save (cr); {
		cairo_rectangle (cr, 0, 0, SIZE, SIZE / 2.0);
		cairo_clip (cr);

		draw (cr, SIZE, SIZE);
	    } cairo_restore (cr);

	    /* Then draw the bottom half in a separate group,
	     * (exposing a bug in 1.6.4 with the group not being
	     * rendered with the correct fallback resolution). */
	    cairo_save (cr); {
		cairo_rectangle (cr, 0, SIZE / 2.0, SIZE, SIZE / 2.0);
		cairo_clip (cr);

		cairo_push_group (cr); {
		    draw (cr, SIZE, SIZE);
		} cairo_pop_group_to_source (cr);

		cairo_paint (cr);
	    } cairo_restore (cr);

	    status = cairo_status (cr);
	    cairo_destroy (cr);

	    pass = FALSE;
	    if (status) {
		cairo_test_log (ctx, "Error: Failed to create target surface: %s\n",
				cairo_status_to_string (status));
		ret = CAIRO_TEST_FAILURE;
	    } else {
		/* extract the image and compare it to our reference */
		if (! check_result (ctx, target, test_name, base_name, surface))
		    ret = CAIRO_TEST_FAILURE;
		else
		    pass = TRUE;
	    }
	    cairo_surface_destroy (surface);
	    if (target->cleanup)
		target->cleanup (closure);

	    free (base_name);
	    free (test_name);

	    if (pass) {
		printf ("PASS\n");
	    } else {
		printf ("FAIL\n");
	    }
	    fflush (stdout);
	}
    }

    return ret;
}
예제 #4
0
void MediaPlayerPrivateEA::paint(GraphicsContext* context, const IntRect& r)
{
    if (!context)
        return;

    // Can get a NULL platform context so need to verify.  Seems that UpdateControlTints does what is called a "fake" paint
    // with a null platform context just to get an invalidate.
    PlatformContextCairo* pPlatformContext = context->platformContext();
    if (!pPlatformContext)
        return;

    cairo_t* cr = context->platformContext()->cr();
    if (!cr)
        return;

    MediaUpdateInfo& info = GetMediaUpdateInfo();
    const FrameView* pFV = mpWebCorePlayer->frameView();
    if (!pFV)
        return;

    // Convert and store movie rect to device coords using the graphic context.
    double x = (double) r.x();
    double y = (double) r.y();
    double w = (double) r.width();
    double h = (double) r.height();
    cairo_user_to_device (cr, &x, &y);
    cairo_user_to_device_distance(cr, &w, &h);  
    const IntRect rect((int) x, (int) y, (int) w, (int) h);
   
    // The intersection of frameView contents and the movie is used as clip rect for we just want to know what part of the movie is visible.
    IntRect clip = pFV->windowClipRect(true);
    clip.intersect(rect);
    
    // Find controls intersection
    HTMLMediaElement* element = static_cast<HTMLMediaElement*>(mpWebCorePlayer->mediaPlayerClient());
    if(element && element->controls())
    {
        MediaControls* pControls = element->mediaControls();    
        bool hideControls = pControls->shouldHideControls(); 
        if (!hideControls)
        {
            const int kControlHeight = 16;  // EAWebKitTODO: Consider finding a way to extract this info directly from the controls or pass as a theme param.
            
            IntRect boundingRect = pControls->getRect();
            x = (double) boundingRect.x();
            y = (double) boundingRect.y();
            w = (double) boundingRect.width();
            h = (double) (boundingRect.height() - kControlHeight);
            cairo_user_to_device (cr, &x, &y);
            cairo_user_to_device_distance(cr, &w, &h);  
            const IntRect ctrlRect((int) x, (int) y, (int) w, (int) h);
            clip.intersect(ctrlRect);
        }
    }

    if ((rect != mMovieRect) || (clip != mWindowRect))
    {
        mMovieRect = rect;      // Store copy locally to detect changes.
        mWindowRect = clip;

        info.mMovieRect = rect;
        info.mWindowRect = clip;
        ClientUpdate(MediaUpdateInfo::kWindowSize);
    }    
 
    ClientUpdate(MediaUpdateInfo::kPaint);
    if (info.mReturnData)
    {
        // Draw surface to view
#ifndef NDEBUG
        static bool sAssertChecked = false;
        if(!sAssertChecked)
        {
            EAW_ASSERT(!info.mReturnData);   
            sAssertChecked = true;
        }
#endif
        context->save(); 
        RefPtr<cairo_surface_t> cairoSurface = adoptRef(cairo_image_surface_create_for_data((unsigned char*) info.mReturnData, CAIRO_FORMAT_ARGB32, w, h, w * sizeof(uint32_t)));
        EAW_ASSERT(cairo_surface_status(cairoSurface.get()) == CAIRO_STATUS_SUCCESS);
        cairo_set_source_surface(cr, cairoSurface.get(), rect.x(), rect.y()); 
        cairo_paint(cr);
        context->restore(); 
    }
    else
    {
        // Draw a default black background.
        context->save(); 
        context->setStrokeStyle(NoStroke);
        context->setFillColor(Color::black, ColorSpaceDeviceRGB);
        context->drawRect(r);    
        context->restore();
    }
}
예제 #5
0
int main(int argc, char** argv) {

  int c;
  float col_r, col_g, col_b = -1.0f;
  Options opt;

  while ((c = getopt(argc, argv, "a:x:y:f:s:t:n:w:r:g:b:c:")) != -1) {
    switch(c) {

      /* color */
      /* ------------------------------------------------------- */
      case 'r': {
        col_r = convert_type<float>(optarg);
        break;
      }
      case 'g': {
        col_g = convert_type<float>(optarg);
        break;
      }
      case 'b': {
        col_b = convert_type<float>(optarg);
        break;
      }
      
      /* ------------------------------------------------------- */
      /* foreground */
      case 'c': {
        opt.foreground_file = convert_type<std::string>(optarg);
        break;
      }
      /* ------------------------------------------------------- */
      /* background */
      case 'x': {
        opt.background_x = convert_type<int>(optarg);
        break;
      }
      case 'y': {
        opt.background_y = convert_type<int>(optarg);
        break;
      }
      case 'f': {
        //printf("Got: %s", optarg);
        opt.background_file = convert_type<std::string>(optarg);
        break;
      }

      /* ------------------------------------------------------- */
      /* visible size */
      case 'a': {
        opt.visible_size = convert_type<float>(optarg);
        break;
      }

      /* ------------------------------------------------------- */
      /* name */
      case 'n': {
        opt.name = convert_type<std::string>(optarg);

        /* we expect that r,g,b has been set */
        if (0 > col_r) {
          printf("Error: you haven't set -r -g -b for the name.\n");
          exit(EXIT_FAILURE);
        }
        opt.name_r = col_r;
        opt.name_g = col_g;
        opt.name_b = col_b;
        break;
      }
      /* name x position */
      case 's': {
        opt.name_x = convert_type<int>(optarg);
        break;
      }
      /* name y position */
      case 't': {
        opt.name_y = convert_type<int>(optarg);
        break;
      }
      /* name font size */
      case 'w': {
        opt.name_font_size = convert_type<float>(optarg);
        break;
      }
      default: {
        printf("Unkown option\n");
        break;
      }
    }
  }
  
  if (false == opt.validate()) {
    printf("+ error: cannot validate the given options.\n");
    exit(EXIT_FAILURE);
  }

  opt.print();

  /* ------------------------------------------------------------------------------------ */

  Image img;
  std::string path;
  std::string ext;
  cairo_surface_t* surf_bg = NULL;
  cairo_format_t img_format = CAIRO_FORMAT_INVALID;

  path = opt.foreground_file;
  if (false == rx_file_exists(path)) {
    printf("+ error: cannot find the file: %s\n", path.c_str());
    exit(EXIT_FAILURE);
  }

  cairo_surface_t* surf_overlay = cairo_image_surface_create_from_png(path.c_str());
  if (NULL == surf_overlay) {
    printf("Error: cannot create s1\n");
    exit(EXIT_FAILURE);
  }

  path = opt.background_file;
  if (false == rx_file_exists(path)) {
    printf("Error: file doesn't exist: %s\n", path.c_str());
    exit(EXIT_FAILURE);
  }
  
  /* check what file type was given. */
  ext = rx_get_file_ext(path);
  if (ext == "jpg") {

    printf("+ warning: jpg as input doesn't seem to work\n");

    /* cairo doesn't have support for PNG? */
    if (0 > rx_load_jpg(path, &img.pixels, img.width, img.height, img.channels)) {
      printf("Error: failed to load: %s\n", path.c_str());
      exit(EXIT_FAILURE);
    }
    if (0 == img.width || 0 == img.height || 0 == img.channels) {
      printf("Error: image has invalid flags: %d x %d, channels: %d\n", img.width, img.height, img.channels);
      exit(EXIT_FAILURE);
    }

    if (3 == img.channels) {
      img_format = CAIRO_FORMAT_RGB24;
      printf("+ Using RGB24\n");
    }  
    else if(4 == img.channels) {
      img_format = CAIRO_FORMAT_ARGB32;
      printf("+ Using ARGB32\n");
    }
    else {
      printf("Error: unsupported number of channels: %d.\n", img.channels);
      exit(EXIT_FAILURE);
    }

    if (NULL != img.pixels && NULL == surf_bg) {

        printf("Stride: %d\n", cairo_format_stride_for_width(img_format, img.width));
        printf("Info: creating %d x %d, channels: %d\n", img.width, img.height, img.channels);

        surf_bg = cairo_image_surface_create_for_data(img.pixels, 
                                                      img_format, 
                                                      img.width, 
                                                      img.height, 
                                                      cairo_format_stride_for_width(img_format, img.width));

#if 0
      /* TESTING */
      cairo_t* cr = cairo_create(surf_bg);
      if (NULL == cr) { 
        printf("Error: cannot create the cairo");
        exit(EXIT_FAILURE);
      }
      path = rx_get_exe_path() +"/generated_polaroid.png";
      cairo_surface_write_to_png(surf_bg, path.c_str());
      printf("Created\n");
      exit(0);
      /* END TESTING */
#endif
    }
  }
  else if (ext == "png") {

    /* use cairo png load feature. */
    surf_bg = cairo_image_surface_create_from_png(path.c_str());
    if (NULL == surf_bg) {
      printf("Error: cannot create s2\n");
      exit(EXIT_FAILURE);
    }

  }
  else {
    printf("Error: unsupported file format: %s\n", ext.c_str());
    exit(EXIT_FAILURE);
  }


  /* make sure the background is loaded correctly (aka the photo) */
  if (NULL == surf_bg) {
    printf("Error: cannot create background surface.\n");
    exit(EXIT_FAILURE);
  }

  if (CAIRO_STATUS_SUCCESS != cairo_surface_status(surf_bg)) {
    printf("Error: something went wrong: %d\n", cairo_surface_status(surf_bg));
    exit(EXIT_FAILURE);
  }

  float source_width = cairo_image_surface_get_width(surf_bg);
  float source_height = cairo_image_surface_get_height(surf_bg);

  /* create output */
  int dest_width = cairo_image_surface_get_width(surf_overlay);
  int dest_height = cairo_image_surface_get_height(surf_overlay);

  printf("+ Output size: %d x %d\n", dest_width, dest_height);

  cairo_surface_t* surf_out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_width, dest_height);
  if (NULL == surf_out) {
    printf("Error: cannot create cairo_surface_t\n");
    exit(EXIT_FAILURE);
  }

  printf("+ Info: creating output surface: %d x %d\n", dest_width, dest_height);

  cairo_t* cr = cairo_create(surf_out);
  if (NULL == cr) { 
    printf("Error: cannot create the cairo");
    exit(EXIT_FAILURE);
  }


  /* fill background. */
  cairo_set_source_rgba(cr, 1, 1, 1, 1);
  cairo_paint(cr);

  float scale_factor = opt.visible_size / source_width;
  printf("+ Scale factor: %f\n", scale_factor);

  /* paint background */  
  cairo_save(cr);
  cairo_scale(cr, scale_factor, scale_factor);
  cairo_set_source_surface(cr, surf_bg, opt.background_x, opt.background_y);
  cairo_rectangle(cr, 0, 0, img.width, img.height);
  cairo_paint(cr);
  cairo_restore(cr);

  /* paint overlay */
  cairo_set_source_surface(cr, surf_overlay, 0, 0);
  cairo_paint(cr);
  cairo_surface_flush(surf_out);

  /* font */
  cairo_select_font_face(cr, "Open Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
  cairo_set_source_rgba(cr, opt.name_r, opt.name_g, opt.name_b, 1.0); 
  cairo_move_to(cr, opt.name_x, opt.name_y);
  cairo_set_font_size(cr, opt.name_font_size);
  cairo_show_text(cr, opt.name.c_str());

  cairo_stroke(cr);
  cairo_fill(cr);
  cairo_surface_flush(surf_out);

  /* write out */
  path = rx_get_exe_path() +"/generated_polaroid.png";
  cairo_surface_write_to_png(surf_out, path.c_str());

  /* cleanup */
  cairo_surface_destroy(surf_out);
  cairo_surface_destroy(surf_bg);
  cairo_surface_destroy(surf_overlay);
  cairo_destroy(cr);

  printf("\n");
  return 0;
}
예제 #6
0
static int
surface_status (lua_State *L) {
    cairo_surface_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_SURFACE);
    return push_cairo_status(L, cairo_surface_status(*obj));
}
예제 #7
0
int main(int argc, char** argv)
{
	cairo_t *cr;
	cairo_status_t status;
	cairo_surface_t *surface;
	//FT_Bitmap bmp = {0};

	int stride = 0;
	int width = 640;
	int height = 480;



	bool ok = FcConfigAppFontAddFile(NULL, (FcChar8*)"fonts/ComicSansAfrica.ttf");
	if (!ok)
	{
		printf("Failed to load ComicSansAfrica.ttf\n");
	}

	FcChar8 *configName = FcConfigFilename(NULL);
	printf("%s", (const char*)configName);
	printf("\n");

	FcConfig* config = FcConfigCreate();
	FcConfigParseAndLoad(config, configName, true);
	FcConfigSetCurrent(config);

	/* FT buffer */
	//FT_Bitmap_New(&bmp);
	//bmp.rows = height;
	//bmp.width = width;

	//bmp.buffer = (unsigned char*)malloc(bmp.rows * bmp.width * 4);
	// if (NULL == bmp.buffer)
	// {
	// 	printf("+ error: cannot allocate the buffer for the output bitmap.\n");
	// 	exit(EXIT_FAILURE);
	// }

	//bmp.pitch = ((width+3) & -4) * 4;
	//bmp.pixel_mode = FT_PIXEL_MODE_BGRA;

	//printf("%d\n", bmp.pitch);

	//stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
	//printf("%d\n", stride);

	//surface = cairo_image_surface_create_for_data(bmp.buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
	if (CAIRO_STATUS_SUCCESS != cairo_surface_status(surface)) {
		printf("+ error: couldn't create the surface.\n");
		exit(EXIT_FAILURE);
	}
	cr = cairo_create(surface);
	if (CAIRO_STATUS_NO_MEMORY == cairo_status(cr)) {
		printf("+ error: out of memory, cannot create cairo_t*\n");
		exit(EXIT_FAILURE);
	}


	cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0);
	cairo_paint(cr);

	rendertext(cr);


	status = cairo_surface_write_to_png(surface, "out.png");
	cairo_surface_destroy(surface);
	cairo_destroy(cr);

	return 0;
}
static cairo_int_status_t
_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
				  cairo_scaled_glyph_t *scaled_glyph)
{
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;

    cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);

    cairo_image_surface_t *surface = NULL;

    CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);

    int advance;
    CGRect bbox;
    double width, height;
    double xscale, yscale;
    double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);

    CGColorSpaceRef gray;
    CGContextRef cgContext = NULL;
    CGAffineTransform textMatrix;
    CGRect glyphRect, glyphRectInt;
    CGPoint glyphOrigin;

    //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);

    /* Create blank 2x2 image if we don't have this character.
     * Maybe we should draw a better missing-glyph slug or something,
     * but this is ok for now.
     */
    if (glyph == INVALID_GLYPH) {
	surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
	status = cairo_surface_status ((cairo_surface_t *) surface);
	if (status)
	    return status;

	_cairo_scaled_glyph_set_surface (scaled_glyph,
					 &font->base,
					 surface);
	return CAIRO_STATUS_SUCCESS;
    }

    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
    {
	return CAIRO_INT_STATUS_UNSUPPORTED;
    }

    status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale,
						  &xscale, &yscale, 1);
    if (status)
	return status;

    textMatrix = CGAffineTransformMake (font->base.scale.xx,
					-font->base.scale.yx,
					-font->base.scale.xy,
					font->base.scale.yy,
					0.0f, 0.0f);
    glyphRect = CGRectMake (bbox.origin.x / emscale,
			    bbox.origin.y / emscale,
			    bbox.size.width / emscale,
			    bbox.size.height / emscale);

    glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);

    /* Round the rectangle outwards, so that we don't have to deal
     * with non-integer-pixel origins or dimensions.
     */
    glyphRectInt = CGRectIntegral (glyphRect);

#if 0
    fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
	     glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
    fprintf (stderr, "glyphRectInt: %f %f %f %f\n",
	     glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height);
#endif

    glyphOrigin = glyphRectInt.origin;

    //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));

    width = glyphRectInt.size.width;
    height = glyphRectInt.size.height;

    //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);

    surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
    if (surface->base.status)
	return surface->base.status;

    gray = CGColorSpaceCreateDeviceGray ();
    cgContext = CGBitmapContextCreate (surface->data,
				       surface->width,
				       surface->height,
				       8,
				       surface->stride,
				       gray,
				       kCGImageAlphaNone);
    CGColorSpaceRelease (gray);

    CGContextSetFont (cgContext, font_face->cgFont);
    CGContextSetFontSize (cgContext, 1.0);
    CGContextSetTextMatrix (cgContext, textMatrix);

    CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height));

    if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE)
	CGContextSetShouldAntialias (cgContext, false);

    CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0);
    CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1);

    CGContextRelease (cgContext);

    cairo_surface_set_device_offset (&surface->base,
				     - glyphOrigin.x,
				     height + glyphOrigin.y);

    _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);

    return status;
}
예제 #9
0
void
draw_shadow (cairo_t* cr,
	     gdouble  width,
	     gdouble  height,
	     gint     shadow_radius,
	     gint     corner_radius)
{
	cairo_surface_t* tmp_surface = NULL;
	cairo_surface_t* new_surface = NULL;
	cairo_pattern_t* pattern     = NULL;
	cairo_t*         cr_surf     = NULL;
	cairo_matrix_t   matrix;
	raico_blur_t*    blur        = NULL;

	tmp_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
						  4 * shadow_radius,
						  4 * shadow_radius);
	if (cairo_surface_status (tmp_surface) != CAIRO_STATUS_SUCCESS)
		return;

	cr_surf = cairo_create (tmp_surface);
	if (cairo_status (cr_surf) != CAIRO_STATUS_SUCCESS)
	{
		cairo_surface_destroy (tmp_surface);
		return;
	}

	cairo_scale (cr_surf, 1.0f, 1.0f);
	cairo_set_operator (cr_surf, CAIRO_OPERATOR_CLEAR);
	cairo_paint (cr_surf);
	cairo_set_operator (cr_surf, CAIRO_OPERATOR_OVER);
	cairo_set_source_rgba (cr_surf, 0.0f, 0.0f, 0.0f, 0.75f);
	cairo_arc (cr_surf,
		   2 * shadow_radius,
		   2 * shadow_radius,
		   2.0f * corner_radius,
		   0.0f,
		   360.0f * (G_PI / 180.f));
	cairo_fill (cr_surf);
	cairo_destroy (cr_surf);

	// create and setup blur
	blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
	raico_blur_set_radius (blur, shadow_radius);

	// now blur it
	raico_blur_apply (blur, tmp_surface);

	// blur no longer needed
	raico_blur_destroy (blur);

	new_surface = cairo_image_surface_create_for_data (
			cairo_image_surface_get_data (tmp_surface),
			cairo_image_surface_get_format (tmp_surface),
			cairo_image_surface_get_width (tmp_surface) / 2,
			cairo_image_surface_get_height (tmp_surface) / 2,
			cairo_image_surface_get_stride (tmp_surface));
	pattern = cairo_pattern_create_for_surface (new_surface);
	if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS)
	{
		cairo_surface_destroy (tmp_surface);
		cairo_surface_destroy (new_surface);
		return;
	}

	// top left
	cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
	cairo_set_source (cr, pattern);
	cairo_rectangle (cr,
			 0.0f,
			 0.0f,
			 width - 2 * shadow_radius,
			 2 * shadow_radius);
	cairo_fill (cr);

	// bottom left
	cairo_matrix_init_scale (&matrix, 1.0f, -1.0f);
	cairo_matrix_translate (&matrix, 0.0f, -height);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 0.0f,
			 2 * shadow_radius,
			 2 * shadow_radius,
			 height - 2 * shadow_radius);
	cairo_fill (cr);

	// top right
	cairo_matrix_init_scale (&matrix, -1.0f, 1.0f);
	cairo_matrix_translate (&matrix, -width, 0.0f);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 width - 2 * shadow_radius,
			 0.0f,
			 2 * shadow_radius,
			 height - 2 * shadow_radius);
	cairo_fill (cr);

	// bottom right
	cairo_matrix_init_scale (&matrix, -1.0f, -1.0f);
	cairo_matrix_translate (&matrix, -width, -height);
	cairo_pattern_set_matrix (pattern, &matrix);
	cairo_rectangle (cr,
			 2 * shadow_radius,
			 height - 2 * shadow_radius,
			 width - 2 * shadow_radius,
			 2 * shadow_radius);
	cairo_fill (cr);

	// clean up
	cairo_pattern_destroy (pattern);
	cairo_surface_destroy (tmp_surface);
	cairo_surface_destroy (new_surface);
}
static cairo_surface_t *
_cairo_boilerplate_gl_create_window (const char 	       *name,
				     cairo_content_t		content,
				     double			width,
				     double			height,
				     double			max_width,
				     double			max_height,
				     cairo_boilerplate_mode_t	mode,
				     void		      **closure)
{
    int rgba_attribs[] = { GLX_RGBA,
			   GLX_RED_SIZE, 1,
			   GLX_GREEN_SIZE, 1,
			   GLX_BLUE_SIZE, 1,
			   GLX_ALPHA_SIZE, 1,
			   GLX_DOUBLEBUFFER,
			   None };

    int msaa_attribs[] = { GLX_RGBA,
			   GLX_RED_SIZE, 1,
			   GLX_GREEN_SIZE, 1,
			   GLX_BLUE_SIZE, 1,
			   GLX_ALPHA_SIZE, 1,
			   GLX_STENCIL_SIZE, 1,
			   GLX_SAMPLES, 4,
			   GLX_SAMPLE_BUFFERS, 1,
			   GLX_DOUBLEBUFFER,
			   None };

    XVisualInfo *vi;
    GLXContext ctx;
    gl_target_closure_t *gltc;
    cairo_surface_t *surface;
    Display *dpy;
    XSetWindowAttributes attr;

    gltc = calloc (1, sizeof (gl_target_closure_t));
    *closure = gltc;

    if (width == 0)
	width = 1;
    if (height == 0)
	height = 1;

    dpy = XOpenDisplay (NULL);
    gltc->dpy = dpy;
    if (!gltc->dpy) {
	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
	free (gltc);
	return NULL;
    }

    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
	XSynchronize (gltc->dpy, 1);

    vi = glXChooseVisual (dpy, DefaultScreen (dpy), msaa_attribs);

    if (vi == NULL)
	vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);

    if (vi == NULL) {
	fprintf (stderr, "Failed to create RGBA, double-buffered visual\n");
	XCloseDisplay (dpy);
	free (gltc);
	return NULL;
    }

    attr.colormap = XCreateColormap (dpy,
				     RootWindow (dpy, vi->screen),
				     vi->visual,
				     AllocNone);
    attr.border_pixel = 0;
    attr.override_redirect = True;
    gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0,
				    width, height, 0, vi->depth,
				    InputOutput, vi->visual,
				    CWOverrideRedirect | CWBorderPixel | CWColormap,
				    &attr);
    XMapWindow (dpy, gltc->drawable);

    ctx = glXCreateContext (dpy, vi, NULL, True);
    XFree (vi);

    gltc->ctx = ctx;
    gltc->device = cairo_glx_device_create (dpy, ctx);

    gltc->surface = surface = cairo_gl_surface_create_for_window (gltc->device,
								  gltc->drawable,
								  ceil (width),
								  ceil (height));
    if (cairo_surface_status (surface))
	_cairo_boilerplate_gl_cleanup (gltc);

    return surface;
}
static cairo_surface_t *
_cairo_boilerplate_gl_create_surface (const char		*name,
				      cairo_content_t		 content,
				      double			 width,
				      double			 height,
				      double			 max_width,
				      double			 max_height,
				      cairo_boilerplate_mode_t	 mode,
				      void		       **closure)
{
    int rgba_attribs[] = { GLX_RGBA,
			   GLX_RED_SIZE, 1,
			   GLX_GREEN_SIZE, 1,
			   GLX_BLUE_SIZE, 1,
			   GLX_ALPHA_SIZE, 1,
			   GLX_DOUBLEBUFFER,
			   None };
    int rgb_attribs[] = { GLX_RGBA,
			  GLX_RED_SIZE, 1,
			  GLX_GREEN_SIZE, 1,
			  GLX_BLUE_SIZE, 1,
			  GLX_DOUBLEBUFFER,
			  None };
    XVisualInfo *visinfo;
    GLXContext ctx;
    gl_target_closure_t *gltc;
    cairo_surface_t *surface;
    Display *dpy;

    gltc = calloc (1, sizeof (gl_target_closure_t));
    *closure = gltc;

    if (width == 0)
	width = 1;
    if (height == 0)
	height = 1;

    dpy = XOpenDisplay (NULL);
    gltc->dpy = dpy;
    if (!gltc->dpy) {
	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
	free (gltc);
	return NULL;
    }

    if (mode == CAIRO_BOILERPLATE_MODE_TEST)
	XSynchronize (gltc->dpy, 1);

    if (content == CAIRO_CONTENT_COLOR)
	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs);
    else
	visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs);

    if (visinfo == NULL) {
	fprintf (stderr, "Failed to create RGB, double-buffered visual\n");
	XCloseDisplay (dpy);
	free (gltc);
	return NULL;
    }

    ctx = glXCreateContext (dpy, visinfo, NULL, True);
    XFree (visinfo);

    gltc->ctx = ctx;
    gltc->device = cairo_glx_device_create (dpy, ctx);

    gltc->surface = surface = cairo_gl_surface_create (gltc->device,
						       content,
						       ceil (width),
						       ceil (height));
    if (cairo_surface_status (surface))
	_cairo_boilerplate_gl_cleanup (gltc);

    return surface;
}
예제 #12
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    char *filename;
    FILE *file;
    cairo_surface_t *surface;
    cairo_status_t status;

    xasprintf (&filename, "%s/reference/%s", ctx->srcdir,
	       "create-from-png-stream.ref.png");

    file = fopen (filename, "rb");
    if (file == NULL) {
	cairo_test_status_t ret;

	ret = CAIRO_TEST_FAILURE;
	if (errno == ENOMEM)
	    ret = cairo_test_status_from_status (ctx, CAIRO_STATUS_NO_MEMORY);

	if (ret != CAIRO_TEST_NO_MEMORY)
	    cairo_test_log (ctx, "Error: failed to open file: %s\n", filename);

	free (filename);
	return ret;
    }

    surface = cairo_image_surface_create_from_png_stream (read_png_from_file,
							  file);

    fclose (file);

    status = cairo_surface_status (surface);
    if (status) {
	cairo_test_status_t ret;

	cairo_surface_destroy (surface);

	ret = cairo_test_status_from_status (ctx, status);
	if (ret != CAIRO_TEST_NO_MEMORY) {
	    cairo_test_log (ctx,
			    "Error: failed to create surface from PNG: %s - %s\n",
			    filename,
			    cairo_status_to_string (status));
	}

	free (filename);

	return ret;
    }

    free (filename);

    /* Pretend we modify the surface data (which detaches the PNG mime data) */
    cairo_surface_flush (surface);
    cairo_surface_mark_dirty (surface);

    cairo_set_source_surface (cr, surface, 0, 0);
    cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
    cairo_paint (cr);

    cairo_surface_destroy (surface);

    return CAIRO_TEST_SUCCESS;
}
예제 #13
0
static void
redraw_handler(struct widget *widget, void *data)
{
	struct fullscreen *fullscreen = data;
	struct rectangle allocation;
	cairo_surface_t *surface;
	cairo_t *cr;
	int i;
	double x, y, border;
	const char *method_name[] = { "default", "center", "zoom", "zoom_crop", "stretch"};

	surface = window_get_surface(fullscreen->window);
	if (surface == NULL ||
	    cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
		fprintf(stderr, "failed to create cairo egl surface\n");
		return;
	}

	widget_get_allocation(fullscreen->widget, &allocation);

	cr = widget_cairo_create(widget);

	cairo_set_source_rgb(cr, 0, 0, 0);
	cairo_paint (cr);

	cairo_set_source_rgb(cr, 0, 0, 1);
	cairo_set_line_width (cr, 10);
	cairo_rectangle(cr, 5, 5, allocation.width - 10, allocation.height - 10);
	cairo_stroke (cr);

	cairo_move_to(cr,
		      allocation.x + 15,
		      allocation.y + 25);
	cairo_set_source_rgb(cr, 1, 1, 1);

	if (fullscreen->fshell) {
		draw_string(cr,
			    "Surface size: %d, %d\n"
			    "Scale: %d, transform: %d\n"
			    "Pointer: %f,%f\n"
			    "Output: %s, present method: %s\n"
			    "Keys: (s)cale, (t)ransform, si(z)e, (m)ethod,\n"
			    "      (o)utput, modes(w)itch, (q)uit\n",
			    fullscreen->width, fullscreen->height,
			    window_get_buffer_scale (fullscreen->window),
			    window_get_buffer_transform (fullscreen->window),
			    fullscreen->pointer_x, fullscreen->pointer_y,
			    method_name[fullscreen->present_method],
			    fullscreen->current_output ? output_get_model(fullscreen->current_output->output): "null");
	} else {
		draw_string(cr,
			    "Surface size: %d, %d\n"
			    "Scale: %d, transform: %d\n"
			    "Pointer: %f,%f\n"
			    "Fullscreen: %d\n"
			    "Keys: (s)cale, (t)ransform, si(z)e, (f)ullscreen, (q)uit\n",
			    fullscreen->width, fullscreen->height,
			    window_get_buffer_scale (fullscreen->window),
			    window_get_buffer_transform (fullscreen->window),
			    fullscreen->pointer_x, fullscreen->pointer_y,
			    fullscreen->fullscreen);
	}

	y = 100;
	i = 0;
	while (y + 60 < fullscreen->height) {
		border = (i++ % 2 == 0) ? 1 : 0.5;

		x = 50;
		cairo_set_line_width (cr, border);
		while (x + 70 < fullscreen->width) {
			if (window_has_focus(fullscreen->window) &&
			    fullscreen->pointer_x >= x && fullscreen->pointer_x < x + 50 &&
			    fullscreen->pointer_y >= y && fullscreen->pointer_y < y + 40) {
				cairo_set_source_rgb(cr, 1, 0, 0);
				cairo_rectangle(cr,
						x, y,
						50, 40);
				cairo_fill(cr);
			}
			cairo_set_source_rgb(cr, 0, 1, 0);
			cairo_rectangle(cr,
					x + border/2.0, y + border/2.0,
					50, 40);
			cairo_stroke(cr);
			x += 60;
		}

		y += 50;
	}

	if (window_has_focus(fullscreen->window) && fullscreen->draw_cursor) {
		cairo_set_source_rgb(cr, 1, 1, 1);
		cairo_set_line_width (cr, 8);
		cairo_move_to(cr,
			      fullscreen->pointer_x - 12,
			      fullscreen->pointer_y - 12);
		cairo_line_to(cr,
			      fullscreen->pointer_x + 12,
			      fullscreen->pointer_y + 12);
		cairo_stroke(cr);

		cairo_move_to(cr,
			      fullscreen->pointer_x + 12,
			      fullscreen->pointer_y - 12);
		cairo_line_to(cr,
			      fullscreen->pointer_x - 12,
			      fullscreen->pointer_y + 12);
		cairo_stroke(cr);

		cairo_set_source_rgb(cr, 0, 0, 0);
		cairo_set_line_width (cr, 4);
		cairo_move_to(cr,
			      fullscreen->pointer_x - 10,
			      fullscreen->pointer_y - 10);
		cairo_line_to(cr,
			      fullscreen->pointer_x + 10,
			      fullscreen->pointer_y + 10);
		cairo_stroke(cr);

		cairo_move_to(cr,
			      fullscreen->pointer_x + 10,
			      fullscreen->pointer_y - 10);
		cairo_line_to(cr,
			      fullscreen->pointer_x - 10,
			      fullscreen->pointer_y + 10);
		cairo_stroke(cr);
	}

	cairo_destroy(cr);
}
예제 #14
0
static cairo_test_status_t
preamble (cairo_test_context_t *ctx)
{
    char *filename;
    cairo_surface_t *surface;
    cairo_status_t status;
    cairo_test_status_t result = CAIRO_TEST_SUCCESS;

    surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
    if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error: expected \"file not found\", but got: %s\n",
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    }
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    surface = cairo_image_surface_create_from_png_stream (no_memory_error, NULL);
    if (cairo_surface_status (surface) != CAIRO_STATUS_NO_MEMORY) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    }
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    surface = cairo_image_surface_create_from_png_stream (read_error, NULL);
    if (cairo_surface_status (surface) != CAIRO_STATUS_READ_ERROR) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    }
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    /* cheekily test error propagation from the user write funcs as well ... */
    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.ref.png");

    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else {
	status = cairo_surface_write_to_png_stream (surface,
					       (cairo_write_func_t) no_memory_error,
					       NULL);
	if (status != CAIRO_STATUS_NO_MEMORY) {
	    result = cairo_test_status_from_status (ctx, status);
	    if (result == CAIRO_TEST_FAILURE) {
		cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
				cairo_status_to_string (status));
	    }
	}

	status = cairo_surface_write_to_png_stream (surface,
						    (cairo_write_func_t) read_error,
						    NULL);
	if (status != CAIRO_STATUS_READ_ERROR) {
	    result = cairo_test_status_from_status (ctx, status);
	    if (result == CAIRO_TEST_FAILURE) {
		cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
				cairo_status_to_string (status));
	    }
	}

	/* and check that error has not propagated to the surface */
	if (cairo_surface_status (surface)) {
	    result = cairo_test_status_from_status (ctx,
						    cairo_surface_status (surface));
	    if (result == CAIRO_TEST_FAILURE) {
		cairo_test_log (ctx, "Error: user write error propagated to surface: %s",
				cairo_status_to_string (cairo_surface_status (surface)));
	    }
	}
    }
    cairo_surface_destroy (surface);
    free (filename);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    /* check that loading alpha/opaque PNGs generate the correct surfaces */
    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.alpha.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    /* check paletted PNGs */
    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.indexed-alpha.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.indexed.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    /* check grayscale PNGs */
    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.gray-alpha.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);
    if (result != CAIRO_TEST_SUCCESS)
	return result;

    xasprintf (&filename, "%s/%s", ctx->srcdir,
	       "create-from-png.gray.ref.png");
    surface = cairo_image_surface_create_from_png (filename);
    if (cairo_surface_status (surface)) {
	result = cairo_test_status_from_status (ctx,
						cairo_surface_status (surface));
	if (result == CAIRO_TEST_FAILURE) {
	    cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
			    filename,
			    cairo_status_to_string (cairo_surface_status (surface)));
	}
    } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
			filename);
	result = CAIRO_TEST_FAILURE;
    }
    free (filename);
    cairo_surface_destroy (surface);

    return result;
}
예제 #15
0
static void cairogen_begin_page(GVJ_t * job)
{
    cairo_t *cr = (cairo_t *) job->context;
    cairo_surface_t *surface;
    cairo_status_t status;

    if (cr == NULL) {
        switch (job->render.id) {
        case FORMAT_PS:
#ifdef CAIRO_HAS_PS_SURFACE
	    surface = cairo_ps_surface_create_for_stream (writer,
			job, job->width, job->height);
#endif
	    break;
        case FORMAT_PDF:
#ifdef CAIRO_HAS_PDF_SURFACE
	    surface = cairo_pdf_surface_create_for_stream (writer,
			job, job->width, job->height);
#endif
	    break;
        case FORMAT_SVG:
#ifdef CAIRO_HAS_SVG_SURFACE
	    surface = cairo_svg_surface_create_for_stream (writer,
			job, job->width, job->height);
#endif
	    break;
        case FORMAT_CAIRO:
        case FORMAT_PNG:
        default:
	    if (job->width >= CAIRO_XMAX || job->height >= CAIRO_YMAX) {
		double scale = MIN((double)CAIRO_XMAX / job->width,
			(double)CAIRO_YMAX / job->height);
		job->width *= scale;
		job->height *= scale;
		job->scale.x *= scale;
		job->scale.y *= scale;
                fprintf(stderr,
                        "%s: graph is too large for cairo-renderer bitmaps. Scaling by %g to fit\n", 
                        job->common->cmdname, scale);
	    }
	    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
			job->width, job->height);
            if (job->common->verbose)
                fprintf(stderr,
                        "%s: allocating a %dK cairo image surface (%d x %d pixels)\n",
                        job->common->cmdname,
			ROUND(job->width * job->height * 4 / 1024.),
			job->width, job->height);
	    break;
        }
	status = cairo_surface_status(surface);
        if (status != CAIRO_STATUS_SUCCESS)  {
		fprintf(stderr, "%s: failure to create cairo surface: %s\n",
			job->common->cmdname,
			cairo_status_to_string(status));
		cairo_surface_destroy (surface);
		return;
	}
        cr = cairo_create(surface);
        cairo_surface_destroy (surface);
        job->context = (void *) cr;
    }

    cairo_scale(cr, job->scale.x, job->scale.y);
    cairo_rotate(cr, -job->rotation * M_PI / 180.);
    cairo_translate(cr, job->translation.x, -job->translation.y);

    cairo_rectangle(cr, job->clip.LL.x, - job->clip.LL.y,
	    job->clip.UR.x - job->clip.LL.x, - (job->clip.UR.y - job->clip.LL.y));
    cairo_clip(cr);
    /* cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); */
}
예제 #16
0
void
setup_tile (gint w, gint h)
{
	cairo_status_t   status;
	cairo_t*         cr          = NULL;
	cairo_surface_t* cr_surf     = NULL;
	cairo_surface_t* tmp         = NULL;
	cairo_surface_t* dummy_surf  = NULL;
	cairo_surface_t* norm_surf   = NULL;
	cairo_surface_t* blur_surf   = NULL;
	gdouble          width       = (gdouble) w;
	gdouble          height      = (gdouble) h;
	raico_blur_t*    blur        = NULL;

	cr_surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
					      3 * BUBBLE_SHADOW_SIZE,
					      3 * BUBBLE_SHADOW_SIZE);
	status = cairo_surface_status (cr_surf);
	if (status != CAIRO_STATUS_SUCCESS)
		g_print ("Error: \"%s\"\n", cairo_status_to_string (status));

	cr = cairo_create (cr_surf);
	status = cairo_status (cr);
	if (status != CAIRO_STATUS_SUCCESS)
	{
		cairo_surface_destroy (cr_surf);
		g_print ("Error: \"%s\"\n", cairo_status_to_string (status));
	}

	// clear and render drop-shadow and bubble-background
	cairo_scale (cr, 1.0f, 1.0f);
	cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
	cairo_paint (cr);
	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);

	if (g_composited)
	{
		draw_shadow (cr,
			     width,
			     height,
			     BUBBLE_SHADOW_SIZE,
			     CORNER_RADIUS);
		cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
		draw_round_rect (cr,
				 1.0f,
				 (gdouble) BUBBLE_SHADOW_SIZE,
				 (gdouble) BUBBLE_SHADOW_SIZE,
				 (gdouble) CORNER_RADIUS,
				 (gdouble) (width - 2.0f * BUBBLE_SHADOW_SIZE),
				 (gdouble) (height - 2.0f* BUBBLE_SHADOW_SIZE));
		cairo_fill (cr);
		cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
		cairo_set_source_rgba (cr,
				       BUBBLE_BG_COLOR_R,
				       BUBBLE_BG_COLOR_G,
				       BUBBLE_BG_COLOR_B,
				       0.95f);
	}
	else
		cairo_set_source_rgb (cr,
				      BUBBLE_BG_COLOR_R,
				      BUBBLE_BG_COLOR_G,
				      BUBBLE_BG_COLOR_B);
	draw_round_rect (cr,
			 1.0f,
			 BUBBLE_SHADOW_SIZE,
			 BUBBLE_SHADOW_SIZE,
			 CORNER_RADIUS,
			 (gdouble) (width - 2.0f * BUBBLE_SHADOW_SIZE),
			 (gdouble) (height - 2.0f * BUBBLE_SHADOW_SIZE));
	cairo_fill (cr);

	tmp = cairo_image_surface_create_for_data (
			cairo_image_surface_get_data (cr_surf),
			cairo_image_surface_get_format (cr_surf),
			3 * BUBBLE_SHADOW_SIZE,
			3 * BUBBLE_SHADOW_SIZE,
			cairo_image_surface_get_stride (cr_surf));
	dummy_surf = copy_surface (tmp);
	cairo_surface_destroy (tmp);

	tmp = cairo_image_surface_create_for_data (
			cairo_image_surface_get_data (dummy_surf),
			cairo_image_surface_get_format (dummy_surf),
			2 * BUBBLE_SHADOW_SIZE,
			2 * BUBBLE_SHADOW_SIZE,
			cairo_image_surface_get_stride (dummy_surf));
	norm_surf = copy_surface (tmp);
	cairo_surface_destroy (tmp);

	blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
	raico_blur_set_radius (blur, 6);
	raico_blur_apply (blur, dummy_surf);
	raico_blur_destroy (blur);

	tmp = cairo_image_surface_create_for_data (
			cairo_image_surface_get_data (dummy_surf),
			cairo_image_surface_get_format (dummy_surf),
			2 * BUBBLE_SHADOW_SIZE,
			2 * BUBBLE_SHADOW_SIZE,
			cairo_image_surface_get_stride (dummy_surf));
	blur_surf = copy_surface (tmp);
	cairo_surface_destroy (tmp);
	cairo_surface_destroy (dummy_surf);

	g_tile = tile_new_for_padding (norm_surf, blur_surf);
	cairo_surface_destroy (norm_surf);
	cairo_surface_destroy (blur_surf);

	cairo_surface_destroy (cr_surf);
	cairo_destroy (cr);
}
예제 #17
0
#include <cairo-pdf.h>
#include <cairo-ps.h>
#include <cairo-svg.h>

#include "c_surface.h"

BEGIN_METHOD_VOID(CairoSurface_free)

	GB.FreeString(&THIS->path);
	cairo_surface_destroy(THIS->surface);

END_METHOD

BEGIN_PROPERTY(CairoSurface_Status)

	GB.ReturnInteger(cairo_surface_status(THIS->surface));

END_PROPERTY

BEGIN_PROPERTY(CairoSurface_Path)

	GB.ReturnString(THIS->path);

END_PROPERTY

BEGIN_METHOD(CairoSurface_Save, GB_STRING path)

	GB.ReturnInteger(cairo_surface_write_to_png(THIS->surface, GB.FileName(STRING(path), LENGTH(path))));

END_METHOD
예제 #18
0
static Eina_Bool _ewk_view_single_smart_repaints_process(Ewk_View_Smart_Data *sd)
{
    Ewk_View_Paint_Context *ctxt;
    Evas_Coord ow, oh;
    void *pixels;
    Eina_Rectangle r = {0, 0, 0, 0};
    const Eina_Rectangle *pr;
    const Eina_Rectangle *pr_end;
    Eina_Tiler *tiler;
    Eina_Iterator *itr;
    cairo_status_t status;
    cairo_surface_t *surface;
    cairo_format_t format;
    cairo_t *cairo;
    size_t count;
    Eina_Bool ret = EINA_TRUE;

    if (sd->animated_zoom.zoom.current < 0.00001) {
        Evas_Object *clip = evas_object_clip_get(sd->backing_store);
        Evas_Coord w, h, cw, ch;
        // reset effects of zoom_weak_set()
        evas_object_image_fill_set
            (sd->backing_store, 0, 0, sd->view.w, sd->view.h);
        evas_object_move(clip, sd->view.x, sd->view.y);

        w = sd->view.w;
        h = sd->view.h;

        ewk_frame_contents_size_get(sd->main_frame, &cw, &ch);
        if (w > cw)
            w = cw;
        if (h > ch)
            h = ch;
        evas_object_resize(clip, w, h);
    }

    pixels = evas_object_image_data_get(sd->backing_store, 1);
    evas_object_image_size_get(sd->backing_store, &ow, &oh);

    if (sd->bg_color.a < 255)
        format = CAIRO_FORMAT_ARGB32;
    else
        format = CAIRO_FORMAT_RGB24;

    surface = cairo_image_surface_create_for_data
        ((unsigned char*)pixels, format, ow, oh, ow * 4);
    status = cairo_surface_status(surface);
    if (status != CAIRO_STATUS_SUCCESS) {
        ERR("could not create surface from data %dx%d: %s",
            ow, oh, cairo_status_to_string(status));
        ret = EINA_FALSE;
        goto error_cairo_surface;
    }
    cairo = cairo_create(surface);
    status = cairo_status(cairo);
    if (status != CAIRO_STATUS_SUCCESS) {
        ERR("could not create cairo from surface %dx%d: %s",
            ow, oh, cairo_status_to_string(status));
        ret = EINA_FALSE;
        goto error_cairo;
    }

    ctxt = ewk_view_paint_context_new(sd->_priv, cairo);
    if (!ctxt) {
        ERR("could not create paint context");
        ret = EINA_FALSE;
        goto error_paint_context;
    }

    tiler = eina_tiler_new(ow, oh);
    if (!tiler) {
        ERR("could not create tiler %dx%d", ow, oh);
        ret = EINA_FALSE;
        goto error_tiler;
    }

    pr = ewk_view_repaints_get(sd->_priv, &count);
    pr_end = pr + count;
    for (; pr < pr_end; pr++)
        eina_tiler_rect_add(tiler, pr);

    itr = eina_tiler_iterator_new(tiler);
    if (!itr) {
        ERR("could not get iterator for tiler");
        ret = EINA_FALSE;
        goto error_iterator;
    }

    int sx, sy;
    ewk_frame_scroll_pos_get(sd->main_frame, &sx, &sy);

    EINA_ITERATOR_FOREACH(itr, r) {
        Eina_Rectangle scrolled_rect = {
            r.x + sx, r.y + sy,
            r.w, r.h
        };

        ewk_view_paint_context_save(ctxt);

        if ((sx) || (sy))
            ewk_view_paint_context_translate(ctxt, -sx, -sy);

        ewk_view_paint_context_clip(ctxt, &scrolled_rect);
        ewk_view_paint_context_paint_contents(ctxt, &scrolled_rect);

        ewk_view_paint_context_restore(ctxt);
        evas_object_image_data_update_add
            (sd->backing_store, r.x, r.y, r.w, r.h);
    }
예제 #19
0
static void
set_source_pixbuf(cairo_t         *cr,
		  const GdkPixbuf *pixbuf,
		  double           src_x,
		  double           src_y,
		  double           src_width,
		  double           src_height)
{
	gint width = gdk_pixbuf_get_width (pixbuf);
	gint height = gdk_pixbuf_get_height (pixbuf);
	guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
	int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
	int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
	int cairo_stride;
	guchar *cairo_pixels;
	cairo_format_t format;
	cairo_surface_t *surface;
	int j;

	if (n_channels == 3)
		format = CAIRO_FORMAT_RGB24;
	else
		format = CAIRO_FORMAT_ARGB32;

	surface = cairo_image_surface_create(format, width, height);
	if (cairo_surface_status(surface)) {
		cairo_set_source_surface(cr, surface, 0, 0);
		return;
	}

	cairo_stride = cairo_image_surface_get_stride(surface);
	cairo_pixels = cairo_image_surface_get_data(surface);

	for (j = height; j; j--) {
		guchar *p = gdk_pixels;
		guchar *q = cairo_pixels;

		if (n_channels == 3) {
			guchar *end = p + 3 * width;

			while (p < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
				q[0] = p[2];
				q[1] = p[1];
				q[2] = p[0];
#else
				q[1] = p[0];
				q[2] = p[1];
				q[3] = p[2];
#endif
				p += 3;
				q += 4;
			}
		} else {
			guchar *end = p + 4 * width;
			guint t1,t2,t3;

#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END

			while (p < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
				MULT(q[0], p[2], p[3], t1);
				MULT(q[1], p[1], p[3], t2);
				MULT(q[2], p[0], p[3], t3);
				q[3] = p[3];
#else
				q[0] = p[3];
				MULT(q[1], p[0], p[3], t1);
				MULT(q[2], p[1], p[3], t2);
				MULT(q[3], p[2], p[3], t3);
#endif

				p += 4;
				q += 4;
			}
#undef MULT
		}

		gdk_pixels += gdk_rowstride;
		cairo_pixels += cairo_stride;
	}
	cairo_surface_mark_dirty(surface);

	cairo_set_source_surface(cr, surface,
				 src_x + .5 * (src_width - width),
				 src_y + .5 * (src_height - height));
	cairo_surface_destroy(surface);
}
예제 #20
0
파일: cairo.c 프로젝트: zartstrom/sway
cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) {
    int chan = gdk_pixbuf_get_n_channels(gdkbuf);
    if (chan < 3) return NULL;

#if GDK_PIXBUF_CHECK_VERSION(2,32,0)
    const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf);
#else
    const guint8* gdkpix = gdk_pixbuf_get_pixels(gdkbuf);
#endif
    if (!gdkpix) {
        return NULL;
    }
    gint w = gdk_pixbuf_get_width(gdkbuf);
    gint h = gdk_pixbuf_get_height(gdkbuf);
    int stride = gdk_pixbuf_get_rowstride(gdkbuf);

    cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32;
    cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h);
    cairo_surface_flush (cs);
    if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) {
        return NULL;
    }

    int cstride = cairo_image_surface_get_stride(cs);
    unsigned char * cpix = cairo_image_surface_get_data(cs);

    if (chan == 3) {
        int i;
        for (i = h; i; --i) {
            const guint8 *gp = gdkpix;
            unsigned char *cp = cpix;
            const guint8* end = gp + 3*w;
            while (gp < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
                cp[0] = gp[2];
                cp[1] = gp[1];
                cp[2] = gp[0];
#else
                cp[1] = gp[0];
                cp[2] = gp[1];
                cp[3] = gp[2];
#endif
                gp += 3;
                cp += 4;
            }
            gdkpix += stride;
            cpix += cstride;
        }
    } else {
        /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255
         * (z/255) = z/256 * 256/255     = z/256 (1 + 1/255)
         *         = z/256 + (z/256)/255 = (z + z/255)/256
         *         # recurse once
         *         = (z + (z + z/255)/256)/256
         *         = (z + z/256 + z/256/255) / 256
         *         # only use 16bit uint operations, loose some precision,
         *         # result is floored.
         *       ->  (z + z>>8)>>8
         *         # add 0x80/255 = 0.5 to convert floor to round
         *       =>  (z+0x80 + (z+0x80)>>8 ) >> 8
         * ------
         * tested as equal to lround(z/255.0) for uint z in [0..0xfe02]
         */
#define PREMUL_ALPHA(x,a,b,z) G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } G_STMT_END
        int i;
        for (i = h; i; --i) {
            const guint8 *gp = gdkpix;
            unsigned char *cp = cpix;
            const guint8* end = gp + 4*w;
            guint z1, z2, z3;
            while (gp < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
                PREMUL_ALPHA(cp[0], gp[2], gp[3], z1);
                PREMUL_ALPHA(cp[1], gp[1], gp[3], z2);
                PREMUL_ALPHA(cp[2], gp[0], gp[3], z3);
                cp[3] = gp[3];
#else
                PREMUL_ALPHA(cp[1], gp[0], gp[3], z1);
                PREMUL_ALPHA(cp[2], gp[1], gp[3], z2);
                PREMUL_ALPHA(cp[3], gp[2], gp[3], z3);
                cp[0] = gp[3];
#endif
                gp += 4;
                cp += 4;
            }
            gdkpix += stride;
            cpix += cstride;
        }
#undef PREMUL_ALPHA
    }
    cairo_surface_mark_dirty(cs);
    return cs;
}
예제 #21
0
static cairo_surface_t *
print_surface_from_drawable (gint32   drawable_ID,
                             GError **error)
{
  GeglBuffer         *buffer   = gimp_drawable_get_buffer (drawable_ID);
  const Babl         *format;
  cairo_surface_t    *surface;
  cairo_status_t      status;
  const gint          width    = gimp_drawable_width  (drawable_ID);
  const gint          height   = gimp_drawable_height (drawable_ID);
  GeglBufferIterator *iter;
  guchar             *pixels;
  gint                stride;
  guint               count    = 0;
  guint               done     = 0;

  if (gimp_drawable_has_alpha (drawable_ID))
    format = babl_format ("cairo-ARGB32");
  else
    format = babl_format ("cairo-RGB24");

  surface = cairo_image_surface_create (gimp_drawable_has_alpha (drawable_ID) ?
                                        CAIRO_FORMAT_ARGB32 :
                                        CAIRO_FORMAT_RGB24,
                                        width, height);

  status = cairo_surface_status (surface);
  if (status != CAIRO_STATUS_SUCCESS)
    {
      switch (status)
        {
        case CAIRO_STATUS_INVALID_SIZE:
          g_set_error_literal (error,
                               GIMP_PLUGIN_PRINT_ERROR,
                               GIMP_PLUGIN_PRINT_ERROR_FAILED,
                               _("Cannot handle the size (either width or height) of the image."));
          break;
        default:
          g_set_error (error,
                       GIMP_PLUGIN_PRINT_ERROR,
                       GIMP_PLUGIN_PRINT_ERROR_FAILED,
                       "Cairo error: %s",
                       cairo_status_to_string (status));
          break;
        }

      return NULL;
    }

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

  iter = gegl_buffer_iterator_new (buffer,
                                   GEGL_RECTANGLE (0, 0, width, height), 0,
                                   format,
                                   GEGL_BUFFER_READ, GEGL_ABYSS_NONE);

  while (gegl_buffer_iterator_next (iter))
    {
      const guchar *src  = iter->data[0];
      guchar       *dest = pixels + iter->roi->y * stride + iter->roi->x * 4;
      gint          y;

      for (y = 0; y < iter->roi->height; y++)
        {
          memcpy (dest, src, iter->roi->width * 4);

          src  += iter->roi->width * 4;
          dest += stride;
        }

      done += iter->roi->height * iter->roi->width;

      if (count++ % 16 == 0)
        gimp_progress_update ((gdouble) done / (width * height));
    }

  g_object_unref (buffer);

  cairo_surface_mark_dirty (surface);

  gimp_progress_update (1.0);

  return surface;
}
예제 #22
0
cairo_test_similar_t
cairo_test_target_has_similar (const cairo_test_context_t *ctx,
			       const cairo_boilerplate_target_t *target)
{
    cairo_surface_t *surface;
    cairo_test_similar_t has_similar;
    cairo_t * cr;
    cairo_surface_t *similar;
    cairo_status_t status;
    void *closure;
    char *path;

    /* ignore image intermediate targets */
    if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE)
	return DIRECT;

    if (getenv ("CAIRO_TEST_IGNORE_SIMILAR"))
	return DIRECT;

    xasprintf (&path, "%s/%s",
	       _cairo_test_mkdir (ctx->output) ? ctx->output : ".",
	       ctx->test_name);

    has_similar = DIRECT;
    do {
	do {
	    surface = (target->create_surface) (path,
						target->content,
						ctx->test->width,
						ctx->test->height,
						ctx->test->width + 25 * NUM_DEVICE_OFFSETS,
						ctx->test->height + 25 * NUM_DEVICE_OFFSETS,
						CAIRO_BOILERPLATE_MODE_TEST,
						&closure);
	    if (surface == NULL)
		goto out;
	} while (cairo_test_malloc_failure (ctx, cairo_surface_status (surface)));

	if (cairo_surface_status (surface))
	    goto out;

	cr = cairo_create (surface);
	cairo_push_group_with_content (cr,
				       cairo_boilerplate_content (target->content));
	similar = cairo_get_group_target (cr);
	status = cairo_surface_status (similar);

	if (cairo_surface_get_type (similar) == cairo_surface_get_type (surface))
	    has_similar = SIMILAR;
	else
	    has_similar = DIRECT;

	cairo_destroy (cr);
	cairo_surface_destroy (surface);

	if (target->cleanup)
	    target->cleanup (closure);
    } while (! has_similar && cairo_test_malloc_failure (ctx, status));
out:
    free (path);

    return has_similar;
}
예제 #23
0
void gui_init(dt_lib_module_t *self)
{
  char filename[PATH_MAX] = { 0 };
  char datadir[PATH_MAX] = { 0 };
  /* initialize ui widgets */
  dt_lib_darktable_t *d = (dt_lib_darktable_t *)g_malloc0(sizeof(dt_lib_darktable_t));
  self->data = (void *)d;

  /* create drawing area */
  self->widget = gtk_event_box_new();

  /* connect callbacks */
  g_signal_connect(G_OBJECT(self->widget), "draw", G_CALLBACK(_lib_darktable_draw_callback), self);
  g_signal_connect(G_OBJECT(self->widget), "button-press-event",
                   G_CALLBACK(_lib_darktable_button_press_callback), self);

  /* create a cairo surface of dt icon */
  char *logo;
  dt_logo_season_t season = get_logo_season();
  if(season != DT_LOGO_SEASON_NONE)
    logo = g_strdup_printf("%%s/pixmaps/idbutton-%d.%%s", (int)season);
  else
    logo = g_strdup("%s/pixmaps/idbutton.%s");

  dt_loc_get_datadir(datadir, sizeof(datadir));
  snprintf(filename, sizeof(filename), logo, datadir, "svg");

  // first we try the SVG
  {
    GError *error = NULL;
    RsvgHandle *svg = rsvg_handle_new_from_file(filename, &error);
    if(!svg || error)
    {
      fprintf(stderr,
              "warning: can't load darktable logo from SVG file `%s', falling back to PNG version\n%s\n",
              filename, error->message);
      g_error_free(error);
      error = NULL;
      goto png_fallback;
    }

    cairo_surface_t *surface;
    cairo_t *cr;

    RsvgDimensionData dimension;
    rsvg_handle_get_dimensions(svg, &dimension);

    int width = DT_PIXEL_APPLY_DPI(dimension.width) * darktable.gui->ppd,
        height = DT_PIXEL_APPLY_DPI(dimension.height) * darktable.gui->ppd;
    int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);

    d->image_buffer = (guint8 *)calloc(stride * height, sizeof(guint8));
    surface
        = dt_cairo_image_surface_create_for_data(d->image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
    if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
    {
      free(d->image_buffer);
      d->image_buffer = NULL;
      g_object_unref(svg);
      fprintf(stderr, "warning: can't load darktable logo from SVG file `%s', falling back to PNG version\n",
              filename);
      goto png_fallback;
    }

    cr = cairo_create(surface);
    cairo_scale(cr, darktable.gui->dpi_factor, darktable.gui->dpi_factor);
    rsvg_handle_render_cairo(svg, cr);
    cairo_destroy(cr);
    cairo_surface_flush(surface);

    d->image = surface;
    g_object_unref(svg);
  }

  goto done;

png_fallback:
  // let's fall back to the PNG
  {
    cairo_surface_t *surface;
    cairo_t *cr;

    snprintf(filename, sizeof(filename), logo, datadir, "png");
    surface = cairo_image_surface_create_from_png(filename);
    if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
    {
      fprintf(stderr, "warning: can't load darktable logo from PNG file `%s'\n", filename);
      d->image = NULL;
      goto done;
    }
    int png_width = cairo_image_surface_get_width(surface),
        png_height = cairo_image_surface_get_height(surface);

    // blow up the PNG. Ugly, but at least it has the correct size afterwards :-/
    int width = DT_PIXEL_APPLY_DPI(png_width) * darktable.gui->ppd,
        height = DT_PIXEL_APPLY_DPI(png_height) * darktable.gui->ppd;
    int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);

    d->image_buffer = (guint8 *)calloc(stride * height, sizeof(guint8));
    d->image
        = dt_cairo_image_surface_create_for_data(d->image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride);
    if(cairo_surface_status(d->image) != CAIRO_STATUS_SUCCESS)
    {
      free(d->image_buffer);
      d->image_buffer = NULL;
      cairo_surface_destroy(surface);
      fprintf(stderr, "warning: can't load darktable logo from PNG file `%s'\n", filename);
      d->image = NULL;
      goto done;
    }

    cr = cairo_create(d->image);
    cairo_rectangle(cr, 0, 0, width, height);
    cairo_scale(cr, darktable.gui->dpi_factor, darktable.gui->dpi_factor);
    cairo_set_source_surface(cr, surface, 0, 0);
    cairo_fill(cr);
    cairo_destroy(cr);
    cairo_surface_flush(d->image);

    cairo_surface_destroy(surface);
  }

done:
  g_free(logo);

  d->image_width = d->image ? dt_cairo_image_surface_get_width(d->image) : 0;
  d->image_height = d->image ? dt_cairo_image_surface_get_height(d->image) : 0;

  /* set size of drawing area */
  gtk_widget_set_size_request(self->widget, d->image_width + (int)DT_PIXEL_APPLY_DPI(180),
                              d->image_height + (int)DT_PIXEL_APPLY_DPI(8));
}
예제 #24
0
static cairo_test_status_t
cairo_test_for_target (cairo_test_context_t		 *ctx,
		       const cairo_boilerplate_target_t	 *target,
		       int				  dev_offset,
		       cairo_bool_t                       similar)
{
    cairo_test_status_t status;
    cairo_surface_t *surface = NULL;
    cairo_t *cr;
    const char *empty_str = "";
    char *offset_str;
    char *base_name, *base_path;
    char *out_png_path;
    char *ref_path = NULL, *ref_png_path, *cmp_png_path = NULL;
    char *new_path = NULL, *new_png_path;
    char *xfail_path = NULL, *xfail_png_path;
    char *base_ref_png_path;
    char *base_new_png_path;
    char *base_xfail_png_path;
    char *diff_png_path;
    char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL;
    cairo_test_status_t ret;
    cairo_content_t expected_content;
    cairo_font_options_t *font_options;
    const char *format;
    cairo_bool_t have_output = FALSE;
    cairo_bool_t have_result = FALSE;
    void *closure;
    double width, height;
    cairo_bool_t have_output_dir;
#if HAVE_MEMFAULT
    int malloc_failure_iterations = ctx->malloc_failure;
    int last_fault_count = 0;
#endif

    /* Get the strings ready that we'll need. */
    format = cairo_boilerplate_content_name (target->content);
    if (dev_offset)
	xasprintf (&offset_str, ".%d", dev_offset);
    else
	offset_str = (char *) empty_str;

    xasprintf (&base_name, "%s.%s.%s%s%s",
	       ctx->test_name,
	       target->name,
	       format,
	       similar ? ".similar" : "",
	       offset_str);

    if (offset_str != empty_str)
      free (offset_str);

    ref_png_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  target->name,
						  target->basename,
						  format,
						  CAIRO_TEST_REF_SUFFIX,
						  CAIRO_TEST_PNG_EXTENSION);
    new_png_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  target->name,
						  target->basename,
						  format,
						  CAIRO_TEST_NEW_SUFFIX,
						  CAIRO_TEST_PNG_EXTENSION);
    xfail_png_path = cairo_test_reference_filename (ctx,
						    base_name,
						    ctx->test_name,
						    target->name,
						    target->basename,
						    format,
						    CAIRO_TEST_XFAIL_SUFFIX,
						    CAIRO_TEST_PNG_EXTENSION);

    base_ref_png_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  NULL, NULL,
						  format,
						  CAIRO_TEST_REF_SUFFIX,
						  CAIRO_TEST_PNG_EXTENSION);
    base_new_png_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  NULL, NULL,
						  format,
						  CAIRO_TEST_NEW_SUFFIX,
						  CAIRO_TEST_PNG_EXTENSION);
    base_xfail_png_path = cairo_test_reference_filename (ctx,
						    base_name,
						    ctx->test_name,
						    NULL, NULL,
						    format,
						    CAIRO_TEST_XFAIL_SUFFIX,
						    CAIRO_TEST_PNG_EXTENSION);

    if (target->file_extension != NULL) {
	ref_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  target->name,
						  target->basename,
						  format,
						  CAIRO_TEST_REF_SUFFIX,
						  target->file_extension);
	new_path = cairo_test_reference_filename (ctx,
						  base_name,
						  ctx->test_name,
						  target->name,
						  target->basename,
						  format,
						  CAIRO_TEST_NEW_SUFFIX,
						  target->file_extension);
	xfail_path = cairo_test_reference_filename (ctx,
						    base_name,
						    ctx->test_name,
						    target->name,
						    target->basename,
						    format,
						    CAIRO_TEST_XFAIL_SUFFIX,
						    target->file_extension);
    }

    have_output_dir = _cairo_test_mkdir (ctx->output);
    xasprintf (&base_path, "%s/%s",
	       have_output_dir ? ctx->output : ".",
	       base_name);
    xasprintf (&out_png_path, "%s" CAIRO_TEST_OUT_PNG, base_path);
    xasprintf (&diff_png_path, "%s" CAIRO_TEST_DIFF_PNG, base_path);

    if (ctx->test->requirements != NULL) {
	const char *required;

	required = target->is_vector ? "target=raster" : "target=vector";
	if (strstr (ctx->test->requirements, required) != NULL) {
	    cairo_test_log (ctx, "Error: Skipping for %s target %s\n",
			    target->is_vector ? "vector" : "raster",
			    target->name);
	    ret = CAIRO_TEST_UNTESTED;
	    goto UNWIND_STRINGS;
	}

	required = target->is_recording ? "target=!recording" : "target=recording";
	if (strstr (ctx->test->requirements, required) != NULL) {
	    cairo_test_log (ctx, "Error: Skipping for %s target %s\n",
			    target->is_recording ? "recording" : "non-recording",
			    target->name);
	    ret = CAIRO_TEST_UNTESTED;
	    goto UNWIND_STRINGS;
	}
    }

    width = ctx->test->width;
    height = ctx->test->height;
    if (width && height) {
	width += dev_offset;
	height += dev_offset;
    }

#if HAVE_MEMFAULT
REPEAT:
    MEMFAULT_CLEAR_FAULTS ();
    MEMFAULT_RESET_LEAKS ();
    ctx->last_fault_count = 0;
    last_fault_count = MEMFAULT_COUNT_FAULTS ();

    /* Pre-initialise fontconfig so that the configuration is loaded without
     * malloc failures (our primary goal is to test cairo fault tolerance).
     */
#if HAVE_FCINIT
    FcInit ();
#endif

    MEMFAULT_ENABLE_FAULTS ();
#endif
    have_output = FALSE;
    have_result = FALSE;

    /* Run the actual drawing code. */
    ret = CAIRO_TEST_SUCCESS;
    surface = (target->create_surface) (base_path,
					target->content,
					width, height,
					ctx->test->width + 25 * NUM_DEVICE_OFFSETS,
					ctx->test->height + 25 * NUM_DEVICE_OFFSETS,
					CAIRO_BOILERPLATE_MODE_TEST,
					&closure);
    if (surface == NULL) {
	cairo_test_log (ctx, "Error: Failed to set %s target\n", target->name);
	ret = CAIRO_TEST_UNTESTED;
	goto UNWIND_STRINGS;
    }

#if HAVE_MEMFAULT
    if (ctx->malloc_failure &&
	MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
	cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY)
    {
	goto REPEAT;
    }
#endif

    if (cairo_surface_status (surface)) {
	MF (MEMFAULT_PRINT_FAULTS ());
	cairo_test_log (ctx, "Error: Created an error surface: %s\n",
			cairo_status_to_string (cairo_surface_status (surface)));
	ret = CAIRO_TEST_FAILURE;
	goto UNWIND_STRINGS;
    }

    /* Check that we created a surface of the expected type. */
    if (cairo_surface_get_type (surface) != target->expected_type) {
	MF (MEMFAULT_PRINT_FAULTS ());
	cairo_test_log (ctx, "Error: Created surface is of type %d (expected %d)\n",
			cairo_surface_get_type (surface), target->expected_type);
	ret = CAIRO_TEST_UNTESTED;
	goto UNWIND_SURFACE;
    }

    /* Check that we created a surface of the expected content,
     * (ignore the artificial CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED value).
     */
    expected_content = cairo_boilerplate_content (target->content);

    if (cairo_surface_get_content (surface) != expected_content) {
	MF (MEMFAULT_PRINT_FAULTS ());
	cairo_test_log (ctx, "Error: Created surface has content %d (expected %d)\n",
			cairo_surface_get_content (surface), expected_content);
	ret = CAIRO_TEST_FAILURE;
	goto UNWIND_SURFACE;
    }

    if (cairo_surface_set_user_data (surface,
				     &cairo_boilerplate_output_basename_key,
				     base_path,
				     NULL))
    {
#if HAVE_MEMFAULT
	cairo_surface_destroy (surface);

	if (target->cleanup)
	    target->cleanup (closure);

	goto REPEAT;
#else
	ret = CAIRO_TEST_FAILURE;
	goto UNWIND_SURFACE;
#endif
    }

    cairo_surface_set_device_offset (surface, dev_offset, dev_offset);

    cr = cairo_create (surface);
    if (cairo_set_user_data (cr, &_cairo_test_context_key, (void*) ctx, NULL)) {
#if HAVE_MEMFAULT
	cairo_destroy (cr);
	cairo_surface_destroy (surface);

	if (target->cleanup)
	    target->cleanup (closure);

	goto REPEAT;
#else
	ret = CAIRO_TEST_FAILURE;
	goto UNWIND_CAIRO;
#endif
    }

    if (similar)
	cairo_push_group_with_content (cr, expected_content);

    /* Clear to transparent (or black) depending on whether the target
     * surface supports alpha. */
    cairo_save (cr);
    cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
    cairo_paint (cr);
    cairo_restore (cr);

    /* Set all components of font_options to avoid backend differences
     * and reduce number of needed reference images. */
    font_options = cairo_font_options_create ();
    cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_ON);
    cairo_font_options_set_antialias (font_options, CAIRO_ANTIALIAS_GRAY);
    cairo_set_font_options (cr, font_options);
    cairo_font_options_destroy (font_options);

    cairo_save (cr);
    alarm (ctx->timeout);
    status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height);
    alarm (0);
    cairo_restore (cr);

    if (similar) {
	cairo_pop_group_to_source (cr);
	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
	cairo_paint (cr);
    }

#if HAVE_MEMFAULT
    MEMFAULT_DISABLE_FAULTS ();

    /* repeat test after malloc failure injection */
    if (ctx->malloc_failure &&
	MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
	(status == CAIRO_TEST_NO_MEMORY ||
	 cairo_status (cr) == CAIRO_STATUS_NO_MEMORY ||
	 cairo_surface_status (surface) == CAIRO_STATUS_NO_MEMORY))
    {
	cairo_destroy (cr);
	cairo_surface_destroy (surface);
	if (target->cleanup)
	    target->cleanup (closure);
	cairo_debug_reset_static_data ();
#if HAVE_FCFINI
	FcFini ();
#endif
	if (MEMFAULT_COUNT_LEAKS () > 0) {
	    MEMFAULT_PRINT_FAULTS ();
	    MEMFAULT_PRINT_LEAKS ();
	}

	goto REPEAT;
    }
#endif

    /* Then, check all the different ways it could fail. */
    if (status) {
	cairo_test_log (ctx, "Error: Function under test failed\n");
	ret = status;
	goto UNWIND_CAIRO;
    }

#if HAVE_MEMFAULT
    if (MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
	MEMFAULT_HAS_FAULTS ())
    {
	VALGRIND_PRINTF ("Unreported memfaults...");
	MEMFAULT_PRINT_FAULTS ();
    }
#endif

    if (target->finish_surface != NULL) {
#if HAVE_MEMFAULT
	/* We need to re-enable faults as most recording-surface processing
	 * is done during cairo_surface_finish().
	 */
	MEMFAULT_CLEAR_FAULTS ();
	last_fault_count = MEMFAULT_COUNT_FAULTS ();
	MEMFAULT_ENABLE_FAULTS ();
#endif

	/* also check for infinite loops whilst replaying */
	alarm (ctx->timeout);
	status = target->finish_surface (surface);
	alarm (0);

#if HAVE_MEMFAULT
	MEMFAULT_DISABLE_FAULTS ();

	if (ctx->malloc_failure &&
	    MEMFAULT_COUNT_FAULTS () - last_fault_count > 0 &&
	    status == CAIRO_STATUS_NO_MEMORY)
	{
	    cairo_destroy (cr);
	    cairo_surface_destroy (surface);
	    if (target->cleanup)
		target->cleanup (closure);
	    cairo_debug_reset_static_data ();
#if HAVE_FCFINI
	    FcFini ();
#endif
	    if (MEMFAULT_COUNT_LEAKS () > 0) {
		MEMFAULT_PRINT_FAULTS ();
		MEMFAULT_PRINT_LEAKS ();
	    }

	    goto REPEAT;
	}
#endif
	if (status) {
	    cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
			    cairo_status_to_string (status));
	    ret = CAIRO_TEST_FAILURE;
	    goto UNWIND_CAIRO;
	}
    }

    /* Skip image check for tests with no image (width,height == 0,0) */
    if (ctx->test->width != 0 && ctx->test->height != 0) {
	cairo_surface_t *ref_image;
	cairo_surface_t *test_image;
	cairo_surface_t *diff_image;
	buffer_diff_result_t result;
	cairo_status_t diff_status;

	if (ref_png_path == NULL) {
	    cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
			    base_name);

	    /* we may be running this test to generate reference images */
	    _xunlink (ctx, out_png_path);
	    /* be more generous as we may need to use external renderers */
	    alarm (4 * ctx->timeout);
	    test_image = target->get_image_surface (surface, 0,
		                                    ctx->test->width,
						    ctx->test->height);
	    alarm (0);
	    diff_status = cairo_surface_write_to_png (test_image, out_png_path);
	    cairo_surface_destroy (test_image);
	    if (diff_status) {
		if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS)
		    ret = CAIRO_TEST_CRASHED;
		else
		    ret = CAIRO_TEST_FAILURE;
		cairo_test_log (ctx,
			        "Error: Failed to write output image: %s\n",
			        cairo_status_to_string (diff_status));
	    }
	    have_output = TRUE;

	    ret = CAIRO_TEST_XFAILURE;
	    goto UNWIND_CAIRO;
	}

	if (target->file_extension != NULL) { /* compare vector surfaces */
	    char *filenames[] = {
		ref_png_path,
		ref_path,
		new_png_path,
		new_path,
		xfail_png_path,
		xfail_path,
		base_ref_png_path,
		base_new_png_path,
		base_xfail_png_path,
	    };

	    xasprintf (&test_filename, "%s.out%s",
		       base_path, target->file_extension);
	    xasprintf (&pass_filename, "%s.pass%s",
		       base_path, target->file_extension);
	    xasprintf (&fail_filename, "%s.fail%s",
		       base_path, target->file_extension);

	    if (cairo_test_file_is_older (pass_filename,
					  filenames,
					  ARRAY_SIZE (filenames)))
	    {
		_xunlink (ctx, pass_filename);
	    }
	    if (cairo_test_file_is_older (fail_filename,
					  filenames,
					  ARRAY_SIZE (filenames)))
	    {
		_xunlink (ctx, fail_filename);
	    }

	    if (cairo_test_files_equal (out_png_path, ref_path)) {
		cairo_test_log (ctx, "Vector surface matches reference.\n");
		have_output = FALSE;
		ret = CAIRO_TEST_SUCCESS;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, new_path)) {
		cairo_test_log (ctx, "Vector surface matches current failure.\n");
		have_output = FALSE;
		ret = CAIRO_TEST_NEW;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, xfail_path)) {
		cairo_test_log (ctx, "Vector surface matches known failure.\n");
		have_output = FALSE;
		ret = CAIRO_TEST_XFAILURE;
		goto UNWIND_CAIRO;
	    }

	    if (cairo_test_files_equal (test_filename, pass_filename)) {
		/* identical output as last known PASS */
		cairo_test_log (ctx, "Vector surface matches last pass.\n");
		have_output = TRUE;
		ret = CAIRO_TEST_SUCCESS;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (test_filename, fail_filename)) {
		/* identical output as last known FAIL, fail */
		cairo_test_log (ctx, "Vector surface matches last fail.\n");
		have_result = TRUE; /* presume these were kept around as well */
		have_output = TRUE;
		ret = CAIRO_TEST_FAILURE;
		goto UNWIND_CAIRO;
	    }
	}

	/* be more generous as we may need to use external renderers */
	alarm (4 * ctx->timeout);
	test_image = target->get_image_surface (surface, 0,
					        ctx->test->width,
						ctx->test->height);
	alarm (0);
	if (cairo_surface_status (test_image)) {
	    cairo_test_log (ctx, "Error: Failed to extract image: %s\n",
			    cairo_status_to_string (cairo_surface_status (test_image)));
	    if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS)
		ret = CAIRO_TEST_CRASHED;
	    else
		ret = CAIRO_TEST_FAILURE;
	    cairo_surface_destroy (test_image);
	    goto UNWIND_CAIRO;
	}

	_xunlink (ctx, out_png_path);
	diff_status = cairo_surface_write_to_png (test_image, out_png_path);
	if (diff_status) {
	    cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
			    cairo_status_to_string (diff_status));
	    cairo_surface_destroy (test_image);
	    ret = CAIRO_TEST_FAILURE;
	    goto UNWIND_CAIRO;
	}
	have_output = TRUE;

	/* binary compare png files (no decompression) */
	if (target->file_extension == NULL) {
	    char *filenames[] = {
		ref_png_path,
		new_png_path,
		xfail_png_path,
		base_ref_png_path,
		base_new_png_path,
		base_xfail_png_path,
	    };

	    xasprintf (&test_filename, "%s", out_png_path);
	    xasprintf (&pass_filename, "%s.pass.png", base_path);
	    xasprintf (&fail_filename, "%s.fail.png", base_path);

	    if (cairo_test_file_is_older (pass_filename,
					  filenames,
					  ARRAY_SIZE (filenames)))
	    {
		_xunlink (ctx, pass_filename);
	    }
	    if (cairo_test_file_is_older (fail_filename,
					  filenames,
					  ARRAY_SIZE (filenames)))
	    {
		_xunlink (ctx, fail_filename);
	    }

	    if (cairo_test_files_equal (test_filename, pass_filename)) {
		cairo_test_log (ctx, "PNG file exactly matches last pass.\n");
                have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_SUCCESS;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, ref_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches reference image.\n");
                have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_SUCCESS;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, new_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches current failure image.\n");
                have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_NEW;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, xfail_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches known failure image.\n");
                have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_XFAILURE;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (test_filename, fail_filename)) {
		cairo_test_log (ctx, "PNG file exactly matches last fail.\n");
		have_result = TRUE; /* presume these were kept around as well */
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_FAILURE;
		goto UNWIND_CAIRO;
	    }
	} else {
	    if (cairo_test_files_equal (out_png_path, ref_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches reference image.\n");
		have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_SUCCESS;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, new_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches current failure image.\n");
		have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_NEW;
		goto UNWIND_CAIRO;
	    }
	    if (cairo_test_files_equal (out_png_path, xfail_png_path)) {
		cairo_test_log (ctx, "PNG file exactly matches known failure image.\n");
		have_result = TRUE;
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_XFAILURE;
		goto UNWIND_CAIRO;
	    }
	}

	if (cairo_test_files_equal (out_png_path, base_ref_png_path)) {
	    cairo_test_log (ctx, "PNG file exactly reference image.\n");
	    have_result = TRUE;
	    cairo_surface_destroy (test_image);
	    ret = CAIRO_TEST_SUCCESS;
	    goto UNWIND_CAIRO;
	}
	if (cairo_test_files_equal (out_png_path, base_new_png_path)) {
	    cairo_test_log (ctx, "PNG file exactly current failure image.\n");
	    have_result = TRUE;
	    cairo_surface_destroy (test_image);
	    ret = CAIRO_TEST_NEW;
	    goto UNWIND_CAIRO;
	}
	if (cairo_test_files_equal (out_png_path, base_xfail_png_path)) {
	    cairo_test_log (ctx, "PNG file exactly known failure image.\n");
	    have_result = TRUE;
	    cairo_surface_destroy (test_image);
	    ret = CAIRO_TEST_XFAILURE;
	    goto UNWIND_CAIRO;
	}

	/* first compare against the ideal reference */
	ref_image = cairo_test_get_reference_image (ctx, base_ref_png_path,
						    target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
	if (cairo_surface_status (ref_image)) {
	    cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
			    base_ref_png_path,
			    cairo_status_to_string (cairo_surface_status (ref_image)));
	    cairo_surface_destroy (test_image);
	    ret = CAIRO_TEST_FAILURE;
	    goto UNWIND_CAIRO;
	}

	diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
						 ctx->test->width,
						 ctx->test->height);

	cmp_png_path = base_ref_png_path;
	diff_status = image_diff (ctx,
				  test_image, ref_image, diff_image,
				  &result);
	_xunlink (ctx, diff_png_path);
	if (diff_status ||
            image_diff_is_failure (&result, target->error_tolerance))
	{
	    /* that failed, so check against the specific backend */
	    ref_image = cairo_test_get_reference_image (ctx, ref_png_path,
							target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
	    if (cairo_surface_status (ref_image)) {
		cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
				ref_png_path,
				cairo_status_to_string (cairo_surface_status (ref_image)));
		cairo_surface_destroy (test_image);
		ret = CAIRO_TEST_FAILURE;
		goto UNWIND_CAIRO;
	    }

	    cmp_png_path = ref_png_path;
	    diff_status = image_diff (ctx,
				      test_image, ref_image,
				      diff_image,
				      &result);
	    if (diff_status)
	    {
		cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
				cairo_status_to_string (diff_status));
		ret = CAIRO_TEST_FAILURE;
	    }
	    else if (image_diff_is_failure (&result, target->error_tolerance))
	    {
		ret = CAIRO_TEST_FAILURE;

		diff_status = cairo_surface_write_to_png (diff_image,
							  diff_png_path);
		if (diff_status) {
		    cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
				    cairo_status_to_string (diff_status));
		} else {
		    have_result = TRUE;
		}

		cairo_test_copy_file (test_filename, fail_filename);
	    }
	    else
	    { /* success */
		cairo_test_copy_file (test_filename, pass_filename);
	    }
	}
	else
	{ /* success */
	    cairo_test_copy_file (test_filename, pass_filename);
	}

	/* If failed, compare against the current image output,
	 * and attempt to detect systematic failures.
	 */
	if (ret == CAIRO_TEST_FAILURE) {
	    char *image_out_path;

	    image_out_path =
		cairo_test_reference_filename (ctx,
					       base_name,
					       ctx->test_name,
					       "image",
					       "image",
					       format,
					       CAIRO_TEST_OUT_SUFFIX,
					       CAIRO_TEST_PNG_EXTENSION);
	    if (image_out_path != NULL) {
		if (cairo_test_files_equal (out_png_path,
					    image_out_path))
		{
		    ret = CAIRO_TEST_XFAILURE;
		}
		else
		{
		    ref_image =
			cairo_image_surface_create_from_png (image_out_path);
		    if (cairo_surface_status (ref_image) == CAIRO_STATUS_SUCCESS)
		    {
			diff_status = image_diff (ctx,
						  test_image, ref_image,
						  diff_image,
						  &result);
			if (diff_status == CAIRO_STATUS_SUCCESS &&
			    !image_diff_is_failure (&result, target->error_tolerance))
			{
			    ret = CAIRO_TEST_XFAILURE;
			}

			cairo_surface_destroy (ref_image);
		    }
		}

		free (image_out_path);
	    }
	}

	cairo_surface_destroy (test_image);
	cairo_surface_destroy (diff_image);
    }

    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
	cairo_test_log (ctx, "Error: Function under test left cairo status in an error state: %s\n",
			cairo_status_to_string (cairo_status (cr)));
	ret = CAIRO_TEST_ERROR;
	goto UNWIND_CAIRO;
    }

UNWIND_CAIRO:
    free (test_filename);
    free (fail_filename);
    free (pass_filename);

    test_filename = fail_filename = pass_filename = NULL;

#if HAVE_MEMFAULT
    if (ret == CAIRO_TEST_FAILURE)
	MEMFAULT_PRINT_FAULTS ();
#endif
    cairo_destroy (cr);
UNWIND_SURFACE:
    cairo_surface_destroy (surface);

    if (target->cleanup)
	target->cleanup (closure);

#if HAVE_MEMFAULT
    cairo_debug_reset_static_data ();

#if HAVE_FCFINI
    FcFini ();
#endif

    if (MEMFAULT_COUNT_LEAKS () > 0) {
	if (ret != CAIRO_TEST_FAILURE)
	    MEMFAULT_PRINT_FAULTS ();
	MEMFAULT_PRINT_LEAKS ();
    }

    if (ret == CAIRO_TEST_SUCCESS && --malloc_failure_iterations > 0)
	goto REPEAT;
#endif

    if (have_output)
	cairo_test_log (ctx, "OUTPUT: %s\n", out_png_path);

    if (have_result) {
	if (cmp_png_path == NULL) {
	    /* XXX presume we matched the normal ref last time */
	    cmp_png_path = ref_png_path;
	}
	cairo_test_log (ctx,
			"REFERENCE: %s\nDIFFERENCE: %s\n",
			cmp_png_path, diff_png_path);
    }

UNWIND_STRINGS:
    free (out_png_path);
    free (ref_png_path);
    free (base_ref_png_path);
    free (ref_path);
    free (new_png_path);
    free (base_new_png_path);
    free (new_path);
    free (xfail_png_path);
    free (base_xfail_png_path);
    free (xfail_path);
    free (diff_png_path);
    free (base_path);
    free (base_name);

    return ret;
}
예제 #25
0
// maybe this should be (partly) in common/imageio.[c|h]?
static void _lib_import_update_preview(GtkFileChooser *file_chooser, gpointer data)
{
  GtkWidget *preview;
  char *filename;
  GdkPixbuf *pixbuf = NULL;
  gboolean have_preview = FALSE, no_preview_fallback = FALSE;

  preview = GTK_WIDGET(data);
  filename = gtk_file_chooser_get_preview_filename(file_chooser);

  if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
  {
    no_preview_fallback = TRUE;
  }
  else
  {
    // don't create dng thumbnails to avoid crashes in libtiff when these are hdr:
    char *c = filename + strlen(filename);
    while(c > filename && *c != '.') c--;
    if(!strcasecmp(c, ".dng")) no_preview_fallback = TRUE;
  }

  // unfortunately we can not use following, because frequently it uses wrong orientation
  // pixbuf = gdk_pixbuf_new_from_file_at_size(filename, 128, 128, NULL);

  have_preview = (pixbuf != NULL);
  if(!have_preview && !no_preview_fallback)
  {
    uint8_t *buffer = NULL;
    size_t size;
    char *mime_type = NULL;
    if(!dt_exif_get_thumbnail(filename, &buffer, &size, &mime_type))
    {
      // Scale the image to the correct size
      GdkPixbuf *tmp;
      GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
      if (!gdk_pixbuf_loader_write(loader, buffer, size, NULL)) goto cleanup;
      if (!(tmp = gdk_pixbuf_loader_get_pixbuf(loader))) goto cleanup;
      float ratio = 1.0 * gdk_pixbuf_get_height(tmp) / gdk_pixbuf_get_width(tmp);
      int width = 128, height = 128 * ratio;
      pixbuf = gdk_pixbuf_scale_simple(tmp, width, height, GDK_INTERP_BILINEAR);

      have_preview = TRUE;

    cleanup:
      gdk_pixbuf_loader_close(loader, NULL);
      free(mime_type);
      free(buffer);
      g_object_unref(loader); // This should clean up tmp as well
    }
  }
  if(have_preview && !no_preview_fallback)
  {
    // get image orientation
    dt_image_t img = { 0 };
    (void)dt_exif_read(&img, filename);

    // Rotate the image to the correct orientation
    GdkPixbuf *tmp = pixbuf;

    if(img.orientation == ORIENTATION_ROTATE_CCW_90_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
    }
    else if(img.orientation == ORIENTATION_ROTATE_CW_90_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_CLOCKWISE);
    }
    else if(img.orientation == ORIENTATION_ROTATE_180_DEG)
    {
      tmp = gdk_pixbuf_rotate_simple(pixbuf, GDK_PIXBUF_ROTATE_UPSIDEDOWN);
    }

    if(pixbuf != tmp)
    {
      g_object_unref(pixbuf);
      pixbuf = tmp;
    }
  }
  if(no_preview_fallback || !have_preview)
  {
    /* load the dt logo as a brackground */
    char dtlogo[PATH_MAX] = { 0 };
    char datadir[PATH_MAX] = { 0 };
    char *logo;
    dt_logo_season_t season = get_logo_season();
    if(season != DT_LOGO_SEASON_NONE)
      logo = g_strdup_printf("%%s/pixmaps/idbutton-%d.svg", (int)season);
    else
      logo = g_strdup("%s/pixmaps/idbutton.svg");

    dt_loc_get_datadir(datadir, sizeof(datadir));
    snprintf(dtlogo, sizeof(dtlogo), logo, datadir);
    g_free(logo);
    RsvgHandle *svg = rsvg_handle_new_from_file(dtlogo, NULL);
    if(svg)
    {
      cairo_surface_t *surface;
      cairo_t *cr;

      RsvgDimensionData dimension;
      rsvg_handle_get_dimensions(svg, &dimension);

      float svg_size = MAX(dimension.width, dimension.height);
      float final_size = 128;
      float factor = final_size / svg_size;
      float final_width = dimension.width * factor * darktable.gui->ppd,
            final_height = dimension.height * factor * darktable.gui->ppd;
      int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, final_width);

      guint8 *image_buffer = (guint8 *)calloc(stride * final_height, sizeof(guint8));
      surface = dt_cairo_image_surface_create_for_data(image_buffer, CAIRO_FORMAT_ARGB32, final_width,
                                                       final_height, stride);
      if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
      {
        free(image_buffer);
        image_buffer = NULL;
      }
      else
      {
        cr = cairo_create(surface);
        cairo_scale(cr, factor, factor);
        rsvg_handle_render_cairo(svg, cr);
        cairo_destroy(cr);
        cairo_surface_flush(surface);
        pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, final_width / darktable.gui->ppd,
                                             final_height / darktable.gui->ppd);
        cairo_surface_destroy(surface);
        free(image_buffer);
      }
      g_object_unref(svg);
    }

    have_preview = TRUE;
  }
  if(have_preview) gtk_image_set_from_pixbuf(GTK_IMAGE(preview), pixbuf);
  if(pixbuf) g_object_unref(pixbuf);
  g_free(filename);

  gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview);
}
예제 #26
0
static cairo_status_t
png_diff (const char *filename_a,
	  const char *filename_b,
	  const char *filename_diff,
	  int		ax,
	  int		ay,
	  int		bx,
	  int		by,
	  buffer_diff_result_t *result)
{
    cairo_surface_t *surface_a;
    cairo_surface_t *surface_b;
    cairo_surface_t *surface_diff;
    cairo_status_t status;

    surface_a = cairo_image_surface_create_from_png (filename_a);
    status = cairo_surface_status (surface_a);
    if (status) {
	fprintf (stderr, "Error: Failed to create surface from %s: %s\n",
		 filename_a, cairo_status_to_string (status));
	return status;
    }

    surface_b = cairo_image_surface_create_from_png (filename_b);
    status = cairo_surface_status (surface_b);
    if (status) {
	fprintf (stderr, "Error: Failed to create surface from %s: %s\n",
		 filename_b, cairo_status_to_string (status));
	cairo_surface_destroy (surface_a);
	return status;
    }

    if (ax || ay) {
	extract_sub_surface (&surface_a, ax, ay);
	ax = ay = 0;
    }

    if (bx || by) {
	extract_sub_surface (&surface_b, bx, by);
	bx = by = 0;
    }

    status = cairo_surface_status (surface_a);
    if (status) {
	fprintf (stderr, "Error: Failed to extract surface from %s: %s\n",
		 filename_a, cairo_status_to_string (status));
	cairo_surface_destroy (surface_a);
	cairo_surface_destroy (surface_b);
	return status;
    }
    status = cairo_surface_status (surface_b);
    if (status) {
	fprintf (stderr, "Error: Failed to extract surface from %s: %s\n",
		 filename_b, cairo_status_to_string (status));
	cairo_surface_destroy (surface_a);
	cairo_surface_destroy (surface_b);
	return status;
    }

    surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
					       cairo_image_surface_get_width (surface_a),
					       cairo_image_surface_get_height (surface_a));
    status = cairo_surface_status (surface_diff);
    if (status) {
	fprintf (stderr,
		 "Error: Failed to allocate surface to hold differences\n");
	cairo_surface_destroy (surface_a);
	cairo_surface_destroy (surface_b);
	return CAIRO_STATUS_NO_MEMORY;
    }

    status = image_diff (NULL,
			 surface_a, surface_b, surface_diff,
			 result);

    cairo_surface_destroy (surface_a);
    cairo_surface_destroy (surface_b);
    cairo_surface_destroy (surface_diff);

    _xunlink (filename_diff);
    if (status == CAIRO_STATUS_SUCCESS &&
	result->pixels_changed)
    {
	status = write_png (surface_diff, filename_diff);
    }


    return status;
}
static cairo_bool_t
check_result (cairo_test_context_t *ctx,
	      const cairo_boilerplate_target_t *target,
	      const char *test_name,
	      const char *base_name,
	      cairo_surface_t *surface)
{
    const char *format;
    char *ref_name;
    char *png_name;
    char *diff_name;
    cairo_surface_t *test_image, *ref_image, *diff_image;
    buffer_diff_result_t result;
    cairo_status_t status;
    cairo_bool_t ret;

    /* XXX log target, OUTPUT, REFERENCE, DIFFERENCE for index.html */

    if (target->finish_surface != NULL) {
	status = target->finish_surface (surface);
	if (status) {
	    cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
		    cairo_status_to_string (status));
	    cairo_surface_destroy (surface);
	    return FALSE;
	}
    }

    xasprintf (&png_name,  "%s.out.png", base_name);
    xasprintf (&diff_name, "%s.diff.png", base_name);

    test_image = target->get_image_surface (surface, 0, SIZE, SIZE);
    if (cairo_surface_status (test_image)) {
	cairo_test_log (ctx, "Error: Failed to extract page: %s\n",
		        cairo_status_to_string (cairo_surface_status (test_image)));
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }

    _xunlink (ctx, png_name);
    status = cairo_surface_write_to_png (test_image, png_name);
    if (status) {
	cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
		cairo_status_to_string (status));
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }

    format = cairo_boilerplate_content_name (target->content);
    ref_name = cairo_test_reference_filename (ctx,
					      base_name,
					      test_name,
					      target->name,
					      target->basename,
					      format,
					      CAIRO_TEST_REF_SUFFIX,
					      CAIRO_TEST_PNG_EXTENSION);
    if (ref_name == NULL) {
	cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
		        base_name);
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	return FALSE;
    }


    ref_image = cairo_test_get_reference_image (ctx, ref_name,
	    target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
    if (cairo_surface_status (ref_image)) {
	cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
		        ref_name,
		cairo_status_to_string (cairo_surface_status (ref_image)));
	cairo_surface_destroy (ref_image);
	cairo_surface_destroy (test_image);
	free (png_name);
	free (diff_name);
	free (ref_name);
	return FALSE;
    }

    diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
	    SIZE, SIZE);

    ret = TRUE;
    status = image_diff (ctx,
	    test_image, ref_image, diff_image,
	    &result);
    _xunlink (ctx, diff_name);
    if (status) {
	cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
			cairo_status_to_string (status));
	ret = FALSE;
    } else if (result.pixels_changed &&
	       result.max_diff > target->error_tolerance)
    {
	ret = FALSE;

	status = cairo_surface_write_to_png (diff_image, diff_name);
	if (status) {
	    cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
		    cairo_status_to_string (status));
	}
    }

    cairo_surface_destroy (test_image);
    cairo_surface_destroy (diff_image);
    free (png_name);
    free (diff_name);
    free (ref_name);

    return ret;
}
예제 #28
0
파일: i3lock.c 프로젝트: 1u4nx/i3lock
int main(int argc, char *argv[]) {
    struct passwd *pw;
    char *username;
    char *image_path = NULL;
    int ret;
    struct pam_conv conv = {conv_callback, NULL};
    int curs_choice = CURS_NONE;
    int o;
    int optind = 0;
    struct option longopts[] = {
        {"version", no_argument, NULL, 'v'},
        {"nofork", no_argument, NULL, 'n'},
        {"beep", no_argument, NULL, 'b'},
        {"dpms", no_argument, NULL, 'd'},
        {"color", required_argument, NULL, 'c'},
        {"pointer", required_argument, NULL, 'p'},
        {"debug", no_argument, NULL, 0},
        {"help", no_argument, NULL, 'h'},
        {"no-unlock-indicator", no_argument, NULL, 'u'},
        {"image", required_argument, NULL, 'i'},
        {"tiling", no_argument, NULL, 't'},
        {"ignore-empty-password", no_argument, NULL, 'e'},
        {"inactivity-timeout", required_argument, NULL, 'I'},
        {"show-failed-attempts", no_argument, NULL, 'f'},
        {"login_failed_execute", required_argument, NULL, 0},
        {NULL, no_argument, NULL, 0}};

    if ((pw = getpwuid(getuid())) == NULL)
        err(EXIT_FAILURE, "getpwuid() failed");
    if ((username = pw->pw_name) == NULL)
        errx(EXIT_FAILURE, "pw->pw_name is NULL.\n");

    char *optstring = "hvnbdc:p:ui:teI:f";
    while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) {
        switch (o) {
            case 'v':
                errx(EXIT_SUCCESS, "version " VERSION " © 2010 Michael Stapelberg");
            case 'n':
                dont_fork = true;
                break;
            case 'b':
                beep = true;
                break;
            case 'd':
                fprintf(stderr, "DPMS support has been removed from i3lock. Please see the manpage i3lock(1).\n");
                break;
            case 'I': {
                int time = 0;
                if (sscanf(optarg, "%d", &time) != 1 || time < 0)
                    errx(EXIT_FAILURE, "invalid timeout, it must be a positive integer\n");
                inactivity_timeout = time;
                break;
            }
            case 'c': {
                char *arg = optarg;

                /* Skip # if present */
                if (arg[0] == '#')
                    arg++;

                if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1)
                    errx(EXIT_FAILURE, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb\n");

                break;
            }
            case 'u':
                unlock_indicator = false;
                break;
            case 'i':
                image_path = strdup(optarg);
                break;
            case 't':
                tile = true;
                break;
            case 'p':
                if (!strcmp(optarg, "win")) {
                    curs_choice = CURS_WIN;
                } else if (!strcmp(optarg, "default")) {
                    curs_choice = CURS_DEFAULT;
                } else {
                    errx(EXIT_FAILURE, "i3lock: Invalid pointer type given. Expected one of \"win\" or \"default\".\n");
                }
                break;
            case 'e':
                ignore_empty_password = true;
                break;
            case 0:
                if (strcmp(longopts[optind].name, "debug") == 0)
                    debug_mode = true;
                if ((strcmp(longopts[optind].name, "login_failed_execute") == 0) && optarg)
                    login_failed_execute = optarg;
                break;
            case 'f':
                show_failed_attempts = true;
                break;
            default:
                errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]"
                                   " [-i image.png] [-t] [-e] [-I timeout] [-f] [--login_failed_execute command]");
        }
    }

    /* We need (relatively) random numbers for highlighting a random part of
     * the unlock indicator upon keypresses. */
    srand(time(NULL));

    /* Initialize PAM */
    if ((ret = pam_start("i3lock", username, &conv, &pam_handle)) != PAM_SUCCESS)
        errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret));

    if ((ret = pam_set_item(pam_handle, PAM_TTY, getenv("DISPLAY"))) != PAM_SUCCESS)
        errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret));

/* Using mlock() as non-super-user seems only possible in Linux. Users of other
 * operating systems should use encrypted swap/no swap (or remove the ifdef and
 * run i3lock as super-user). */
#if defined(__linux__)
    /* Lock the area where we store the password in memory, we don’t want it to
     * be swapped to disk. Since Linux 2.6.9, this does not require any
     * privileges, just enough bytes in the RLIMIT_MEMLOCK limit. */
    if (mlock(password, sizeof(password)) != 0)
        err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK");
#endif

    /* Double checking that connection is good and operatable with xcb */
    int screennr;
    if ((conn = xcb_connect(NULL, &screennr)) == NULL ||
        xcb_connection_has_error(conn))
        errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?");

    if (xkb_x11_setup_xkb_extension(conn,
                                    XKB_X11_MIN_MAJOR_XKB_VERSION,
                                    XKB_X11_MIN_MINOR_XKB_VERSION,
                                    0,
                                    NULL,
                                    NULL,
                                    &xkb_base_event,
                                    &xkb_base_error) != 1)
        errx(EXIT_FAILURE, "Could not setup XKB extension.");

    static const xcb_xkb_map_part_t required_map_parts =
        (XCB_XKB_MAP_PART_KEY_TYPES |
         XCB_XKB_MAP_PART_KEY_SYMS |
         XCB_XKB_MAP_PART_MODIFIER_MAP |
         XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
         XCB_XKB_MAP_PART_KEY_ACTIONS |
         XCB_XKB_MAP_PART_VIRTUAL_MODS |
         XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);

    static const xcb_xkb_event_type_t required_events =
        (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
         XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
         XCB_XKB_EVENT_TYPE_STATE_NOTIFY);

    xcb_xkb_select_events(
        conn,
        xkb_x11_get_core_keyboard_device_id(conn),
        required_events,
        0,
        required_events,
        required_map_parts,
        required_map_parts,
        0);

    /* When we cannot initially load the keymap, we better exit */
    if (!load_keymap())
        errx(EXIT_FAILURE, "Could not load keymap");

    const char *locale = getenv("LC_ALL");
    if (!locale)
        locale = getenv("LC_CTYPE");
    if (!locale)
        locale = getenv("LANG");
    if (!locale) {
        if (debug_mode)
            fprintf(stderr, "Can't detect your locale, fallback to C\n");
        locale = "C";
    }

    load_compose_table(locale);

    xinerama_init();
    xinerama_query_screens();

    screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

    last_resolution[0] = screen->width_in_pixels;
    last_resolution[1] = screen->height_in_pixels;

    xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK,
                                 (uint32_t[]){XCB_EVENT_MASK_STRUCTURE_NOTIFY});

    if (image_path) {
        /* Create a pixmap to render on, fill it with the background color */
        img = cairo_image_surface_create_from_png(image_path);
        /* In case loading failed, we just pretend no -i was specified. */
        if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) {
            fprintf(stderr, "Could not load image \"%s\": %s\n",
                    image_path, cairo_status_to_string(cairo_surface_status(img)));
            img = NULL;
        }
    }

    /* Pixmap on which the image is rendered to (if any) */
    xcb_pixmap_t bg_pixmap = draw_image(last_resolution);

    /* open the fullscreen window, already with the correct pixmap in place */
    win = open_fullscreen_window(conn, screen, color, bg_pixmap);
    xcb_free_pixmap(conn, bg_pixmap);

    pid_t pid = fork();
    /* The pid == -1 case is intentionally ignored here:
     * While the child process is useful for preventing other windows from
     * popping up while i3lock blocks, it is not critical. */
    if (pid == 0) {
        /* Child */
        close(xcb_get_file_descriptor(conn));
        raise_loop(win);
        exit(EXIT_SUCCESS);
    }

    cursor = create_cursor(conn, screen, win, curs_choice);

    grab_pointer_and_keyboard(conn, screen, cursor);
    /* Load the keymap again to sync the current modifier state. Since we first
     * loaded the keymap, there might have been changes, but starting from now,
     * we should get all key presses/releases due to having grabbed the
     * keyboard. */
    (void)load_keymap();

    /* Initialize the libev event loop. */
    main_loop = EV_DEFAULT;
    if (main_loop == NULL)
        errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n");

    struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1);
    struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1);
    struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1);

    ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
    ev_io_start(main_loop, xcb_watcher);

    ev_check_init(xcb_check, xcb_check_cb);
    ev_check_start(main_loop, xcb_check);

    ev_prepare_init(xcb_prepare, xcb_prepare_cb);
    ev_prepare_start(main_loop, xcb_prepare);

    /* Invoke the event callback once to catch all the events which were
     * received up until now. ev will only pick up new events (when the X11
     * file descriptor becomes readable). */
    ev_invoke(main_loop, xcb_check, 0);
    ev_loop(main_loop, 0);
}
예제 #29
0
static GObject*
hippo_image_cache_parse(HippoObjectCache      *cache,
                        const char            *url,
                        const char            *content_type,
                        GString               *content,
                        GError               **error_p)
{
    cairo_surface_t *csurface;
    HippoSurface *surface;

    g_debug("image cache parse '%s'", url);
    
    if (has_prefix(content, PNG_MAGIC_PREFIX)) {
        GStringReader reader;
        
        reader.str = content;
        reader.already_read = 0;
        
        csurface =
            cairo_image_surface_create_from_png_stream(gstring_read_func,
                                                       &reader);
        
        if (csurface != NULL && cairo_surface_status(csurface) == CAIRO_STATUS_SUCCESS) {
            surface = hippo_surface_new(csurface);
            cairo_surface_destroy(csurface);
        } else {
            const char *msg;
            
            if (csurface) {
                msg = cairo_status_to_string(cairo_surface_status(csurface));
                cairo_surface_destroy(csurface);
            } else {
                msg = _("Corrupt image");
            }
            
            surface = NULL;
            g_set_error(error_p,
                        g_quark_from_string("cairo-surface-error"),
                        0, msg);                    
            goto failed;
        }
    } else if (has_prefix(content, JPEG_MAGIC_PREFIX)) {
        csurface = hippo_parse_jpeg(content->str, content->len, error_p);
        if (csurface == NULL) {
            g_debug("JPEG parse failed for '%s'", url);
            goto failed;
        }
        surface = hippo_surface_new(csurface);
        cairo_surface_destroy(csurface);
    } else {
        g_debug("Unknown image format for '%s'", url);
        g_set_error(error_p, HIPPO_ERROR, HIPPO_ERROR_FAILED, _("Unknown image format"));
        goto failed;
    }

    return G_OBJECT(surface);
    
  failed:
    g_debug("Image parse failed for '%s'", url);
    
    g_assert(error_p == NULL || *error_p != NULL);
    
    return NULL;
}
예제 #30
0
static GpStatus
draw_tile_flipXY_texture (cairo_t *ct, GpBitmap *bitmap, GpTexture *brush)
{
	cairo_surface_t *original = NULL;
	cairo_surface_t *texture;
	cairo_pattern_t *pat;
	GpMatrix	tempMatrix;
	GpRect		*rect = &brush->rectangle;
	GpStatus	status;
	cairo_t		*ct2;
	BYTE *premul = NULL;

	if (!rect)
		return InvalidParameter;

	gdip_bitmap_ensure_surface (bitmap);

	if (gdip_bitmap_format_needs_premultiplication (bitmap)) {
		premul = gdip_bitmap_get_premultiplied_scan0 (bitmap);
		if (premul) {
			ActiveBitmapData *data = bitmap->active_bitmap;
			original = cairo_image_surface_create_for_data (premul, CAIRO_FORMAT_ARGB32, 
				data->width, data->height, data->stride);
		}
	}

	/* if premul isn't required (or couldn't be computed, e.g. out of memory) */
	if (!original)
		original = bitmap->surface;

	/* Use the original as a pattern */
	pat = cairo_pattern_create_for_surface (original);
	status = gdip_get_pattern_status(pat);
	if (status != Ok)
		goto cleanup;

	cairo_pattern_set_extend (pat, CAIRO_EXTEND_REPEAT);

	/* texture surface to be created */
	texture = cairo_surface_create_similar (original, from_cairoformat_to_content (bitmap->cairo_format),
						2 * rect->Width, 2 * rect->Height);
	status = gdip_get_status (cairo_surface_status (texture));
	if (status != Ok) {
		cairo_pattern_destroy (pat);
		goto cleanup;
	}

	/* Draw upper left part of the texture */
	ct2 = cairo_create (texture);
	cairo_set_source (ct2, pat);
	cairo_rectangle (ct2, 0, 0, rect->Width, rect->Height);
	cairo_fill (ct2);

	/* Not sure if this is a bug, but using rect->Height - 1 avoids the seam. */
	cairo_matrix_init_identity (&tempMatrix);
	cairo_matrix_translate (&tempMatrix, 0, rect->Height - 1);
	/* scale in -Y direction to flip along Y */
	cairo_matrix_scale (&tempMatrix, 1.0, -1.0);
	cairo_pattern_set_matrix (pat, &tempMatrix);

	/* Draw lower left part of the texture */
	cairo_translate (ct2, 0, rect->Height);
	cairo_set_source (ct2, pat);
	cairo_rectangle (ct2, 0, 0, rect->Width, rect->Height);
	cairo_fill (ct2);

	/* Reset the pattern matrix and do fresh transformation */
	cairo_matrix_init_identity (&tempMatrix);

	/* Not sure if this is a bug, but using rect->Width - 1 avoids the seam. */
	cairo_matrix_translate (&tempMatrix, rect->Width - 1, 0);

	/* scale in -X direction to flip along X */
	cairo_matrix_scale (&tempMatrix, -1.0, 1.0);
	cairo_pattern_set_matrix (pat, &tempMatrix);

	/* Draw upper right part of the texture */
	cairo_translate (ct2, rect->Width, -rect->Height);
	cairo_set_source (ct2, pat);
	cairo_rectangle (ct2, 0, 0, rect->Width, rect->Height);
	cairo_fill (ct2);

	/* Not sure if this is a bug, but using rect->Height - 1 avoids the seam. */
	cairo_matrix_translate (&tempMatrix, 0, rect->Height - 1);

	/* scale in -Y direction to flip along Y */
	cairo_matrix_scale (&tempMatrix, 1.0, -1.0);
	cairo_pattern_set_matrix (pat, &tempMatrix);

	/* Draw lower right part of the texture */
	cairo_translate (ct2, 0, rect->Height);
	cairo_set_source (ct2, pat);
	cairo_rectangle (ct2, 0, 0, rect->Width, rect->Height);
	cairo_fill (ct2);
	cairo_destroy(ct2);

	brush->pattern = cairo_pattern_create_for_surface (texture);
	status = gdip_get_pattern_status(brush->pattern);
	if (status != Ok) {
		cairo_pattern_destroy (pat);
		cairo_surface_destroy (texture);
		goto cleanup;
	}
	cairo_pattern_set_extend (brush->pattern, CAIRO_EXTEND_REPEAT);

	cairo_pattern_destroy (pat);
	cairo_surface_destroy (texture);

	status = gdip_get_status (cairo_status (ct));

cleanup:
	if (premul) {
		cairo_surface_destroy (original);
		GdipFree (premul);
	}
	return status;
}