// Copyright (c) 1999-2005 // Motorola, Inc., ALL RIGHTS RESERVED #include #include #include #include #include #include #include #include #include using namespace std; #ifdef __GNUG__ #define COPY(value) strdup(value) #include #include #include #include #include // cairo #include #include #include // cairo #include #else #define COPY(value) _strdup(value) #include #endif static bool isActive; struct NavMapImage { char* data;/*!data)+(img->size), data, length); img->size += length; } // Really never called static void flush_data_fn(png_struct* png_ptr) { // nothing to do } static void unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data){ int i; for (i = 0; i < row_info->rowbytes; i += 4) { unsigned char *b = &data[i]; unsigned int pixel; unsigned char alpha; memcpy (&pixel, b, sizeof (unsigned int)); alpha = (pixel & 0xff000000) >> 24; if (alpha == 0) { b[0] = b[1] = b[2] = b[3] = 0; } else { b[0] = (((pixel & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha; b[1] = (((pixel & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha; b[2] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha; b[3] = alpha; } } } void write_png(char * buffer, int width, int height, NavMapImage *target) { int i; png_struct *png; png_info *info; png_byte **rows; png_color_16 white; int stride = PNG_BPP * width; rows =(png_byte**) malloc (height * sizeof(png_byte*)); for (i = 0; i < height; i++) { rows[i] = (png_byte*) buffer + i * stride; } png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct (png); NavMapImage image; image.size = 0; // draft buffer size estimation (we don't know final size yet) // suppose to be not more than 16 byte per pixel int iMaxSize = 16*width*height; image.data = new char [iMaxSize]; // set custom I/O functions png_set_write_fn(png,(png_voidp) &image, write_data_fn, flush_data_fn); png_set_IHDR (png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); white.red = 0xff; white.blue = 0xff; white.green = 0xff; png_set_bKGD (png, info, &white); png_set_write_user_transform_fn (png, unpremultiply_data); png_set_bgr (png); png_write_info (png, info); png_write_image (png, rows); png_write_end (png, info); png_destroy_write_struct (&png, &info); free (rows); // prevent buffer overflow int size = ((image.size < iMaxSize) ? image.size : iMaxSize); target->data = new char [size]; memcpy(target->data, image.data, size); target->size = size; delete [] image.data; } void svg2image(NavMapImage *src, NavMapImage *target, cairo_format_t format, void (*write_fn)(char * buffer, int width, int height, NavMapImage *target) ){ unsigned int svg_width, svg_height; //CAIRO_MUTEX_DECLARE(my_cairo_mutex); svg_cairo_status_t status; cairo_t *cr; svg_cairo_t *svgc; cairo_surface_t *surface; status = svg_cairo_create (&svgc); if (status) { fprintf (stderr, "Failed to create svg_cairo_t. Exiting.\n"); return; } status = svg_cairo_parse_buffer(svgc, src->data, src->size); if (status) return; svg_cairo_get_size (svgc, &svg_width, &svg_height); int stride; switch(format) { case CAIRO_FORMAT_A1: stride = svg_width / 8; break; case CAIRO_FORMAT_A8: stride = svg_width; break; case CAIRO_FORMAT_RGB24: case CAIRO_FORMAT_ARGB32: default: stride = CAIRO_BPP * svg_width; } char * image_buf = (char *) malloc (stride * svg_height); surface = cairo_image_surface_create_for_data ((unsigned char *) image_buf, format, svg_width, svg_height, stride); cr = cairo_create (surface); /// XXX: This probably doesn't need to be here (eventually) cairo_set_source_rgb (cr, 1, 1, 1); // CAIRO_MUTEX_LOCK(my_cairo_mutex); status = svg_cairo_render (svgc, cr); // CAIRO_MUTEX_UNLOCK(my_cairo_mutex); cairo_destroy (cr); cairo_surface_destroy(surface); svg_cairo_destroy (svgc); // call function to write image to corresponding format (*write_fn) (image_buf, svg_width, svg_height, target); free (image_buf); } void svg2png(NavMapImage *src, NavMapImage *target) { svg2image(src, target, CAIRO_FORMAT_ARGB32, write_png); } #else // stub void svg2png(NavMapImage *src, NavMapImage *target) { } #endif ///////////////////////////////////////////////////////// void CairoTest::RunTests(int Id) { NavMapImage target; target.data = NULL; char file[80]; sprintf(file, "%d.png", Id); svg2png(&source, &target); //////////////////// std::ofstream f; cerr<<"***writing PNG file:"<RunTests(Id); isActive = false; cout <<"Finished thread " < [ ]\n"; return -1; } else in_file = argv[1]; int nThreads = 1; if(argc >2) { nThreads = atoi(argv[2]); } CairoTest test(nThreads); if (test.loadFile(in_file)) { test.Run(); } return 0; } bool CairoTest::loadFile(const char *file){ std::ifstream f; struct stat st; if(stat(file, &st)!=0) { cerr<<"***fail on openning file:"<