/**************************************************************************** Free any resources associated with this canvas and the canvas struct itself. ****************************************************************************/ void canvas_free(struct canvas *store) { cairo_surface_destroy(store->surface); free(store); }
void draw_rectangles(cairo_t *fbcr, struct tsdev *ts, cairo_linuxfb_device_t *device) { int bufid = 1; /* start drawing into second buffer */ float r, g, b; int fbsizex = device->fb_vinfo.xres; int fbsizey = device->fb_vinfo.yres; int startx, starty, sizex, sizey; struct ts_sample sample; cairo_surface_t *surface; cairo_t *cr; float scale = 1.0f; surface = cairo_image_surface_create(CAIRO_FORMAT_RGB16_565, fbsizex, fbsizey); cr = cairo_create(surface); /* * We clear the cairo surface here before drawing * This is required in case something was drawn on this surface * previously, the previous contents would not be cleared without this. */ cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); srand(time(NULL)); while (!cancel) { r = (rand() % 100) / 100.0; g = (rand() % 100) / 100.0; b = (rand() % 100) / 100.0; startx = rand() % fbsizex; starty = rand() % fbsizey; sizex = rand() % (fbsizex - startx); sizey = rand() % (fbsizey - starty); cairo_identity_matrix(cr); if (ts) { int pressed = 0; /* Pressure is our identication whether we act on axis... */ while (ts_read(ts, &sample, 1)) { if (sample.pressure > 0) pressed = 1; } if (pressed) { scale *= 1.05f; cairo_translate(cr, sample.x, sample.y); cairo_scale(cr, scale, scale); //r = g = b = 0; startx = -5; starty = -5; sizex = 10; sizey = 10; } else { scale = 1.0f; } } cairo_set_source_rgb(cr, r, g, b); cairo_rectangle(cr, startx, starty, sizex, sizey); cairo_stroke_preserve(cr); cairo_fill(cr); /* Draw to framebuffer at y offset according to current buffer.. */ cairo_set_source_surface(fbcr, surface, 0, bufid * fbsizey); cairo_paint(fbcr); flip_buffer(device, 1, bufid); /* Switch buffer ID for next draw */ bufid = !bufid; usleep(20000); } /* Make sure we leave with buffer 0 enabled */ flip_buffer(device, 1, 0); /* Destroy and release all cairo related contexts */ cairo_destroy(cr); cairo_surface_destroy(surface); }
/** * fo_doc_cairo_place_image: * @fo_doc: * @fo_image: * @x: * @y: * @xscale: * @yscale: * * **/ static void fo_doc_cairo_place_image (FoDoc *fo_doc, FoImage *fo_image, gdouble x G_GNUC_UNUSED, gdouble y G_GNUC_UNUSED, gdouble xscale G_GNUC_UNUSED, gdouble yscale G_GNUC_UNUSED) { GdkPixbuf *pixbuf = g_object_ref (fo_pixbuf_get_pixbuf (fo_image)); 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); guchar *cairo_pixels; cairo_format_t format; cairo_surface_t *surface; static const cairo_user_data_key_t key; int j; cairo_translate (FO_DOC_CAIRO (fo_doc)->cr, 0, FO_DOC_CAIRO(fo_doc)->page_height); cairo_save (FO_DOC_CAIRO(fo_doc)->cr); cairo_scale (FO_DOC_CAIRO (fo_doc)->cr, xscale * 72.0 / PIXELS_PER_INCH, yscale * 72.0 / PIXELS_PER_INCH); #if HAVE_LIBRSVG if (g_str_has_suffix( fo_image_get_uri(fo_image), ".svg")) { RsvgHandle *rsvg; GError *error = NULL; g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "rendering %s as SVG\n", fo_image_get_uri(fo_image)); rsvg_init(); rsvg_set_default_dpi_x_y (PIXELS_PER_INCH, PIXELS_PER_INCH); rsvg = rsvg_handle_new_from_file (fo_image_get_uri(fo_image), &error); rsvg_handle_render_cairo (rsvg, FO_DOC_CAIRO(fo_doc)->cr); rsvg_term(); cairo_restore (FO_DOC_CAIRO(fo_doc)->cr); if (error) { g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, error->message); g_error_free (error); } return; } #endif if (n_channels == 3) { format = CAIRO_FORMAT_RGB24; } else { format = CAIRO_FORMAT_ARGB32; } cairo_pixels = g_malloc (4 * width * height); surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels, format, width, height, 4 * width); cairo_surface_set_user_data (surface, &key, cairo_pixels, (cairo_destroy_func_t)g_free); 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 += 4 * width; } cairo_surface_set_fallback_resolution (surface, PIXELS_PER_INCH, PIXELS_PER_INCH); cairo_set_source_surface (FO_DOC_CAIRO (fo_doc)->cr, surface, 0, 0); cairo_pattern_t *pattern = cairo_get_source (FO_DOC_CAIRO (fo_doc)->cr); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE); cairo_paint (FO_DOC_CAIRO (fo_doc)->cr); cairo_surface_destroy (surface); g_object_unref (pixbuf); cairo_restore (FO_DOC_CAIRO(fo_doc)->cr); }
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; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d P A N G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadPANGOImage() reads an image in the Pango Markup Language Format. % % The format of the ReadPANGOImage method is: % % Image *ReadPANGOImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadPANGOImage(const ImageInfo *image_info, ExceptionInfo *exception) { cairo_font_options_t *font_options; cairo_surface_t *surface; char *caption, *property; cairo_t *cairo_image; const char *option; DrawInfo *draw_info; Image *image; MagickBooleanType status; MemoryInfo *pixel_info; PangoAlignment align; PangoContext *context; PangoFontDescription *description; PangoFontMap *fontmap; PangoGravity gravity; PangoLayout *layout; PangoRectangle extent; PixelInfo fill_color; RectangleInfo page; register unsigned char *p; size_t stride; ssize_t y; unsigned char *pixels; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); image=AcquireImage(image_info,exception); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageOption(image_info,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties((ImageInfo *) image_info,image, image_info->filename,exception); else if (LocaleNCompare(option,"pango:",6) == 0) property=InterpretImageProperties((ImageInfo *) image_info,image,option+6, exception); else property=InterpretImageProperties((ImageInfo *) image_info,image,option, exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); /* Get context. */ fontmap=pango_cairo_font_map_new(); pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(fontmap), image->resolution.x == 0.0 ? 90.0 : image->resolution.x); font_options=cairo_font_options_create(); option=GetImageOption(image_info,"pango:hinting"); if (option != (const char *) NULL) { if (LocaleCompare(option,"none") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE); if (LocaleCompare(option,"full") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_FULL); } context=pango_font_map_create_context(fontmap); pango_cairo_context_set_font_options(context,font_options); cairo_font_options_destroy(font_options); option=GetImageOption(image_info,"pango:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) { case NorthGravity: { gravity=PANGO_GRAVITY_NORTH; break; } case NorthWestGravity: case WestGravity: case SouthWestGravity: { gravity=PANGO_GRAVITY_WEST; break; } case NorthEastGravity: case EastGravity: case SouthEastGravity: { gravity=PANGO_GRAVITY_EAST; break; } case SouthGravity: { gravity=PANGO_GRAVITY_SOUTH; break; } default: { gravity=PANGO_GRAVITY_AUTO; break; } } pango_context_set_base_gravity(context,gravity); option=GetImageOption(image_info,"pango:gravity-hint"); if (option != (const char *) NULL) { if (LocaleCompare(option,"line") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE); if (LocaleCompare(option,"natural") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL); if (LocaleCompare(option,"strong") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG); } /* Configure layout. */ layout=pango_layout_new(context); option=GetImageOption(image_info,"pango:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageOption(image_info,"pango:ellipsize"); if (option != (const char *) NULL) { if (LocaleCompare(option,"end") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END); if (LocaleCompare(option,"middle") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE); if (LocaleCompare(option,"none") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE); if (LocaleCompare(option,"start") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START); } option=GetImageOption(image_info,"pango:justify"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_justify(layout,1); option=GetImageOption(image_info,"pango:single-paragraph"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageOption(image_info,"pango:wrap"); if (option != (const char *) NULL) { if (LocaleCompare(option,"char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_CHAR); if (LocaleCompare(option,"word") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD); if (LocaleCompare(option,"word-char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR); } option=GetImageOption(image_info,"pango:indent"); if (option != (const char *) NULL) pango_layout_set_indent(layout,(int) ((StringToLong(option)* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)*PANGO_SCALE+36)/ 90.0+0.5)); switch (draw_info->align) { case CenterAlign: align=PANGO_ALIGN_CENTER; break; case RightAlign: align=PANGO_ALIGN_RIGHT; break; case LeftAlign: align=PANGO_ALIGN_LEFT; break; default: { if (draw_info->gravity == CenterGravity) { align=PANGO_ALIGN_CENTER; break; } align=PANGO_ALIGN_LEFT; break; } } if ((align != PANGO_ALIGN_CENTER) && (draw_info->direction == RightToLeftDirection)) align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align); pango_layout_set_alignment(layout,align); if (draw_info->font == (char *) NULL) description=pango_font_description_new(); else description=pango_font_description_from_string(draw_info->font); pango_font_description_set_size(description,(int) (PANGO_SCALE* draw_info->pointsize+0.5)); pango_layout_set_font_description(layout,description); pango_font_description_free(description); option=GetImageOption(image_info,"pango:markup"); if ((option != (const char *) NULL) && (IsStringTrue(option) == MagickFalse)) pango_layout_set_text(layout,caption,-1); else { GError *error; error=(GError *) NULL; if (pango_parse_markup(caption,-1,0,NULL,NULL,NULL,&error) == 0) (void) ThrowMagickException(exception,GetMagickModule(),CoderError, error->message,"`%s'",image_info->filename); pango_layout_set_markup(layout,caption,-1); } pango_layout_context_changed(layout); page.x=0; page.y=0; if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); if (image->columns == 0) { pango_layout_get_extents(layout,NULL,&extent); image->columns=(extent.x+extent.width+PANGO_SCALE/2)/PANGO_SCALE+2*page.x; } else { image->columns-=2*page.x; pango_layout_set_width(layout,(int) ((PANGO_SCALE*image->columns* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)+45.0)/90.0+ 0.5)); } if (image->rows == 0) { pango_layout_get_extents(layout,NULL,&extent); image->rows=(extent.y+extent.height+PANGO_SCALE/2)/PANGO_SCALE+2*page.y; } else { image->rows-=2*page.y; pango_layout_set_height(layout,(int) ((PANGO_SCALE*image->rows* (image->resolution.y == 0.0 ? 90.0 : image->resolution.y)+45.0)/90.0+ 0.5)); } status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) return(DestroyImageList(image)); /* Render markup. */ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, (int) image->columns); pixel_info=AcquireVirtualMemory(image->rows,stride*sizeof(*pixels)); if (pixel_info == (MemoryInfo *) NULL) { draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32, (int) image->columns,(int) image->rows,(int) stride); cairo_image=cairo_create(surface); cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); cairo_paint(cairo_image); cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); cairo_translate(cairo_image,page.x,page.y); cairo_set_source_rgba(cairo_image,QuantumScale*draw_info->fill.red, QuantumScale*draw_info->fill.green,QuantumScale*draw_info->fill.blue, QuantumScale*draw_info->fill.alpha); pango_cairo_show_layout(cairo_image,layout); cairo_destroy(cairo_image); cairo_surface_destroy(surface); g_object_unref(layout); g_object_unref(fontmap); /* Convert surface to image. */ (void) SetImageBackgroundColor(image,exception); p=pixels; GetPixelInfo(image,&fill_color); for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *q; register ssize_t x; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { double gamma; fill_color.blue=(double) ScaleCharToQuantum(*p++); fill_color.green=(double) ScaleCharToQuantum(*p++); fill_color.red=(double) ScaleCharToQuantum(*p++); fill_color.alpha=(double) ScaleCharToQuantum(*p++); /* Disassociate alpha. */ gamma=QuantumScale*fill_color.alpha; gamma=PerceptibleReciprocal(gamma); fill_color.blue*=gamma; fill_color.green*=gamma; fill_color.red*=gamma; CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double) GetPixelAlpha(image,q),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } /* Relinquish resources. */ pixel_info=RelinquishVirtualMemory(pixel_info); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
/* This file is part of darktable, copyright (c) 2009--2011 johannes hanika. copyright (c) 2012 tobias ellinghaus. copyright (c) 2014 henrik andersson. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. darktable is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with darktable. If not, see <http://www.gnu.org/licenses/>. */ #include "bauhaus/bauhaus.h" #include "common/camera_control.h" #include "common/darktable.h" #include "common/image_cache.h" #include "common/mipmap_cache.h" #include "control/conf.h" #include "control/control.h" #include "control/jobs.h" #include "dtgtk/button.h" #include "gui/accelerators.h" #include "gui/gtk.h" #include "gui/guides.h" #include "libs/lib.h" #include "libs/lib_api.h" #include <gdk/gdkkeysyms.h> typedef enum dt_lib_live_view_flip_t { FLAG_FLIP_NONE = 0, FLAG_FLIP_HORIZONTAL = 1<<0, FLAG_FLIP_VERTICAL = 1<<1, FLAG_FLIP_BOTH = FLAG_FLIP_HORIZONTAL|FLAG_FLIP_VERTICAL } dt_lib_live_view_flip_t; typedef enum dt_lib_live_view_overlay_t { OVERLAY_NONE = 0, OVERLAY_SELECTED, OVERLAY_ID } dt_lib_live_view_overlay_t; #define HANDLE_SIZE 0.02 static const cairo_operator_t _overlay_modes[] = { CAIRO_OPERATOR_OVER, CAIRO_OPERATOR_XOR, CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE #if(CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)) , CAIRO_OPERATOR_MULTIPLY, CAIRO_OPERATOR_SCREEN, CAIRO_OPERATOR_OVERLAY, CAIRO_OPERATOR_DARKEN, CAIRO_OPERATOR_LIGHTEN, CAIRO_OPERATOR_COLOR_DODGE, CAIRO_OPERATOR_COLOR_BURN, CAIRO_OPERATOR_HARD_LIGHT, CAIRO_OPERATOR_SOFT_LIGHT, CAIRO_OPERATOR_DIFFERENCE, CAIRO_OPERATOR_EXCLUSION, CAIRO_OPERATOR_HSL_HUE, CAIRO_OPERATOR_HSL_SATURATION, CAIRO_OPERATOR_HSL_COLOR, CAIRO_OPERATOR_HSL_LUMINOSITY #endif }; DT_MODULE(1) typedef struct dt_lib_live_view_t { int imgid; int splitline_rotation; double overlay_x0, overlay_x1, overlay_y0, overlay_y1; double splitline_x, splitline_y; // 0..1 gboolean splitline_dragging; GtkWidget *live_view, *live_view_zoom, *rotate_ccw, *rotate_cw, *flip; GtkWidget *focus_out_small, *focus_out_big, *focus_in_small, *focus_in_big; GtkWidget *guide_selector, *flip_guides, *guides_widgets; GList *guides_widgets_list; GtkWidget *overlay, *overlay_id_box, *overlay_id, *overlay_mode, *overlay_splitline; } dt_lib_live_view_t; static void guides_presets_set_visibility(dt_lib_live_view_t *lib, int which) { if(which == 0) { gtk_widget_set_no_show_all(lib->guides_widgets, TRUE); gtk_widget_hide(lib->guides_widgets); gtk_widget_set_no_show_all(lib->flip_guides, TRUE); gtk_widget_hide(lib->flip_guides); } else { GtkWidget *widget = g_list_nth_data(lib->guides_widgets_list, which - 1); if(widget) { gtk_widget_set_no_show_all(lib->guides_widgets, FALSE); gtk_widget_show_all(lib->guides_widgets); gtk_stack_set_visible_child(GTK_STACK(lib->guides_widgets), widget); } else { gtk_widget_set_no_show_all(lib->guides_widgets, TRUE); gtk_widget_hide(lib->guides_widgets); } gtk_widget_set_no_show_all(lib->flip_guides, FALSE); gtk_widget_show_all(lib->flip_guides); } // TODO: add a support_flip flag to guides to hide the flip gui? } static void guides_presets_changed(GtkWidget *combo, dt_lib_live_view_t *lib) { int which = dt_bauhaus_combobox_get(combo); guides_presets_set_visibility(lib, which); } static void overlay_changed(GtkWidget *combo, dt_lib_live_view_t *lib) { int which = dt_bauhaus_combobox_get(combo); if(which == OVERLAY_NONE) { gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), FALSE); gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), FALSE); } else { gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), TRUE); gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), TRUE); } if(which == OVERLAY_ID) gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), TRUE); else gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), FALSE); } const char *name(dt_lib_module_t *self) { return _("live view"); } uint32_t views(dt_lib_module_t *self) { return DT_VIEW_TETHERING; } uint32_t container(dt_lib_module_t *self) { return DT_UI_CONTAINER_PANEL_RIGHT_CENTER; } void gui_reset(dt_lib_module_t *self) { } int position() { return 998; } void init_key_accels(dt_lib_module_t *self) { dt_accel_register_lib(self, NC_("accel", "toggle live view"), GDK_KEY_v, 0); dt_accel_register_lib(self, NC_("accel", "zoom live view"), GDK_KEY_z, 0); dt_accel_register_lib(self, NC_("accel", "rotate 90 degrees CCW"), 0, 0); dt_accel_register_lib(self, NC_("accel", "rotate 90 degrees CW"), 0, 0); dt_accel_register_lib(self, NC_("accel", "flip horizontally"), 0, 0); dt_accel_register_lib(self, NC_("accel", "move focus point in (big steps)"), 0, 0); dt_accel_register_lib(self, NC_("accel", "move focus point in (small steps)"), 0, 0); dt_accel_register_lib(self, NC_("accel", "move focus point out (small steps)"), 0, 0); dt_accel_register_lib(self, NC_("accel", "move focus point out (big steps)"), 0, 0); } void connect_key_accels(dt_lib_module_t *self) { dt_lib_live_view_t *lib = (dt_lib_live_view_t *)self->data; dt_accel_connect_button_lib(self, "toggle live view", GTK_WIDGET(lib->live_view)); dt_accel_connect_button_lib(self, "zoom live view", GTK_WIDGET(lib->live_view_zoom)); dt_accel_connect_button_lib(self, "rotate 90 degrees CCW", GTK_WIDGET(lib->rotate_ccw)); dt_accel_connect_button_lib(self, "rotate 90 degrees CW", GTK_WIDGET(lib->rotate_cw)); dt_accel_connect_button_lib(self, "flip horizontally", GTK_WIDGET(lib->flip)); dt_accel_connect_button_lib(self, "move focus point in (big steps)", GTK_WIDGET(lib->focus_in_big)); dt_accel_connect_button_lib(self, "move focus point in (small steps)", GTK_WIDGET(lib->focus_in_small)); dt_accel_connect_button_lib(self, "move focus point out (small steps)", GTK_WIDGET(lib->focus_out_small)); dt_accel_connect_button_lib(self, "move focus point out (big steps)", GTK_WIDGET(lib->focus_out_big)); } static void _rotate_ccw(GtkWidget *widget, gpointer user_data) { dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera; cam->live_view_rotation = (cam->live_view_rotation + 1) % 4; // 0 -> 1 -> 2 -> 3 -> 0 -> ... } static void _rotate_cw(GtkWidget *widget, gpointer user_data) { dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera; cam->live_view_rotation = (cam->live_view_rotation + 3) % 4; // 0 -> 3 -> 2 -> 1 -> 0 -> ... } // Congratulations to Simon for being the first one recognizing live view in a screen shot ^^ static void _toggle_live_view_clicked(GtkWidget *widget, gpointer user_data) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) { if(dt_camctl_camera_start_live_view(darktable.camctl) == FALSE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE); } else { dt_camctl_camera_stop_live_view(darktable.camctl); } } // TODO: using a toggle button would be better, but this setting can also be changed by right clicking on the // canvas (src/views/capture.c). // maybe using a signal would work? i have no idea. static void _zoom_live_view_clicked(GtkWidget *widget, gpointer user_data) { dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera; if(cam->is_live_viewing) { cam->live_view_zoom = !cam->live_view_zoom; if(cam->live_view_zoom == TRUE) dt_camctl_camera_set_property_string(darktable.camctl, NULL, "eoszoom", "5"); else dt_camctl_camera_set_property_string(darktable.camctl, NULL, "eoszoom", "1"); } } static void _focus_button_clicked(GtkWidget *widget, gpointer user_data) { int focus = GPOINTER_TO_INT(user_data); dt_camctl_camera_set_property_choice(darktable.camctl, NULL, "manualfocusdrive", focus); } static void _toggle_flip_clicked(GtkWidget *widget, gpointer user_data) { dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera; cam->live_view_flip = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); } static void _overlay_id_changed(GtkWidget *widget, gpointer user_data) { dt_lib_live_view_t *lib = (dt_lib_live_view_t *)user_data; lib->imgid = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)); dt_conf_set_int("plugins/lighttable/live_view/overlay_imgid", lib->imgid); } static void _overlay_mode_changed(GtkWidget *combo, gpointer user_data) { dt_conf_set_int("plugins/lighttable/live_view/overlay_mode", dt_bauhaus_combobox_get(combo)); } static void _overlay_splitline_changed(GtkWidget *combo, gpointer user_data) { dt_conf_set_int("plugins/lighttable/live_view/splitline", dt_bauhaus_combobox_get(combo)); } void gui_init(dt_lib_module_t *self) { self->data = calloc(1, sizeof(dt_lib_live_view_t)); // Setup lib data dt_lib_live_view_t *lib = self->data; lib->splitline_x = lib->splitline_y = 0.5; // Setup gui self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); GtkWidget *box; box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start(GTK_BOX(self->widget), box, TRUE, TRUE, 0); lib->live_view = dtgtk_togglebutton_new(dtgtk_cairo_paint_eye, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER); lib->live_view_zoom = dtgtk_button_new( dtgtk_cairo_paint_zoom, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER); // TODO: see _zoom_live_view_clicked lib->rotate_ccw = dtgtk_button_new(dtgtk_cairo_paint_refresh, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER); lib->rotate_cw = dtgtk_button_new(dtgtk_cairo_paint_refresh, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP); lib->flip = dtgtk_togglebutton_new(dtgtk_cairo_paint_flip, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_UP); gtk_box_pack_start(GTK_BOX(box), lib->live_view, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->live_view_zoom, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->rotate_ccw, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->rotate_cw, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->flip, TRUE, TRUE, 0); gtk_widget_set_tooltip_text(lib->live_view, _("toggle live view")); gtk_widget_set_tooltip_text(lib->live_view_zoom, _("zoom live view")); gtk_widget_set_tooltip_text(lib->rotate_ccw, _("rotate 90 degrees ccw")); gtk_widget_set_tooltip_text(lib->rotate_cw, _("rotate 90 degrees cw")); gtk_widget_set_tooltip_text(lib->flip, _("flip live view horizontally")); g_signal_connect(G_OBJECT(lib->live_view), "clicked", G_CALLBACK(_toggle_live_view_clicked), lib); g_signal_connect(G_OBJECT(lib->live_view_zoom), "clicked", G_CALLBACK(_zoom_live_view_clicked), lib); g_signal_connect(G_OBJECT(lib->rotate_ccw), "clicked", G_CALLBACK(_rotate_ccw), lib); g_signal_connect(G_OBJECT(lib->rotate_cw), "clicked", G_CALLBACK(_rotate_cw), lib); g_signal_connect(G_OBJECT(lib->flip), "clicked", G_CALLBACK(_toggle_flip_clicked), lib); // focus buttons box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); gtk_box_pack_start(GTK_BOX(self->widget), box, TRUE, TRUE, 0); lib->focus_in_big = dtgtk_button_new(dtgtk_cairo_paint_solid_triangle, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_LEFT); lib->focus_in_small = dtgtk_button_new(dtgtk_cairo_paint_arrow, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_LEFT); // TODO icon not centered lib->focus_out_small = dtgtk_button_new(dtgtk_cairo_paint_arrow, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_RIGHT); // TODO same here lib->focus_out_big = dtgtk_button_new(dtgtk_cairo_paint_solid_triangle, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_DIRECTION_RIGHT); gtk_box_pack_start(GTK_BOX(box), lib->focus_in_big, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->focus_in_small, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->focus_out_small, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box), lib->focus_out_big, TRUE, TRUE, 0); gtk_widget_set_tooltip_text(lib->focus_in_big, _("move focus point in (big steps)")); gtk_widget_set_tooltip_text(lib->focus_in_small, _("move focus point in (small steps)")); gtk_widget_set_tooltip_text(lib->focus_out_small, _("move focus point out (small steps)")); gtk_widget_set_tooltip_text(lib->focus_out_big, _("move focus point out (big steps)")); // Near 3 g_signal_connect(G_OBJECT(lib->focus_in_big), "clicked", G_CALLBACK(_focus_button_clicked), GINT_TO_POINTER(2)); // Near 1 g_signal_connect(G_OBJECT(lib->focus_in_small), "clicked", G_CALLBACK(_focus_button_clicked), GINT_TO_POINTER(0)); // Far 1 g_signal_connect(G_OBJECT(lib->focus_out_small), "clicked", G_CALLBACK(_focus_button_clicked), GINT_TO_POINTER(4)); // Far 3 g_signal_connect(G_OBJECT(lib->focus_out_big), "clicked", G_CALLBACK(_focus_button_clicked), GINT_TO_POINTER(6)); // Guides lib->guide_selector = dt_bauhaus_combobox_new(NULL); dt_bauhaus_widget_set_label(lib->guide_selector, NULL, _("guides")); gtk_box_pack_start(GTK_BOX(self->widget), lib->guide_selector, TRUE, TRUE, 0); lib->guides_widgets = gtk_stack_new(); gtk_stack_set_homogeneous(GTK_STACK(lib->guides_widgets), FALSE); gtk_box_pack_start(GTK_BOX(self->widget), lib->guides_widgets, TRUE, TRUE, 0); dt_bauhaus_combobox_add(lib->guide_selector, _("none")); int i = 0; for(GList *iter = darktable.guides; iter; iter = g_list_next(iter), i++) { GtkWidget *widget = NULL; dt_guides_t *guide = (dt_guides_t *)iter->data; dt_bauhaus_combobox_add(lib->guide_selector, _(guide->name)); if(guide->widget) { // generate some unique name so that we can have the same name several times char name[5]; snprintf(name, sizeof(name), "%d", i); widget = guide->widget(NULL, guide->user_data); gtk_widget_show_all(widget); gtk_stack_add_named(GTK_STACK(lib->guides_widgets), widget, name); } lib->guides_widgets_list = g_list_append(lib->guides_widgets_list, widget); } gtk_widget_set_no_show_all(lib->guides_widgets, TRUE); gtk_widget_set_tooltip_text(lib->guide_selector, _("display guide lines to help compose your photograph")); g_signal_connect(G_OBJECT(lib->guide_selector), "value-changed", G_CALLBACK(guides_presets_changed), lib); lib->flip_guides = dt_bauhaus_combobox_new(NULL); dt_bauhaus_widget_set_label(lib->flip_guides, NULL, _("flip")); dt_bauhaus_combobox_add(lib->flip_guides, _("none")); dt_bauhaus_combobox_add(lib->flip_guides, _("horizontally")); dt_bauhaus_combobox_add(lib->flip_guides, _("vertically")); dt_bauhaus_combobox_add(lib->flip_guides, _("both")); gtk_widget_set_tooltip_text(lib->flip_guides, _("flip guides")); gtk_box_pack_start(GTK_BOX(self->widget), lib->flip_guides, TRUE, TRUE, 0); lib->overlay = dt_bauhaus_combobox_new(NULL); dt_bauhaus_widget_set_label(lib->overlay, NULL, _("overlay")); dt_bauhaus_combobox_add(lib->overlay, _("none")); dt_bauhaus_combobox_add(lib->overlay, _("selected image")); dt_bauhaus_combobox_add(lib->overlay, _("id")); gtk_widget_set_tooltip_text(lib->overlay, _("overlay another image over the live view")); g_signal_connect(G_OBJECT(lib->overlay), "value-changed", G_CALLBACK(overlay_changed), lib); gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay, TRUE, TRUE, 0); lib->overlay_id_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); GtkWidget *label = gtk_label_new(_("image id")); gtk_widget_set_halign(label, GTK_ALIGN_START); lib->overlay_id = gtk_spin_button_new_with_range(0, 1000000000, 1); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(lib->overlay_id), 0); gtk_widget_set_tooltip_text(lib->overlay_id, _("enter image id of the overlay manually")); g_signal_connect(G_OBJECT(lib->overlay_id), "value-changed", G_CALLBACK(_overlay_id_changed), lib); gtk_spin_button_set_value(GTK_SPIN_BUTTON(lib->overlay_id), dt_conf_get_int("plugins/lighttable/live_view/overlay_imgid")); gtk_box_pack_start(GTK_BOX(lib->overlay_id_box), label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(lib->overlay_id_box), lib->overlay_id, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_id_box, TRUE, TRUE, 0); gtk_widget_show(lib->overlay_id); gtk_widget_show(label); lib->overlay_mode = dt_bauhaus_combobox_new(NULL); dt_bauhaus_widget_set_label(lib->overlay_mode, NULL, _("overlay mode")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "normal")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "xor")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "add")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "saturate")); #if(CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)) dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "multiply")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "screen")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "overlay")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "darken")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "lighten")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "color dodge")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "color burn")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "hard light")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "soft light")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "difference")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "exclusion")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL hue")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL saturation")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL color")); dt_bauhaus_combobox_add(lib->overlay_mode, C_("blendmode", "HSL luminosity")); #endif gtk_widget_set_tooltip_text(lib->overlay_mode, _("mode of the overlay")); dt_bauhaus_combobox_set(lib->overlay_mode, dt_conf_get_int("plugins/lighttable/live_view/overlay_mode")); g_signal_connect(G_OBJECT(lib->overlay_mode), "value-changed", G_CALLBACK(_overlay_mode_changed), lib); gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_mode, TRUE, TRUE, 0); lib->overlay_splitline = dt_bauhaus_combobox_new(NULL); dt_bauhaus_widget_set_label(lib->overlay_splitline, NULL, _("split line")); dt_bauhaus_combobox_add(lib->overlay_splitline, _("off")); dt_bauhaus_combobox_add(lib->overlay_splitline, _("on")); gtk_widget_set_tooltip_text(lib->overlay_splitline, _("only draw part of the overlay")); dt_bauhaus_combobox_set(lib->overlay_splitline, dt_conf_get_int("plugins/lighttable/live_view/splitline")); g_signal_connect(G_OBJECT(lib->overlay_splitline), "value-changed", G_CALLBACK(_overlay_splitline_changed), lib); gtk_box_pack_start(GTK_BOX(self->widget), lib->overlay_splitline, TRUE, TRUE, 0); gtk_widget_set_visible(GTK_WIDGET(lib->overlay_mode), FALSE); gtk_widget_set_visible(GTK_WIDGET(lib->overlay_id_box), FALSE); gtk_widget_set_visible(GTK_WIDGET(lib->overlay_splitline), FALSE); gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_mode), TRUE); gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_id_box), TRUE); gtk_widget_set_no_show_all(GTK_WIDGET(lib->overlay_splitline), TRUE); guides_presets_set_visibility(lib, 0); } void gui_cleanup(dt_lib_module_t *self) { // dt_lib_live_view_t *lib = self->data; // g_list_free(lib->guides_widgets_list); // INTENTIONAL. it's supposed to be leaky until lua is fixed. free(self->data); self->data = NULL; } void view_enter(struct dt_lib_module_t *self,struct dt_view_t *old_view,struct dt_view_t *new_view) { // disable buttons that won't work with this camera // TODO: initialize tethering mode outside of libs/camera.s so we can use darktable.camctl->active_camera // here dt_lib_live_view_t *lib = self->data; const dt_camera_t *cam = darktable.camctl->active_camera; if(cam == NULL) cam = darktable.camctl->wanted_camera; gboolean sensitive = cam && cam->can_live_view_advanced; gtk_widget_set_sensitive(lib->live_view_zoom, sensitive); gtk_widget_set_sensitive(lib->focus_in_big, sensitive); gtk_widget_set_sensitive(lib->focus_in_small, sensitive); gtk_widget_set_sensitive(lib->focus_out_big, sensitive); gtk_widget_set_sensitive(lib->focus_out_small, sensitive); } // TODO: find out where the zoom window is and draw overlay + grid accordingly #define MARGIN 20 #define BAR_HEIGHT 18 /* see libs/camera.c */ void gui_post_expose(dt_lib_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_camera_t *cam = (dt_camera_t *)darktable.camctl->active_camera; dt_lib_live_view_t *lib = self->data; if(cam->is_live_viewing == FALSE || cam->live_view_zoom == TRUE) return; dt_pthread_mutex_lock(&cam->live_view_pixbuf_mutex); if(GDK_IS_PIXBUF(cam->live_view_pixbuf) == FALSE) { dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex); return; } double w = width - (MARGIN * 2.0f); double h = height - (MARGIN * 2.0f) - BAR_HEIGHT; gint pw = gdk_pixbuf_get_width(cam->live_view_pixbuf); gint ph = gdk_pixbuf_get_height(cam->live_view_pixbuf); lib->overlay_x0 = lib->overlay_x1 = lib->overlay_y0 = lib->overlay_y1 = 0.0; gboolean use_splitline = (dt_bauhaus_combobox_get(lib->overlay_splitline) == 1); // OVERLAY int imgid = 0; switch(dt_bauhaus_combobox_get(lib->overlay)) { case OVERLAY_SELECTED: imgid = dt_view_tethering_get_selected_imgid(darktable.view_manager); break; case OVERLAY_ID: imgid = lib->imgid; break; } if(imgid > 0) { cairo_save(cr); const dt_image_t *img = dt_image_cache_testget(darktable.image_cache, imgid, 'r'); // if the user points at this image, we really want it: if(!img) img = dt_image_cache_get(darktable.image_cache, imgid, 'r'); int zoom = 1; float imgwd = 0.90f; if(zoom == 1) { imgwd = .97f; } dt_mipmap_buffer_t buf; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(darktable.mipmap_cache, imgwd * w, imgwd * h); dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, mip, 0, 'r'); float scale = 1.0; cairo_surface_t *surface = NULL; if(buf.buf) { const int32_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, buf.width); surface = cairo_image_surface_create_for_data(buf.buf, CAIRO_FORMAT_RGB24, buf.width, buf.height, stride); if(zoom == 1) { scale = fminf(fminf(w, pw) / (float)buf.width, fminf(h, ph) / (float)buf.height); } else scale = fminf(w * imgwd / (float)buf.width, h * imgwd / (float)buf.height); } // draw centered and fitted: cairo_translate(cr, width / 2.0, (height + BAR_HEIGHT) / 2.0f); cairo_scale(cr, scale, scale); if(buf.buf) { cairo_translate(cr, -.5f * buf.width, -.5f * buf.height); if(use_splitline) { double x0, y0, x1, y1; switch(lib->splitline_rotation) { case 0: x0 = 0.0; y0 = 0.0; x1 = buf.width * lib->splitline_x; y1 = buf.height; break; case 1: x0 = 0.0; y0 = 0.0; x1 = buf.width; y1 = buf.height * lib->splitline_y; break; case 2: x0 = buf.width * lib->splitline_x; y0 = 0.0; x1 = buf.width; y1 = buf.height; break; case 3: x0 = 0.0; y0 = buf.height * lib->splitline_y; x1 = buf.width; y1 = buf.height; break; default: fprintf(stderr, "OMFG, the world will collapse, this shouldn't be reachable!\n"); return; } cairo_rectangle(cr, x0, y0, x1, y1); cairo_clip(cr); } cairo_set_source_surface(cr, surface, 0, 0); // set filter no nearest: // in skull mode, we want to see big pixels. // in 1 iir mode for the right mip, we want to see exactly what the pipe gave us, 1:1 pixel for pixel. // in between, filtering just makes stuff go unsharp. if((buf.width <= 8 && buf.height <= 8) || fabsf(scale - 1.0f) < 0.01f) cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); cairo_rectangle(cr, 0, 0, buf.width, buf.height); int overlay_modes_index = dt_bauhaus_combobox_get(lib->overlay_mode); if(overlay_modes_index >= 0) { cairo_operator_t mode = _overlay_modes[overlay_modes_index]; cairo_set_operator(cr, mode); } cairo_fill(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_surface_destroy(surface); } cairo_restore(cr); if(buf.buf) dt_mipmap_cache_release(darktable.mipmap_cache, &buf); if(img) dt_image_cache_read_release(darktable.image_cache, img); // ON CANVAS CONTROLS if(use_splitline) { float scale = fminf(1.0, fminf(w / pw, h / ph)); // image coordinates lib->overlay_x0 = 0.5 * (width - pw * scale); lib->overlay_y0 = 0.5 * (height - ph * scale + BAR_HEIGHT); lib->overlay_x1 = lib->overlay_x0 + pw * scale; lib->overlay_y1 = lib->overlay_y0 + ph * scale; // splitline position to absolute coords: double sl_x = lib->overlay_x0 + lib->splitline_x * pw * scale; double sl_y = lib->overlay_y0 + lib->splitline_y * ph * scale; int x0 = sl_x, y0 = 0.0, x1 = x0, y1 = height; if(lib->splitline_rotation % 2 != 0) { x0 = 0.0; y0 = sl_y; x1 = width; y1 = y0; } gboolean mouse_over_control = (lib->splitline_rotation % 2 == 0) ? (fabs(sl_x - pointerx) < 5) : (fabs(sl_y - pointery) < 5); cairo_save(cr); cairo_set_source_rgb(cr, .7, .7, .7); cairo_set_line_width(cr, (mouse_over_control ? 2.0 : 0.5)); cairo_move_to(cr, x0, y0); cairo_line_to(cr, x1, y1); cairo_stroke(cr); /* if mouse over control lets draw center rotate control, hide if split is dragged */ if(!lib->splitline_dragging && mouse_over_control) { cairo_set_line_width(cr, 0.5); double s = width * HANDLE_SIZE; dtgtk_cairo_paint_refresh(cr, sl_x - (s * 0.5), sl_y - (s * 0.5), s, s, 1); } cairo_restore(cr); } } // GUIDES if(cam->live_view_rotation % 2 == 1) { gint tmp = pw; pw = ph; ph = tmp; } float scale = 1.0; // if(cam->live_view_zoom == FALSE) // { if(pw > w) scale = w / pw; if(ph > h) scale = fminf(scale, h / ph); // } double sw = scale * pw; double sh = scale * ph; // draw guides int guide_flip = dt_bauhaus_combobox_get(lib->flip_guides); double left = (width - sw) * 0.5; double top = (height + BAR_HEIGHT - sh) * 0.5; double dashes = 5.0; cairo_save(cr); cairo_rectangle(cr, left, top, sw, sh); cairo_clip(cr); cairo_set_dash(cr, &dashes, 1, 0); // Move coordinates to local center selection. cairo_translate(cr, (sw / 2 + left), (sh / 2 + top)); // Flip horizontal. if(guide_flip & FLAG_FLIP_HORIZONTAL) cairo_scale(cr, -1, 1); // Flip vertical. if(guide_flip & FLAG_FLIP_VERTICAL) cairo_scale(cr, 1, -1); int which = dt_bauhaus_combobox_get(lib->guide_selector); dt_guides_t *guide = (dt_guides_t *)g_list_nth_data(darktable.guides, which - 1); if(guide) { guide->draw(cr, -sw / 2, -sh / 2, sw, sh, 1.0, guide->user_data); cairo_stroke_preserve(cr); cairo_set_dash(cr, &dashes, 0, 0); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_stroke(cr); } cairo_restore(cr); dt_pthread_mutex_unlock(&cam->live_view_pixbuf_mutex); }
void *dt_control_expose(void *voidptr) { int width, height, pointerx, pointery; if(!darktable.gui->surface) return NULL; width = dt_cairo_image_surface_get_width(darktable.gui->surface); height = dt_cairo_image_surface_get_height(darktable.gui->surface); GtkWidget *widget = dt_ui_center(darktable.gui->ui); #if GTK_CHECK_VERSION(3, 20, 0) gdk_window_get_device_position(gtk_widget_get_window(widget), gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))), &pointerx, &pointery, NULL); #else GdkDevice *device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget))); gdk_window_get_device_position(gtk_widget_get_window(widget), device, &pointerx, &pointery, NULL); #endif // create a gtk-independent surface to draw on cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); // TODO: control_expose: only redraw the part not overlapped by temporary control panel show! // float tb = 8; // fmaxf(10, width/100.0); darktable.control->tabborder = tb; darktable.control->width = width; darktable.control->height = height; GdkRGBA color; GtkStyleContext *context = gtk_widget_get_style_context(widget); gboolean color_found = gtk_style_context_lookup_color (context, "bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_set_line_width(cr, tb); cairo_rectangle(cr, tb / 2., tb / 2., width - tb, height - tb); cairo_stroke(cr); cairo_set_line_width(cr, 1.5); color_found = gtk_style_context_lookup_color (context, "really_dark_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_rectangle(cr, tb, tb, width - 2 * tb, height - 2 * tb); cairo_stroke(cr); cairo_save(cr); cairo_translate(cr, tb, tb); cairo_rectangle(cr, 0, 0, width - 2 * tb, height - 2 * tb); cairo_clip(cr); cairo_new_path(cr); // draw view dt_view_manager_expose(darktable.view_manager, cr, width - 2 * tb, height - 2 * tb, pointerx - tb, pointery - tb); cairo_restore(cr); // draw log message, if any dt_pthread_mutex_lock(&darktable.control->log_mutex); if(darktable.control->log_ack != darktable.control->log_pos) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, darktable.control->log_message[darktable.control->log_ack], -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float pad = DT_PIXEL_APPLY_DPI(20.0f), xc = width / 2.0; const float yc = height * 0.85 + DT_PIXEL_APPLY_DPI(10), wd = pad + ink.width * .5f; float rad = DT_PIXEL_APPLY_DPI(14); cairo_set_line_width(cr, 1.); cairo_move_to(cr, xc - wd, yc + rad); for(int k = 0; k < 5; k++) { cairo_arc(cr, xc - wd, yc, rad, M_PI / 2.0, 3.0 / 2.0 * M_PI); cairo_line_to(cr, xc + wd, yc - rad); cairo_arc(cr, xc + wd, yc, rad, 3.0 * M_PI / 2.0, M_PI / 2.0); cairo_line_to(cr, xc - wd, yc + rad); if(k == 0) { color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_fill_preserve(cr); } cairo_set_source_rgba(cr, 0., 0., 0., 1.0 / (1 + k)); cairo_stroke(cr); rad += .5f; } color_found = gtk_style_context_lookup_color (context, "fg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_move_to(cr, xc - wd + .5f * pad, (yc + 1. / 3. * fontsize) - fontsize); pango_cairo_show_layout(cr, layout); pango_font_description_free(desc); g_object_unref(layout); } // draw busy indicator if(darktable.control->log_busy > 0) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, _("working.."), -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float xc = width / 2.0, yc = height * 0.85 - DT_PIXEL_APPLY_DPI(30), wd = ink.width * .5f; cairo_move_to(cr, xc - wd, yc + 1. / 3. * fontsize - fontsize); pango_cairo_layout_path(cr, layout); cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); cairo_fill_preserve(cr); cairo_set_line_width(cr, 0.7); cairo_set_source_rgb(cr, 0.3, 0.3, 0.3); cairo_stroke(cr); pango_font_description_free(desc); g_object_unref(layout); } dt_pthread_mutex_unlock(&darktable.control->log_mutex); cairo_destroy(cr); cairo_t *cr_pixmap = cairo_create(darktable.gui->surface); cairo_set_source_surface(cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return NULL; }
int main (int argc, char **argv) { GOptionContext *context; GError *err; SwfdecPlayer *player; SwfdecURL *url; guint i; cairo_surface_t *surface; cairo_t *cr; gboolean aborts; glong play_per_file = 30; glong max_per_file = 60; glong max_per_advance = 10; GTimer *timer; char **filenames = NULL; const GOptionEntry entries[] = { { "play-time", 'p', 0, G_OPTION_ARG_INT, &play_per_file, "How many seconds will be played from each file (default 30)", NULL }, { "max-per-file", '\0', 0, G_OPTION_ARG_INT, &max_per_file, "Maximum runtime in seconds allowed for each file (default 60)", NULL }, { "max-per-advance", '\0', 0, G_OPTION_ARG_INT, &max_per_advance, "Maximum runtime in seconds allowed for each advance (default 10)", NULL }, { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, "<INPUT FILE> <OUTPUT FILE>" }, { NULL } }; // catch asserts and don't spew debug output by default g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING); g_setenv ("SWFDEC_DEBUG", "0", FALSE); // init swfdec_init (); // read command line params context = g_option_context_new ("Run a Flash file trying to crash Swfdec"); g_option_context_add_main_entries (context, entries, NULL); if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) { g_printerr ("Couldn't parse command-line options: %s\n", err->message); g_error_free (err); return 1; } if (filenames == NULL || g_strv_length (filenames) < 1) { g_printerr ("At least one input filename is required\n"); return 1; } // make them milliseconds play_per_file *= 1000; max_per_file *= 1000; max_per_advance *= 1000; // create surface surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1); cr = cairo_create (surface); aborts = FALSE; for (i = 0; i < g_strv_length (filenames); i++) { glong played, advance, elapsed; g_print ("Running: %s\n", filenames[i]); // start timer timer = g_timer_new (); player = swfdec_player_new (NULL); url = swfdec_url_new_from_input (filenames[i]); swfdec_player_set_url (player, url); swfdec_url_free (url); // loop until we have played what we wanted, or timelimit is hit played = 0; elapsed = 0; while (played < play_per_file && !swfdec_as_context_is_aborted (SWFDEC_AS_CONTEXT (player))) { elapsed = (glong)(g_timer_elapsed (timer, NULL) * 1000); if (elapsed >= max_per_file) break; swfdec_player_set_maximum_runtime (player, MIN (max_per_advance, max_per_file - elapsed)); advance = swfdec_player_get_next_event (player); if (advance == -1) break; played += swfdec_player_advance (player, advance); swfdec_player_render (player, cr); } if (elapsed >= max_per_file || swfdec_as_context_is_aborted (SWFDEC_AS_CONTEXT (player))) { g_print ("*** Aborted ***\n"); aborts = TRUE; } // clean up g_object_unref (player); g_timer_destroy (timer); } cairo_destroy (cr); cairo_surface_destroy (surface); if (aborts) { return 1; } else { return 0; } }
static cairo_status_t _cairo_clip_intersect_mask (cairo_clip_t *clip, cairo_traps_t *traps, cairo_antialias_t antialias, cairo_surface_t *target) { cairo_pattern_union_t pattern; cairo_box_t extents; cairo_rectangle_t surface_rect, target_rect; cairo_surface_t *surface; cairo_status_t status; /* Represent the clip as a mask surface. We create a new surface * the size of the intersection of the old mask surface and the * extents of the new clip path. */ _cairo_traps_extents (traps, &extents); _cairo_box_round_to_rectangle (&extents, &surface_rect); if (clip->surface != NULL) _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect); /* Intersect with the target surface rectangle so we don't use * more memory and time than we need to. */ status = _cairo_surface_get_extents (target, &target_rect); if (!status) _cairo_rectangle_intersect (&surface_rect, &target_rect); surface = _cairo_surface_create_similar_solid (target, CAIRO_CONTENT_ALPHA, surface_rect.width, surface_rect.height, CAIRO_COLOR_WHITE); if (surface->status) return CAIRO_STATUS_NO_MEMORY; /* Render the new clipping path into the new mask surface. */ _cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y); _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE); status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN, &pattern.base, surface, antialias, 0, 0, 0, 0, surface_rect.width, surface_rect.height, traps->traps, traps->num_traps); _cairo_pattern_fini (&pattern.base); if (status) { cairo_surface_destroy (surface); return status; } /* If there was a clip surface already, combine it with the new * mask surface using the IN operator, so we get the intersection * of the old and new clipping paths. */ if (clip->surface != NULL) { _cairo_pattern_init_for_surface (&pattern.surface, clip->surface); status = _cairo_surface_composite (CAIRO_OPERATOR_IN, &pattern.base, NULL, surface, surface_rect.x - clip->surface_rect.x, surface_rect.y - clip->surface_rect.y, 0, 0, 0, 0, surface_rect.width, surface_rect.height); _cairo_pattern_fini (&pattern.base); if (status) { cairo_surface_destroy (surface); return status; } cairo_surface_destroy (clip->surface); } clip->surface = surface; clip->surface_rect = surface_rect; clip->serial = _cairo_surface_allocate_clip_serial (target); return status; }
NS_IMETHODIMP compzillaRenderingContext::CopyImageDataFrom (Display *dpy, Window drawable, PRInt32 src_x, PRInt32 src_y, PRUint32 w, PRUint32 h) { DEBUG ("CopyImageDataFrom (%d,%d)\n", w, h); // XXX this is wrong, but it'll do for now. it needs to create a // (possibly smaller) subimage and composite it into the larger // mSurface. XImage *image = XGetImage (dpy, drawable, src_x, src_y, w, h, AllPlanes, ZPixmap); #ifdef MOZ_CAIRO_GFX DEBUG ("thebes\n"); gfxImageSurface *imagesurf = new gfxImageSurface(gfxIntSize (w, h), gfxASurface::ImageFormatARGB32); unsigned char *r = imagesurf->Data(); unsigned char *p = (unsigned char*)image->data; for (int i = 0; i < w * h; i ++) { *r++ = *p++; *r++ = *p++; *r++ = *p++; *r = 255; r++; p++; } mThebesContext->SetSource (imagesurf, gfxPoint (src_x, src_y)); mThebesContext->Paint (); #if 0 mThebesContext->DrawSurface (imagesurf, gfxSize (w, h)); #endif #else // Fix colors unsigned char *r = (unsigned char*)image->data; for (int i = 0; i < w * h; i ++) { r[3] = 255; r += 4; } if (mImageSurfaceData) { int stride = mWidth*4; PRUint8 *dest = mImageSurfaceData + stride*src_y + src_x*4; for (int32 i = 0; i < src_y; i++) { memcpy(dest, image->data + (w*4)*i, w*4); dest += stride; } } else { cairo_surface_t *imgsurf; imgsurf = cairo_image_surface_create_for_data ((unsigned char*)image->data, CAIRO_FORMAT_ARGB32, w, h, w*4); cairo_save (mCairo); cairo_identity_matrix (mCairo); cairo_translate (mCairo, src_x, src_y); cairo_new_path (mCairo); cairo_rectangle (mCairo, 0, 0, w, h); cairo_set_source_surface (mCairo, imgsurf, 0, 0); cairo_set_operator (mCairo, CAIRO_OPERATOR_SOURCE); cairo_fill (mCairo); cairo_restore (mCairo); cairo_surface_destroy (imgsurf); } #endif XFree (image); // XXX this redraws the entire canvas element. we only need to // force a redraw of the affected rectangle. return Redraw (); }
static void st_drawing_area_paint (ClutterActor *self) { StDrawingArea *area = ST_DRAWING_AREA (self); StDrawingAreaPrivate *priv = area->priv; StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self)); ClutterActorBox allocation_box; ClutterActorBox content_box; int width, height; CoglColor color; guint8 paint_opacity; (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class))->paint (self); clutter_actor_get_allocation_box (self, &allocation_box); st_theme_node_get_content_box (theme_node, &allocation_box, &content_box); width = (int)(0.5 + content_box.x2 - content_box.x1); height = (int)(0.5 + content_box.y2 - content_box.y1); if (priv->material == COGL_INVALID_HANDLE) priv->material = cogl_material_new (); if (priv->texture != COGL_INVALID_HANDLE && (width != cogl_texture_get_width (priv->texture) || height != cogl_texture_get_height (priv->texture))) { cogl_handle_unref (priv->texture); priv->texture = COGL_INVALID_HANDLE; } if (width > 0 && height > 0) { if (priv->texture == COGL_INVALID_HANDLE) { priv->texture = st_cogl_texture_new_with_size_wrapper (width, height, COGL_TEXTURE_NONE, CLUTTER_CAIRO_FORMAT_ARGB32); priv->needs_repaint = TRUE; } if (priv->needs_repaint) { cairo_surface_t *surface; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); priv->context = cairo_create (surface); priv->in_repaint = TRUE; priv->needs_repaint = FALSE; g_signal_emit ((GObject*)area, st_drawing_area_signals[REPAINT], 0); priv->in_repaint = FALSE; cairo_destroy (priv->context); priv->context = NULL; cogl_texture_set_region (priv->texture, 0, 0, 0, 0, width, height, width, height, CLUTTER_CAIRO_FORMAT_ARGB32, cairo_image_surface_get_stride (surface), cairo_image_surface_get_data (surface)); cairo_surface_destroy (surface); } } cogl_material_set_layer (priv->material, 0, priv->texture); if (priv->texture) { paint_opacity = clutter_actor_get_paint_opacity (self); cogl_color_set_from_4ub (&color, paint_opacity, paint_opacity, paint_opacity, paint_opacity); cogl_material_set_color (priv->material, &color); cogl_set_source (priv->material); cogl_rectangle_with_texture_coords (content_box.x1, content_box.y1, width, height, 0.0f, 0.0f, 1.0f, 1.0f); } }
/* * This is identical to nsCanvasRenderingContext2D::Render, we just don't * have a good place to put it; though maybe I want a CanvasContextImpl that * all this stuff can derive from? */ NS_METHOD compzillaRenderingContext::Render (nsIRenderingContext *rc) { DEBUG ("Render\n"); nsresult rv = NS_OK; #ifdef MOZ_CAIRO_GFX DEBUG ("thebes\n"); gfxContext* ctx = (gfxContext*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); nsRefPtr<gfxPattern> pat = new gfxPattern(mThebesSurface); // XXX I don't want to use PixelSnapped here, but layout doesn't guarantee // pixel alignment for this stuff! ctx->NewPath(); ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat); ctx->Fill(); #else DEBUG ("non-thebes\n"); // non-Thebes; this becomes exciting cairo_surface_t *dest = nsnull; cairo_t *dest_cr = nsnull; GdkDrawable *gdkdraw = nsnull; #ifdef MOZILLA_1_8_BRANCH rv = rc->RetrieveCurrentNativeGraphicData((void**) &gdkdraw); if (NS_FAILED(rv) || !gdkdraw) return NS_ERROR_FAILURE; #else gdkdraw = (GdkDrawable*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE); if (!gdkdraw) return NS_ERROR_FAILURE; #endif gint w, h; gdk_drawable_get_size (gdkdraw, &w, &h); dest = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY(gdkdraw), GDK_DRAWABLE_XID(gdkdraw), GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(gdkdraw)), w, h); dest_cr = cairo_create (dest); nsTransform2D *tx = nsnull; rc->GetCurrentTransform(tx); nsCOMPtr<nsIDeviceContext> dctx; rc->GetDeviceContext(*getter_AddRefs(dctx)); float x0 = 0.0, y0 = 0.0; float sx = 1.0, sy = 1.0; if (tx->GetType() & MG_2DTRANSLATION) { tx->Transform(&x0, &y0); } if (tx->GetType() & MG_2DSCALE) { sx = sy = dctx->DevUnitsToTwips(); tx->TransformNoXLate(&sx, &sy); } cairo_translate (dest_cr, NSToIntRound(x0), NSToIntRound(y0)); if (sx != 1.0 || sy != 1.0) cairo_scale (dest_cr, sx, sy); cairo_rectangle (dest_cr, 0, 0, mWidth, mHeight); cairo_clip (dest_cr); cairo_set_source_surface (dest_cr, mSurface, 0, 0); cairo_paint (dest_cr); if (dest_cr) cairo_destroy (dest_cr); if (dest) cairo_surface_destroy (dest); #endif return rv; }
void RenderJob::run() { XOJ_CHECK_TYPE(RenderJob); if(handler == NULL) { handler = new RepaintWidgetHandler(this->view->getXournal()->getWidget()); } double zoom = this->view->xournal->getZoom(); g_mutex_lock(this->view->repaintRectMutex); bool rerenderComplete = this->view->rerenderComplete; GList * rerenderRects = this->view->rerenderRects; this->view->rerenderRects = NULL; this->view->rerenderComplete = false; g_mutex_unlock(this->view->repaintRectMutex); if (rerenderComplete) { Document * doc = this->view->xournal->getDocument(); int dispWidth = this->view->getDisplayWidth(); int dispHeight = this->view->getDisplayHeight(); cairo_surface_t * crBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dispWidth, dispHeight); cairo_t * cr2 = cairo_create(crBuffer); cairo_scale(cr2, zoom, zoom); XojPopplerPage * popplerPage = NULL; doc->lock(); if (this->view->page.getBackgroundType() == BACKGROUND_TYPE_PDF) { int pgNo = this->view->page.getPdfPageNr(); popplerPage = doc->getPdfPage(pgNo); } DocumentView view; int width = this->view->page.getWidth(); int height = this->view->page.getHeight(); PdfView::drawPage(this->view->xournal->getCache(), popplerPage, cr2, zoom, width, height); view.drawPage(this->view->page, cr2, false); cairo_destroy(cr2); g_mutex_lock(this->view->drawingMutex); if (this->view->crBuffer) { cairo_surface_destroy(this->view->crBuffer); } this->view->crBuffer = crBuffer; g_mutex_unlock(this->view->drawingMutex); doc->unlock(); handler->repaintComplete(); } else { for (GList * l = rerenderRects; l != NULL; l = l->next) { Rectangle * rect = (Rectangle *) l->data; rerenderRectangle(rect); rect = this->view->rectOnWidget(rect->x, rect->y, rect->width, rect->height); handler->repaintRects(rect); } } // delete all rectangles for (GList * l = rerenderRects; l != NULL; l = l->next) { Rectangle * rect = (Rectangle *) l->data; delete rect; } g_list_free(rerenderRects); }
void cd_clock_clear_theme (GldiModuleInstance *myApplet, gboolean bClearAll) { if (myData.pBackgroundSurface != NULL) { cairo_surface_destroy (myData.pBackgroundSurface); myData.pBackgroundSurface = NULL; } if (myData.pForegroundSurface != NULL) { cairo_surface_destroy (myData.pForegroundSurface); myData.pForegroundSurface = NULL; } if (myData.iBgTexture != 0) { _cairo_dock_delete_texture (myData.iBgTexture); myData.iBgTexture = 0; } if (myData.iFgTexture != 0) { _cairo_dock_delete_texture (myData.iFgTexture); myData.iFgTexture = 0; } if (myData.iHourNeedleTexture != 0) { _cairo_dock_delete_texture (myData.iHourNeedleTexture); myData.iHourNeedleTexture = 0; } if (myData.iMinuteNeedleTexture != 0) { _cairo_dock_delete_texture (myData.iMinuteNeedleTexture); myData.iMinuteNeedleTexture = 0; } if (myData.iSecondNeedleTexture != 0) { _cairo_dock_delete_texture (myData.iSecondNeedleTexture); myData.iSecondNeedleTexture = 0; } if (myData.iDateTexture != 0) { _cairo_dock_delete_texture (myData.iDateTexture); myData.iDateTexture = 0; } if (myData.pNumericBgSurface != NULL) { cairo_surface_destroy (myData.pNumericBgSurface); myData.pNumericBgSurface = NULL; } if (bClearAll) { int i; for (i = 0; i < CLOCK_ELEMENTS; i ++) { if (myData.pSvgHandles[i] != NULL) { g_object_unref (myData.pSvgHandles[i]); myData.pSvgHandles[i] = NULL; } } } }
cairo_surface_t* pdf_page_image_get_cairo(zathura_page_t* page, mupdf_page_t* mupdf_page, zathura_image_t* image, zathura_error_t* error) { if (page == NULL || mupdf_page == NULL || image == NULL || image->data == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_INVALID_ARGUMENTS; } goto error_ret; } fz_image* mupdf_image = (fz_image*) image->data; fz_pixmap* pixmap = NULL; cairo_surface_t* surface = NULL; pixmap = fz_get_pixmap_from_image(mupdf_page->ctx, mupdf_image, NULL, NULL, 0, 0); if (pixmap == NULL) { goto error_free; } surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, mupdf_image->w, mupdf_image->h); if (surface == NULL) { goto error_free; } unsigned char* surface_data = cairo_image_surface_get_data(surface); int rowstride = cairo_image_surface_get_stride(surface); unsigned char* s = fz_pixmap_samples(mupdf_page->ctx, pixmap); unsigned int n = fz_pixmap_components(mupdf_page->ctx, pixmap); for (unsigned int y = 0; y < fz_pixmap_height(mupdf_page->ctx, pixmap); y++) { for (unsigned int x = 0; x < fz_pixmap_width(mupdf_page->ctx, pixmap); x++) { guchar* p = surface_data + y * rowstride + x * 4; // RGB if (n == 4) { p[0] = s[2]; p[1] = s[1]; p[2] = s[0]; // Gray-scale or mask } else { p[0] = s[0]; p[1] = s[0]; p[2] = s[0]; } s += n; } } fz_drop_pixmap(mupdf_page->ctx, pixmap); return surface; error_free: if (pixmap != NULL) { fz_drop_pixmap(mupdf_page->ctx, pixmap); } if (surface != NULL) { cairo_surface_destroy(surface); } error_ret: return NULL; }
void gimp_view_renderer_set_viewable (GimpViewRenderer *renderer, GimpViewable *viewable) { g_return_if_fail (GIMP_IS_VIEW_RENDERER (renderer)); g_return_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable)); if (viewable) g_return_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (viewable), renderer->viewable_type)); if (viewable == renderer->viewable) return; if (renderer->surface) { cairo_surface_destroy (renderer->surface); renderer->surface = NULL; } if (renderer->pixbuf) { g_object_unref (renderer->pixbuf); renderer->pixbuf = NULL; } gimp_view_renderer_transform_free (renderer); if (renderer->viewable) { g_object_weak_unref (G_OBJECT (renderer->viewable), (GWeakNotify) gimp_view_renderer_weak_notify, renderer); g_signal_handlers_disconnect_by_func (renderer->viewable, G_CALLBACK (gimp_view_renderer_invalidate), renderer); g_signal_handlers_disconnect_by_func (renderer->viewable, G_CALLBACK (gimp_view_renderer_size_changed), renderer); if (GIMP_IS_COLOR_MANAGED (renderer->viewable)) g_signal_handlers_disconnect_by_func (renderer->viewable, G_CALLBACK (gimp_view_renderer_profile_changed), renderer); } renderer->viewable = viewable; if (renderer->viewable) { g_object_weak_ref (G_OBJECT (renderer->viewable), (GWeakNotify) gimp_view_renderer_weak_notify, renderer); g_signal_connect_swapped (renderer->viewable, "invalidate-preview", G_CALLBACK (gimp_view_renderer_invalidate), renderer); g_signal_connect_swapped (renderer->viewable, "size-changed", G_CALLBACK (gimp_view_renderer_size_changed), renderer); if (GIMP_IS_COLOR_MANAGED (renderer->viewable)) g_signal_connect_swapped (renderer->viewable, "profile-changed", G_CALLBACK (gimp_view_renderer_profile_changed), renderer); if (renderer->size != -1) gimp_view_renderer_set_size (renderer, renderer->size, renderer->border_width); gimp_view_renderer_invalidate (renderer); } else { gimp_view_renderer_update_idle (renderer); } }
static void cairo_perf_trace (cairo_perf_t *perf, const cairo_boilerplate_target_t *target, const char *trace) { static cairo_bool_t first_run = TRUE; unsigned int i; cairo_time_t *times, *paint, *mask, *fill, *stroke, *glyphs; cairo_stats_t stats = {0.0, 0.0}; struct trace args = { target }; int low_std_dev_count; char *trace_cpy, *name; const cairo_script_interpreter_hooks_t hooks = { &args, perf->tile_size ? _tiling_surface_create : _similar_surface_create, NULL, /* surface_destroy */ _context_create, NULL, /* context_destroy */ NULL, /* show_page */ NULL, /* copy_page */ _source_image_create, }; args.tile_size = perf->tile_size; args.observe = perf->observe; trace_cpy = xstrdup (trace); name = basename_no_ext (trace_cpy); if (perf->list_only) { printf ("%s\n", name); free (trace_cpy); return; } if (first_run) { if (perf->raw) { printf ("[ # ] %s.%-s %s %s %s ...\n", "backend", "content", "test-size", "ticks-per-ms", "time(ticks)"); } if (perf->summary) { if (perf->observe) { fprintf (perf->summary, "[ # ] %8s %28s %9s %9s %9s %9s %9s %9s %5s\n", "backend", "test", "total(s)", "paint(s)", "mask(s)", "fill(s)", "stroke(s)", "glyphs(s)", "count"); } else { fprintf (perf->summary, "[ # ] %8s %28s %8s %5s %5s %s\n", "backend", "test", "min(s)", "median(s)", "stddev.", "count"); } } first_run = FALSE; } times = perf->times; paint = times + perf->iterations; mask = paint + perf->iterations; stroke = mask + perf->iterations; fill = stroke + perf->iterations; glyphs = fill + perf->iterations; low_std_dev_count = 0; for (i = 0; i < perf->iterations && ! user_interrupt; i++) { cairo_script_interpreter_t *csi; cairo_status_t status; unsigned int line_no; args.surface = target->create_surface (NULL, CAIRO_CONTENT_COLOR_ALPHA, 1, 1, 1, 1, CAIRO_BOILERPLATE_MODE_PERF, &args.closure); fill_surface(args.surface); /* remove any clear flags */ if (perf->observe) { cairo_surface_t *obs; obs = cairo_surface_create_observer (args.surface, CAIRO_SURFACE_OBSERVER_NORMAL); cairo_surface_destroy (args.surface); args.surface = obs; } if (cairo_surface_status (args.surface)) { fprintf (stderr, "Error: Failed to create target surface: %s\n", target->name); return; } cairo_perf_timer_set_synchronize (target->synchronize, args.closure); if (i == 0) { describe (perf, args.closure); if (perf->summary) { fprintf (perf->summary, "[%3d] %8s %28s ", perf->test_number, perf->target->name, name); fflush (perf->summary); } } csi = cairo_script_interpreter_create (); cairo_script_interpreter_install_hooks (csi, &hooks); if (! perf->observe) { cairo_perf_yield (); cairo_perf_timer_start (); } cairo_script_interpreter_run (csi, trace); line_no = cairo_script_interpreter_get_line_number (csi); /* Finish before querying timings in case we are using an intermediate * target and so need to destroy all surfaces before rendering * commences. */ cairo_script_interpreter_finish (csi); if (perf->observe) { cairo_device_t *observer = cairo_surface_get_device (args.surface); times[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_elapsed (observer)); paint[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_paint_elapsed (observer)); mask[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_mask_elapsed (observer)); stroke[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_stroke_elapsed (observer)); fill[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_fill_elapsed (observer)); glyphs[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_glyphs_elapsed (observer)); } else { fill_surface (args.surface); /* queue a write to the sync'ed surface */ cairo_perf_timer_stop (); times[i] = cairo_perf_timer_elapsed (); } scache_clear (); cairo_surface_destroy (args.surface); if (target->cleanup) target->cleanup (args.closure); status = cairo_script_interpreter_destroy (csi); if (status) { if (perf->summary) { fprintf (perf->summary, "Error during replay, line %d: %s\n", line_no, cairo_status_to_string (status)); } goto out; } if (perf->raw) { if (i == 0) printf ("[*] %s.%s %s.%d %g", perf->target->name, "rgba", name, 0, _cairo_time_to_double (_cairo_time_from_s (1)) / 1000.); printf (" %lld", (long long) times[i]); fflush (stdout); } else if (! perf->exact_iterations) { if (i > CAIRO_PERF_MIN_STD_DEV_COUNT) { _cairo_stats_compute (&stats, times, i+1); if (stats.std_dev <= CAIRO_PERF_LOW_STD_DEV) { if (++low_std_dev_count >= CAIRO_PERF_STABLE_STD_DEV_COUNT) break; } else { low_std_dev_count = 0; } } } if (perf->summary && perf->summary_continuous) { _cairo_stats_compute (&stats, times, i+1); fprintf (perf->summary, "\r[%3d] %8s %28s ", perf->test_number, perf->target->name, name); if (perf->observe) { fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, paint, i+1); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, mask, i+1); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, fill, i+1); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, stroke, i+1); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, glyphs, i+1); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); fprintf (perf->summary, " %5d", i+1); } else { fprintf (perf->summary, "%#8.3f %#8.3f %#6.2f%% %4d/%d", _cairo_time_to_s (stats.min_ticks), _cairo_time_to_s (stats.median_ticks), stats.std_dev * 100.0, stats.iterations, i+1); } fflush (perf->summary); } } user_interrupt = 0; if (perf->summary) { _cairo_stats_compute (&stats, times, i); if (perf->summary_continuous) { fprintf (perf->summary, "\r[%3d] %8s %28s ", perf->test_number, perf->target->name, name); } if (perf->observe) { fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, paint, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, mask, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, fill, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, stroke, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); _cairo_stats_compute (&stats, glyphs, i); fprintf (perf->summary, " %#9.3f", _cairo_time_to_s (stats.median_ticks)); fprintf (perf->summary, " %5d\n", i); } else { fprintf (perf->summary, "%#8.3f %#8.3f %#6.2f%% %4d/%d\n", _cairo_time_to_s (stats.min_ticks), _cairo_time_to_s (stats.median_ticks), stats.std_dev * 100.0, stats.iterations, i); } fflush (perf->summary); } out: if (perf->raw) { printf ("\n"); fflush (stdout); } perf->test_number++; free (trace_cpy); }
static void gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer, GtkWidget *widget, GimpTempBuf *temp_buf, gint temp_buf_x, gint temp_buf_y, gint channel, GimpViewBG inside_bg, GimpViewBG outside_bg, cairo_surface_t *surface, gint surface_width, gint surface_height) { cairo_t *cr; gint x, y; gint width, height; const Babl *temp_buf_format; gint temp_buf_width; gint temp_buf_height; g_return_if_fail (temp_buf != NULL); g_return_if_fail (surface != NULL); temp_buf_format = gimp_temp_buf_get_format (temp_buf); temp_buf_width = gimp_temp_buf_get_width (temp_buf); temp_buf_height = gimp_temp_buf_get_height (temp_buf); /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color * 3) Background check buffer for transparent temp_bufs * 4) Using the optional "channel" argument, one channel can be extracted * from a multi-channel temp_buf and composited as a grayscale * Prereqs: * 1) Grayscale temp_bufs have bytes == {1, 2} * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ cr = cairo_create (surface); if (outside_bg == GIMP_VIEW_BG_CHECKS || inside_bg == GIMP_VIEW_BG_CHECKS) { if (! renderer->pattern) renderer->pattern = gimp_cairo_checkerboard_create (cr, GIMP_CHECK_SIZE_SM, gimp_render_light_check_color (), gimp_render_dark_check_color ()); } switch (outside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_paint (cr); if (! gimp_rectangle_intersect (0, 0, surface_width, surface_height, temp_buf_x, temp_buf_y, temp_buf_width, temp_buf_height, &x, &y, &width, &height)) { cairo_destroy (cr); return; } if (inside_bg != outside_bg && babl_format_has_alpha (temp_buf_format) && channel == -1) { cairo_rectangle (cr, x, y, width, height); switch (inside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_fill (cr); } if (babl_format_has_alpha (temp_buf_format) && channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_t *alpha_surface; alpha_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (alpha_surface); cairo_translate (cr, x, y); cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_surface (cr, alpha_surface, 0, 0); cairo_fill (cr); cairo_surface_destroy (alpha_surface); } else if (channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_flush (surface); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (surface); } else { const Babl *fish; const guchar *src; guchar *dest; gint dest_stride; gint bytes; gint rowstride; gint i; cairo_surface_flush (surface); bytes = babl_format_get_bytes_per_pixel (temp_buf_format); rowstride = temp_buf_width * bytes; src = gimp_temp_buf_get_data (temp_buf) + ((y - temp_buf_y) * rowstride + (x - temp_buf_x) * bytes); dest = cairo_image_surface_get_data (surface); dest_stride = cairo_image_surface_get_stride (surface); dest += y * dest_stride + x * 4; fish = babl_fish (temp_buf_format, babl_format ("cairo-RGB24")); for (i = y; i < (y + height); i++) { const guchar *s = src; guchar *d = dest; gint j; for (j = x; j < (x + width); j++, d += 4, s += bytes) { if (bytes > 2) { guchar pixel[4] = { s[channel], s[channel], s[channel], 255 }; babl_process (fish, pixel, d, 1); } else { guchar pixel[2] = { s[channel], 255 }; babl_process (fish, pixel, d, 1); } } src += rowstride; dest += dest_stride; } cairo_surface_mark_dirty (surface); } cairo_destroy (cr); }
int main(int argc, char **argv) { char *image_path = NULL; char *scaling_mode_str = "fit"; uint32_t color = 0xFFFFFFFF; init_log(L_INFO); static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"color", required_argument, NULL, 'c'}, {"image", required_argument, NULL, 'i'}, {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, {0, 0, 0, 0} }; const char *usage = "Usage: swaylock [options...]\n" "\n" " -h, --help Show help message and quit.\n" " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" " -t, --tiling Same as --scaling=tile.\n" " -v, --version Show the version number and quit.\n" " -i, --image <path> Display the given image.\n"; int c; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hc:i:s:tv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'c': { int colorlen = strlen(optarg); if (colorlen < 6 || colorlen == 7 || colorlen > 8) { fprintf(stderr, "color must be specified in 3 or 4 byte format, e.g. ff0000 or ff0000ff\n"); exit(EXIT_FAILURE); } color = strtol(optarg, NULL, 16); if (colorlen == 6) { color <<= 8; color |= 0xFF; } sway_log(L_DEBUG, "color: 0x%x", color); break; } case 'i': image_path = optarg; break; case 's': scaling_mode_str = optarg; break; case 't': scaling_mode_str = "tile"; break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); #else fprintf(stdout, "version not detected\n"); #endif exit(EXIT_SUCCESS); break; default: fprintf(stderr, "%s", usage); exit(EXIT_FAILURE); } } enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; if (strcmp(scaling_mode_str, "stretch") == 0) { scaling_mode = SCALING_MODE_STRETCH; } else if (strcmp(scaling_mode_str, "fill") == 0) { scaling_mode = SCALING_MODE_FILL; } else if (strcmp(scaling_mode_str, "fit") == 0) { scaling_mode = SCALING_MODE_FIT; } else if (strcmp(scaling_mode_str, "center") == 0) { scaling_mode = SCALING_MODE_CENTER; } else if (strcmp(scaling_mode_str, "tile") == 0) { scaling_mode = SCALING_MODE_TILE; } else { sway_abort("Unsupported scaling mode: %s", scaling_mode_str); } password_size = 1024; password = malloc(password_size); password[0] = '\0'; surfaces = create_list(); registry = registry_poll(); if (!registry) { sway_abort("Unable to connect to wayland compositor"); } if (!registry->swaylock) { sway_abort("swaylock requires the compositor to support the swaylock extension."); } if (registry->pointer) { // We don't want swaylock to have a pointer wl_pointer_destroy(registry->pointer); registry->pointer = NULL; } int i; for (i = 0; i < registry->outputs->length; ++i) { struct output_state *output = registry->outputs->items[i]; struct window *window = window_setup(registry, output->width, output->height, true); if (!window) { sway_abort("Failed to create surfaces."); } list_add(surfaces, window); } registry->input->notify = notify_key; cairo_surface_t *image = NULL; if (image_path) { #ifdef WITH_GDK_PIXBUF GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); if (!pixbuf) { sway_abort("Failed to load background image."); } image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); g_object_unref(pixbuf); #else cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); #endif //WITH_GDK_PIXBUF if (!image) { sway_abort("Failed to read background image."); } } for (i = 0; i < surfaces->length; ++i) { struct window *window = surfaces->items[i]; if (!window_prerender(window) || !window->cairo) { continue; } if (image) { render_image(window, image, scaling_mode); } else { render_color(window, color); } } if (image) { cairo_surface_destroy(image); } bool locked = false; while (wl_display_dispatch(registry->display) != -1) { if (!locked) { for (i = 0; i < registry->outputs->length; ++i) { struct output_state *output = registry->outputs->items[i]; struct window *window = surfaces->items[i]; lock_set_lock_surface(registry->swaylock, output->output, window->surface); } locked = true; } } for (i = 0; i < surfaces->length; ++i) { struct window *window = surfaces->items[i]; window_teardown(window); } list_free(surfaces); registry_teardown(registry); return 0; }
/** * gd_embed_image_in_frame: * @source_image: * @frame_image_path: * @slice_width: * @border_width: * * Returns: (transfer full): */ GdkPixbuf * gd_embed_image_in_frame (GdkPixbuf *source_image, const gchar *frame_image_path, GtkBorder *slice_width, GtkBorder *border_width) { cairo_surface_t *surface; cairo_t *cr; int source_width, source_height; int dest_width, dest_height; gchar *css_str; GtkCssProvider *provider; GtkStyleContext *context; GError *error = NULL; GdkPixbuf *retval; GtkWidgetPath *path; source_width = gdk_pixbuf_get_width (source_image); source_height = gdk_pixbuf_get_height (source_image); dest_width = source_width + border_width->left + border_width->right; dest_height = source_height + border_width->top + border_width->bottom; css_str = g_strdup_printf (".embedded-image { border-image: url(\"%s\") %d %d %d %d / %dpx %dpx %dpx %dpx }", frame_image_path, slice_width->top, slice_width->right, slice_width->bottom, slice_width->left, border_width->top, border_width->right, border_width->bottom, border_width->left); provider = gtk_css_provider_new (); gtk_css_provider_load_from_data (provider, css_str, -1, &error); if (error != NULL) { g_warning ("Unable to create the thumbnail frame image: %s", error->message); g_error_free (error); g_free (css_str); return g_object_ref (source_image); } surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, dest_width, dest_height); cr = cairo_create (surface); context = gtk_style_context_new (); path = gtk_widget_path_new (); gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW); gtk_style_context_set_path (context, path); gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), 600); gtk_style_context_save (context); gtk_style_context_add_class (context, "embedded-image"); gtk_render_frame (context, cr, 0, 0, dest_width, dest_height); gtk_style_context_restore (context); gtk_render_icon (context, cr, source_image, border_width->left, border_width->top); retval = gdk_pixbuf_get_from_surface (surface, 0, 0, dest_width, dest_height); cairo_surface_destroy (surface); cairo_destroy (cr); gtk_widget_path_unref (path); g_object_unref (provider); g_object_unref (context); g_free (css_str); return retval; }
void SaveSummary(const std::string &fname, Result &result, Config &config) { #if 0 const float fnorm = 2.f / sqrtf(result.npoints); const float rnorm = 1.f / sqrtf(2.f / (SQRT3 * result.npoints)); const int csize = 512; // Composition cell size const double dashes[] = { 6.0, 3.0 }; cairo_surface_t *surface = cairo_pdf_surface_create(fname.c_str(), 2*csize, 1.5*csize); cairo_pdf_surface_restrict_to_version(surface, CAIRO_PDF_VERSION_1_4); cairo_t *cr = cairo_create(surface); unsigned char *imgdata = NULL; cairo_surface_t *image = NULL; // Draw points const float radius = 2.0; cairo_identity_matrix(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1); for (int i = 0; i < result.points.size(); ++i) { float x = result.points[i].x * csize; float y = (1.f - result.points[i].y) * csize; cairo_arc(cr, x, y, radius, 0, TWOPI); cairo_fill(cr); } // Draw radial power reference level cairo_identity_matrix(cr); cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1); cairo_set_line_width(cr, 1.0); cairo_set_dash(cr, dashes, 2, 0); const float rpref = 1.f - (1.f - config.fymin) / (config.fymax - config.fymin); cairo_move_to(cr, csize, csize + rpref*csize/2); cairo_line_to(cr, 2*csize, csize + rpref*csize/2); cairo_stroke(cr); // Draw radial power cairo_identity_matrix(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_line_width(cr, 1.0); cairo_set_dash(cr, NULL, 0, 0); for (int i = 0; i < result.rp.size(); ++i) { float x = i / (float) result.rp.size(); float y = 1.f - (result.rp[i] - config.fymin) / (config.fymax - config.fymin); Clamp01(y); if (i == 0) cairo_move_to(cr, csize + x*csize, csize + y*csize/2); else cairo_line_to(cr, csize + x*csize, csize + y*csize/2); } cairo_stroke(cr); // Draw spectrum int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, result.spectrum.width); result.spectrum.GetRGBA(imgdata); image = cairo_image_surface_create_for_data(imgdata, CAIRO_FORMAT_RGB24, result.spectrum.width, result.spectrum.height, stride); cairo_identity_matrix(cr); cairo_translate(cr, csize, 0); cairo_scale(cr, csize / (float) result.spectrum.width, csize / (float) result.spectrum.height); cairo_set_source_surface(cr, image, 0, 0); cairo_paint(cr); // Draw RDF reference level cairo_identity_matrix(cr); cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1); cairo_set_line_width(cr, 1.0); cairo_set_dash(cr, dashes, 2, 0); const float rdfref = 1.f - (1.f - config.rymin) / (config.rymax - config.rymin); cairo_move_to(cr, 0, csize + rdfref*csize/2); cairo_line_to(cr, csize, csize + rdfref*csize/2); cairo_stroke(cr); // Draw RDF cairo_identity_matrix(cr); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_set_line_width(cr, 1.0); cairo_set_dash(cr, NULL, 0, 0); for (int i = 0; i < result.rdf.size(); ++i) { float x = i / (float) result.rdf.size(); float y = 1.f - (result.rdf[i] - config.rymin) / (config.rymax - config.rymin); Clamp01(y); if (i == 0) cairo_move_to(cr, x*csize, csize + y*csize/2); else cairo_line_to(cr, x*csize, csize + y*csize/2); } cairo_stroke(cr); // Draw separators cairo_identity_matrix(cr); cairo_set_line_width(cr, 1.0); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_move_to(cr, 0, csize); cairo_line_to(cr, 2*csize, csize); cairo_stroke(cr); cairo_move_to(cr, csize, 0); cairo_line_to(cr, csize, 1.5*csize); cairo_stroke(cr); // Draw labels cairo_identity_matrix(cr); cairo_set_font_size(cr, 12.0); cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_move_to(cr, 0.0125 * csize, 1.025 * csize); cairo_show_text(cr, "RDF"); cairo_stroke(cr); cairo_move_to(cr, 1.0125 * csize, 1.025 * csize); cairo_show_text(cr, "Power Spectrum"); cairo_stroke(cr); // Draw stats box #ifdef PSA_HAS_CGAL int nlines = 5; #else int nlines = 4; #endif nlines += (result.nsets > 1); double offset = 0.03; double bsize[] = { 0.33 * csize, (nlines * offset + 0.01) * csize }; double banchor = 0.0125 * csize; cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.7); cairo_rectangle(cr, banchor, banchor, bsize[0], bsize[1]); cairo_fill(cr); // Draw stats and corresponding labels cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); cairo_set_font_size(cr, 12.0); cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); const int len = 128; char label[len]; double tanchor[2] = { 1.75 * banchor, 0.9 * banchor }; int i = 1; if (result.nsets > 1) { snprintf(label, len, "Averaged over %d sets", result.nsets); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); cairo_show_text(cr, label); ++i; } snprintf(label, len, "Gbl. Mindist %.5f", result.stats.mindist * rnorm); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i; cairo_show_text(cr, label); snprintf(label, len, "Avg. Mindist %.5f", result.stats.avgmindist * rnorm); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i; cairo_show_text(cr, label); #ifdef PSA_HAS_CGAL snprintf(label, len, "Orient. order %.5f", result.stats.orientorder); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i; cairo_show_text(cr, label); #endif snprintf(label, len, "Eff. Nyquist %.5f", result.stats.effnyquist * fnorm); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i; cairo_show_text(cr, label); snprintf(label, len, "Oscillations %.5f", result.stats.oscillations); cairo_move_to(cr, tanchor[0], tanchor[1] + i * offset * csize); ++i; cairo_show_text(cr, label); cairo_stroke(cr); // Save and clean up cairo_show_page(cr); cairo_surface_destroy(image); if (imgdata) delete[] imgdata; cairo_destroy(cr); cairo_surface_destroy(surface); #endif }
/** * gd_create_collection_icon: * @base_size: * @pixbufs: (element-type GdkPixbuf): * * Returns: (transfer full): */ GIcon * gd_create_collection_icon (gint base_size, GList *pixbufs) { cairo_surface_t *surface; GIcon *retval; cairo_t *cr; GtkStyleContext *context; GtkWidgetPath *path; gint padding, tile_size, scale_size; gint pix_width, pix_height; gint idx, cur_x, cur_y; GList *l; GdkPixbuf *pix; /* TODO: do not hardcode 4, but scale to another layout if more * pixbufs are provided. */ padding = MAX (floor (base_size / 10), 4); tile_size = (base_size - (3 * padding)) / 2; context = gtk_style_context_new (); gtk_style_context_add_class (context, "documents-collection-icon"); path = gtk_widget_path_new (); gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW); gtk_style_context_set_path (context, path); gtk_widget_path_unref (path); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, base_size, base_size); cr = cairo_create (surface); gtk_render_background (context, cr, 0, 0, base_size, base_size); l = pixbufs; idx = 0; cur_x = padding; cur_y = padding; while (l != NULL && idx < 4) { pix = l->data; pix_width = gdk_pixbuf_get_width (pix); pix_height = gdk_pixbuf_get_height (pix); scale_size = MIN (pix_width, pix_height); cairo_save (cr); cairo_translate (cr, cur_x, cur_y); cairo_rectangle (cr, 0, 0, tile_size, tile_size); cairo_clip (cr); cairo_scale (cr, (gdouble) tile_size / (gdouble) scale_size, (gdouble) tile_size / (gdouble) scale_size); gdk_cairo_set_source_pixbuf (cr, pix, 0, 0); cairo_paint (cr); cairo_restore (cr); if ((idx % 2) == 0) { cur_x += tile_size + padding; } else { cur_x = padding; cur_y += tile_size + padding; } idx++; l = l->next; } retval = G_ICON (gdk_pixbuf_get_from_surface (surface, 0, 0, base_size, base_size)); cairo_surface_destroy (surface); cairo_destroy (cr); g_object_unref (context); return retval; }
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; }
/** * gd_create_symbolic_icon: * @name: * * Returns: (transfer full): */ GIcon * gd_create_symbolic_icon (const gchar *name, gint base_size) { gchar *symbolic_name; GIcon *icon, *retval = NULL; cairo_surface_t *surface; cairo_t *cr; GtkStyleContext *style; GtkWidgetPath *path; GdkPixbuf *pixbuf; GtkIconTheme *theme; GtkIconInfo *info; gint bg_size; gint emblem_size; gint total_size; total_size = base_size / 2; bg_size = MAX (total_size / 2, _BG_MIN_SIZE); emblem_size = MAX (bg_size - 8, _EMBLEM_MIN_SIZE); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, total_size, total_size); cr = cairo_create (surface); style = gtk_style_context_new (); path = gtk_widget_path_new (); gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW); gtk_style_context_set_path (style, path); gtk_widget_path_unref (path); gtk_style_context_add_class (style, "documents-icon-bg"); gtk_render_background (style, cr, (total_size - bg_size) / 2, (total_size - bg_size) / 2, bg_size, bg_size); symbolic_name = g_strconcat (name, "-symbolic", NULL); icon = g_themed_icon_new_with_default_fallbacks (symbolic_name); g_free (symbolic_name); theme = gtk_icon_theme_get_default(); info = gtk_icon_theme_lookup_by_gicon (theme, icon, emblem_size, GTK_ICON_LOOKUP_FORCE_SIZE); g_object_unref (icon); if (info == NULL) goto out; pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL); gtk_icon_info_free (info); if (pixbuf == NULL) goto out; gtk_render_icon (style, cr, pixbuf, (total_size - emblem_size) / 2, (total_size - emblem_size) / 2); g_object_unref (pixbuf); retval = G_ICON (gdk_pixbuf_get_from_surface (surface, 0, 0, total_size, total_size)); out: g_object_unref (style); cairo_surface_destroy (surface); cairo_destroy (cr); return retval; }
FlashPlayerWidget::~FlashPlayerWidget() { cairo_surface_destroy( d->surface ); }
int main(int argc, char* argv[]) { std::string map; std::string style; double latTop,latBottom,lonLeft,lonRight; unsigned int startZoom; unsigned int endZoom; unsigned int tileWidth; unsigned int tileHeight; std::string driver; #if defined(HAVE_LIB_GPERFTOOLS) bool heapProfile; std::string heapProfilePrefix; #endif if (argc<12) { std::cerr << "DrawMap " << std::endl; std::cerr << " <map directory> <style-file> " << std::endl; std::cerr << " <lat_top> <lon_left> <lat_bottom> <lon_right> " << std::endl; std::cerr << " <start zoom> <end zoom>" << std::endl; std::cerr << " <tile width> <tile height>" << std::endl; std::cerr << " <cairo|Qt|noop|none>" << std::endl; #if defined(HAVE_LIB_GPERFTOOLS) std::cerr << " [heap profile prefix]" << std::endl; #endif return 1; } #if defined(HAVE_LIB_GPERFTOOLS) heapProfile = false; if (argc>12) { heapProfile = true; heapProfilePrefix = argv[12]; } #endif map=argv[1]; style=argv[2]; if (sscanf(argv[3],"%lf",&latTop)!=1) { std::cerr << "lon is not numeric!" << std::endl; return 1; } if (sscanf(argv[4],"%lf",&lonLeft)!=1) { std::cerr << "lat is not numeric!" << std::endl; return 1; } if (sscanf(argv[5],"%lf",&latBottom)!=1) { std::cerr << "lon is not numeric!" << std::endl; return 1; } if (sscanf(argv[6],"%lf",&lonRight)!=1) { std::cerr << "lat is not numeric!" << std::endl; return 1; } if (sscanf(argv[7],"%u",&startZoom)!=1) { std::cerr << "start zoom is not numeric!" << std::endl; return 1; } if (sscanf(argv[8],"%u",&endZoom)!=1) { std::cerr << "end zoom is not numeric!" << std::endl; return 1; } if (sscanf(argv[9],"%u",&tileWidth)!=1) { std::cerr << "tile width is not numeric!" << std::endl; return 1; } if (sscanf(argv[10],"%u",&tileHeight)!=1) { std::cerr << "tile height is not numeric!" << std::endl; return 1; } driver=argv[11]; #if defined(HAVE_LIB_OSMSCOUTMAPCAIRO) cairo_surface_t * cairoSurface=NULL; cairo_t *cairo=NULL; #endif #if defined(HAVE_LIB_OSMSCOUTMAPQT) QPixmap *qtPixmap=NULL; QPainter *qtPainter=NULL; SailfishApp::application(argc, argv); #endif if (driver=="cairo") { std::cout << "Using driver 'cairo'..." << std::endl; #if defined(HAVE_LIB_OSMSCOUTMAPCAIRO) cairoSurface=cairo_image_surface_create(CAIRO_FORMAT_RGB24,tileWidth,tileHeight); if (cairoSurface==NULL) { std::cerr << "Cannot create cairo image cairoSurface" << std::endl; return 1; } cairo=cairo_create(cairoSurface); if (cairo==NULL) { std::cerr << "Cannot create cairo_t for image cairoSurface" << std::endl; return 1; } #else std::cerr << "Driver 'cairo' is not enabled" << std::endl; return 1; #endif } else if (driver=="Qt") { std::cout << "Using driver 'Qt'..." << std::endl; #if defined(HAVE_LIB_OSMSCOUTMAPQT) qtPixmap=new QPixmap(tileWidth,tileHeight); if (qtPixmap==NULL) { std::cerr << "Cannot create QPixmap" << std::endl; return 1; } qtPainter=new QPainter(qtPixmap); if (qtPainter==NULL) { std::cerr << "Cannot create QPainter image cairoSurface" << std::endl; return 1; } #else std::cerr << "Driver 'Qt' is not enabled" << std::endl; return 1; #endif } else if (driver=="noop") { std::cout << "Using driver 'noop'..." << std::endl; } else if (driver=="none") { std::cout << "Using driver 'none'..." << std::endl; } else { std::cerr << "Unsupported driver '" << driver << "'" << std::endl; return 1; } osmscout::DatabaseParameter databaseParameter; //databaseParameter.SetDebugPerformance(true); osmscout::DatabaseRef database=std::make_shared<osmscout::Database>(databaseParameter); osmscout::MapServiceRef mapService=std::make_shared<osmscout::MapService>(database); if (!database->Open(map.c_str())) { std::cerr << "Cannot open database" << std::endl; return 1; } osmscout::StyleConfigRef styleConfig=std::make_shared<osmscout::StyleConfig>(database->GetTypeConfig()); if (!styleConfig->Load(style)) { std::cerr << "Cannot open style" << std::endl; return 1; } #if defined(HAVE_LIB_GPERFTOOLS) if (heapProfile){ HeapProfilerStart(heapProfilePrefix.c_str()); } #endif osmscout::TileProjection projection; osmscout::MapParameter drawParameter; osmscout::AreaSearchParameter searchParameter; std::list<LevelStats> statistics; searchParameter.SetUseMultithreading(true); for (uint32_t level=std::min(startZoom,endZoom); level<=std::max(startZoom,endZoom); level++) { LevelStats stats(level); osmscout::Magnification magnification; int xTileStart,xTileEnd,xTileCount,yTileStart,yTileEnd,yTileCount; magnification.SetLevel(level); xTileStart=osmscout::LonToTileX(std::min(lonLeft,lonRight), magnification); xTileEnd=osmscout::LonToTileX(std::max(lonLeft,lonRight), magnification); xTileCount=xTileEnd-xTileStart+1; yTileStart=osmscout::LatToTileY(std::max(latTop,latBottom), magnification); yTileEnd=osmscout::LatToTileY(std::min(latTop,latBottom), magnification); yTileCount=yTileEnd-yTileStart+1; std::cout << "----------" << std::endl; std::cout << "Drawing level " << level << ", " << (xTileCount)*(yTileCount) << " tiles [" << xTileStart << "," << yTileStart << " - " << xTileEnd << "," << yTileEnd << "]" << std::endl; #if defined(HAVE_LIB_OSMSCOUTMAPCAIRO) osmscout::MapPainterCairo cairoMapPainter(styleConfig); #endif #if defined(HAVE_LIB_OSMSCOUTMAPQT) osmscout::MapPainterQt qtMapPainter(styleConfig); #endif osmscout::MapPainterNoOp noOpMapPainter(styleConfig); size_t current=1; size_t tileCount=(yTileEnd-yTileStart+1)*(xTileEnd-xTileStart+1); size_t delta=tileCount/20; if (delta==0) { delta=1; } for (int y=yTileStart; y<=yTileEnd; y++) { for (int x=xTileStart; x<=xTileEnd; x++) { osmscout::MapData data; osmscout::GeoBox boundingBox; if ((current % delta)==0) { std::cout << current*100/tileCount << "% " << current; if (stats.tileCount>0) { std::cout << " " << stats.dbTotalTime/stats.tileCount; std::cout << " " << stats.drawTotalTime/stats.tileCount; } std::cout << std::endl; } projection.Set(x-1,y-1, x+1,y+1, magnification, DPI, tileWidth, tileHeight); projection.GetDimensions(boundingBox); projection.SetLinearInterpolationUsage(level >= 10); osmscout::StopClock dbTimer; osmscout::GeoBox dataBoundingBox(osmscout::GeoCoord(osmscout::TileYToLat(y-1,magnification),osmscout::TileXToLon(x-1,magnification)), osmscout::GeoCoord(osmscout::TileYToLat(y+1,magnification),osmscout::TileXToLon(x+1,magnification))); std::list<osmscout::TileRef> tiles; // set cache size almost unlimited, // for better estimate of peak memory usage by tile loading mapService->SetCacheSize(10000000); mapService->LookupTiles(magnification,dataBoundingBox,tiles); mapService->LoadMissingTileData(searchParameter,*styleConfig,tiles); mapService->ConvertTilesToMapData(tiles,data); stats.nodeCount+=data.nodes.size(); stats.wayCount+=data.ways.size(); stats.areaCount+=data.areas.size(); #if defined(HAVE_LIB_GPERFTOOLS) if (heapProfile){ std::ostringstream buff; buff << "load-" << level << "-" << x << "-" << y; HeapProfilerDump(buff.str().c_str()); } struct mallinfo alloc_info = tc_mallinfo(); #else #if defined(HAVE_MALLINFO) struct mallinfo alloc_info = mallinfo(); #endif #endif #if defined(HAVE_MALLINFO) || defined(HAVE_LIB_GPERFTOOLS) std::cout << "memory usage: " << formatAlloc(alloc_info.uordblks) << std::endl; stats.allocMax = std::max(stats.allocMax, (double)alloc_info.uordblks); stats.allocSum = stats.allocSum + (double)alloc_info.uordblks; #endif // set cache size back to default mapService->SetCacheSize(25); dbTimer.Stop(); double dbTime=dbTimer.GetMilliseconds(); stats.dbMinTime=std::min(stats.dbMinTime,dbTime); stats.dbMaxTime=std::max(stats.dbMaxTime,dbTime); stats.dbTotalTime+=dbTime; osmscout::StopClock drawTimer; #if defined(HAVE_LIB_OSMSCOUTMAPCAIRO) if (driver=="cairo") { //std::cout << data.nodes.size() << " " << data.ways.size() << " " << data.areas.size() << std::endl; cairoMapPainter.DrawMap(projection, drawParameter, data, cairo); } #endif #if defined(HAVE_LIB_OSMSCOUTMAPQT) if (driver=="Qt") { //std::cout << data.nodes.size() << " " << data.ways.size() << " " << data.areas.size() << std::endl; for (int i=0; i < 100; i++){ qtMapPainter.DrawMap(projection, drawParameter, data, qtPainter); } } #endif if (driver=="noop") { noOpMapPainter.DrawMap(projection, drawParameter, data); } if (driver=="none") { // Do nothing } drawTimer.Stop(); stats.tileCount++; double drawTime=drawTimer.GetMilliseconds(); stats.drawMinTime=std::min(stats.drawMinTime,drawTime); stats.drawMaxTime=std::max(stats.drawMaxTime,drawTime); stats.drawTotalTime+=drawTime; current++; } } statistics.push_back(stats); } #if defined(HAVE_LIB_GPERFTOOLS) if (heapProfile){ HeapProfilerStop(); } #endif std::cout << "==========" << std::endl; for (const auto& stats : statistics) { std::cout << "Level: " << stats.level << std::endl; #if defined(HAVE_MALLINFO) || defined(HAVE_LIB_GPERFTOOLS) std::cout << " Used memory: "; std::cout << "max: " << formatAlloc(stats.allocMax) << " "; std::cout << "avg: " << formatAlloc(stats.allocSum / stats.tileCount) << std::endl; #endif std::cout << " Tot. data : "; std::cout << "nodes: " << stats.nodeCount << " "; std::cout << "way: " << stats.wayCount << " "; std::cout << "areas: " << stats.areaCount << std::endl; std::cout << " Avg. data : "; std::cout << "nodes: " << stats.nodeCount/stats.tileCount << " "; std::cout << "way: " << stats.wayCount/stats.tileCount << " "; std::cout << "areas: " << stats.areaCount/stats.tileCount << std::endl; std::cout << " DB : "; std::cout << "total: " << stats.dbTotalTime << " "; std::cout << "min: " << stats.dbMinTime << " "; std::cout << "avg: " << stats.dbTotalTime/stats.tileCount << " "; std::cout << "max: " << stats.dbMaxTime << " " << std::endl; std::cout << " Map : "; std::cout << "total: " << stats.drawTotalTime << " "; std::cout << "min: " << stats.drawMinTime << " "; std::cout << "avg: " << stats.drawTotalTime/stats.tileCount << " "; std::cout << "max: " << stats.drawMaxTime << std::endl; } database->Close(); #if defined(HAVE_LIB_OSMSCOUTMAPCAIRO) if (driver=="cairo") { cairo_destroy(cairo); cairo_surface_destroy(cairoSurface); } #endif return 0; }
int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #ifdef USE_SVG_CAIRO struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; //already rendered at the right size and scale? return if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache; if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) { cairo_t *cr; cairo_surface_t *surface; unsigned char *pb; int width, height, surface_w, surface_h; /* need to recompute the pixmap */ msFreeRasterBuffer(&svg_cache->pixmap_buffer); //increase pixmap size to accomodate scaling/rotation if (style->scale != 1.0) { width = surface_w = (symbol->sizex * style->scale + 0.5); height = surface_h = (symbol->sizey * style->scale + 0.5); } else { width = surface_w = symbol->sizex; height = surface_h = symbol->sizey; } if (style->rotation != 0) { surface_w = MS_NINT(width * 1.415); surface_h = MS_NINT(height * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate(cr, surface_w / 2, surface_h / 2); cairo_rotate(cr, -style->rotation); cairo_translate(cr, -width / 2, -height / 2); } if (style->scale != 1.0) { cairo_scale(cr, style->scale, style->scale); } if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) { return MS_FAILURE; } pb = cairo_image_surface_get_data(surface); //set up raster initializeRasterBufferCairo(&svg_cache->pixmap_buffer, surface_w, surface_h, 0); memcpy(svg_cache->pixmap_buffer.data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char)); svg_cache->scale = style->scale; svg_cache->rotation = style->rotation; cairo_destroy(cr); cairo_surface_destroy(surface); } assert(svg_cache->pixmap_buffer.height && svg_cache->pixmap_buffer.width); pixstyle = *style; pixstyle.rotation = 0.0; pixstyle.scale = 1.0; pixsymbol.pixmap_buffer = &svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif }
static void draw (cairo_t *cr, int width, int height) { cairo_surface_t *overlay, *punch, *circles; cairo_t *overlay_cr, *punch_cr, *circles_cr; /* Fill the background */ double radius = 0.5 * (width < height ? width : height) - 10; double xc = width / 2.; double yc = height / 2.; overlay = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, width, height); if (overlay == NULL) return; punch = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_ALPHA, width, height); if (punch == NULL) return; circles = cairo_surface_create_similar (cairo_get_target (cr), CAIRO_CONTENT_COLOR_ALPHA, width, height); if (circles == NULL) return; fill_checks (cr, 0, 0, width, height); /* Draw a black circle on the overlay */ overlay_cr = cairo_create (overlay); cairo_set_source_rgb (overlay_cr, 0., 0., 0.); oval_path (overlay_cr, xc, yc, radius, radius); cairo_fill (overlay_cr); /* Draw 3 circles to the punch surface, then cut * that out of the main circle in the overlay */ punch_cr = cairo_create (punch); draw_3circles (punch_cr, xc, yc, radius, 1.0); cairo_destroy (punch_cr); cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT); cairo_set_source_surface (overlay_cr, punch, 0, 0); cairo_paint (overlay_cr); /* Now draw the 3 circles in a subgroup again * at half intensity, and use OperatorAdd to join up * without seams. */ circles_cr = cairo_create (circles); cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER); draw_3circles (circles_cr, xc, yc, radius, 0.5); cairo_destroy (circles_cr); cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD); cairo_set_source_surface (overlay_cr, circles, 0, 0); cairo_paint (overlay_cr); cairo_destroy (overlay_cr); cairo_set_source_surface (cr, overlay, 0, 0); cairo_paint (cr); cairo_surface_destroy (overlay); cairo_surface_destroy (punch); cairo_surface_destroy (circles); }
static PangoClutterGlyphCacheValue * pango_clutter_renderer_get_cached_glyph (PangoRenderer *renderer, PangoFont *font, PangoGlyph glyph) { PangoClutterRenderer *priv = PANGO_CLUTTER_RENDERER (renderer); PangoClutterGlyphCacheValue *value; PangoClutterGlyphCache *glyph_cache; glyph_cache = priv->use_mipmapping ? priv->mipmapped_glyph_cache : priv->glyph_cache; if ((value = pango_clutter_glyph_cache_lookup (glyph_cache, font, glyph)) == NULL) { cairo_surface_t *surface; cairo_t *cr; cairo_scaled_font_t *scaled_font; PangoRectangle ink_rect; cairo_glyph_t cairo_glyph; pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); surface = cairo_image_surface_create (CAIRO_FORMAT_A8, ink_rect.width, ink_rect.height); cr = cairo_create (surface); scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font)); cairo_set_scaled_font (cr, scaled_font); cairo_glyph.x = -ink_rect.x; cairo_glyph.y = -ink_rect.y; /* The PangoCairo glyph numbers directly map to Cairo glyph numbers */ cairo_glyph.index = glyph; cairo_show_glyphs (cr, &cairo_glyph, 1); cairo_destroy (cr); cairo_surface_flush (surface); /* Copy the glyph to the cache */ value = pango_clutter_glyph_cache_set (glyph_cache, font, glyph, cairo_image_surface_get_data (surface), cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), cairo_image_surface_get_stride (surface), ink_rect.x, ink_rect.y); cairo_surface_destroy (surface); CLUTTER_NOTE (PANGO, "cache fail %i", glyph); } else CLUTTER_NOTE (PANGO, "cache success %i", glyph); return value; }
void meta_draw_window_decoration (decor_t *d) { Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); cairo_surface_t *surface; Picture src; MetaButtonState button_states [META_BUTTON_TYPE_LAST]; MetaButtonLayout button_layout; MetaFrameGeometry fgeom; MetaFrameFlags flags; MetaFrameType frame_type; MetaTheme *theme; GtkStyleContext *context; cairo_t *cr; gint i; GdkRectangle clip; Region top_region = NULL; Region bottom_region = NULL; Region left_region = NULL; Region right_region = NULL; gdouble meta_active_opacity, meta_inactive_opacity; gboolean meta_active_shade_opacity, meta_inactive_shade_opacity; g_object_get (settings, "metacity-active-opacity", &meta_active_opacity, NULL); g_object_get (settings, "metacity-inactive-opacity", &meta_inactive_opacity, NULL); g_object_get (settings, "metacity-active-shade-opacity", &meta_active_shade_opacity, NULL); g_object_get (settings, "metacity-inactive-shade-opacity", &meta_inactive_shade_opacity, NULL); double alpha = (d->active) ? meta_active_opacity : meta_inactive_opacity; gboolean shade_alpha = (d->active) ? meta_active_shade_opacity : meta_inactive_shade_opacity; MetaFrameStyle *frame_style; GtkWidget *style_window; GdkRGBA bg_rgba; if (!d->surface || !d->picture) return; if (decoration_alpha == 1.0) alpha = 1.0; if (cairo_xlib_surface_get_depth (d->surface) == 32) { context = gtk_widget_get_style_context (d->frame->style_window_rgba); style_window = d->frame->style_window_rgba; } else { context = gtk_widget_get_style_context (d->frame->style_window_rgb); style_window = d->frame->style_window_rgb; } cr = cairo_create (d->buffer_surface ? d->buffer_surface : d->surface); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); theme = meta_theme_get_current (); frame_type = meta_frame_type_from_string (d->frame->type); if (frame_type == META_FRAME_TYPE_LAST) frame_type = META_FRAME_TYPE_NORMAL; meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, frame_type, &clip); if ((d->prop_xid || !d->buffer_surface) && !d->frame_window) draw_shadow_background (d, cr, d->shadow, d->context); for (i = 0; i < META_BUTTON_TYPE_LAST; ++i) button_states[i] = meta_button_state_for_button_type (d, i); frame_style = meta_theme_get_frame_style (theme, frame_type, flags); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_rgba); bg_rgba.alpha = 1.0; if (frame_style->window_background_color) { meta_color_spec_render (frame_style->window_background_color, gtk_widget_get_style_context (style_window), &bg_rgba); bg_rgba.alpha = frame_style->window_background_alpha / 255.0; } /* Draw something that will be almost invisible to user. This is hacky way * to fix invisible decorations. */ cairo_set_source_rgba (cr, 0, 0, 0, 0.01); cairo_rectangle (cr, 0, 0, 1, 1); cairo_fill (cr); /* ------------ */ cairo_destroy (cr); if (d->frame_window) surface = create_surface (clip.width, clip.height, d->frame->style_window_rgb); else surface = create_surface (clip.width, clip.height, d->frame->style_window_rgba); cr = cairo_create (surface); gdk_cairo_set_source_rgba (cr, &bg_rgba); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); src = XRenderCreatePicture (xdisplay, cairo_xlib_surface_get_drawable (surface), get_format_for_surface (d, surface), 0, NULL); cairo_paint (cr); meta_theme_draw_frame (theme, style_window, cr, frame_type, flags, clip.width - fgeom.left_width - fgeom.right_width, clip.height - fgeom.top_height - fgeom.bottom_height, d->layout, d->frame->text_height, &button_layout, button_states, d->icon_pixbuf, NULL); if (fgeom.top_height) { top_region = meta_get_top_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, 0, d->picture, &d->border_layout, BORDER_TOP, top_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.bottom_height) { bottom_region = meta_get_bottom_border_region (&fgeom, clip.width); decor_blend_border_picture (xdisplay, d->context, src, 0, clip.height - fgeom.bottom_height, d->picture, &d->border_layout, BORDER_BOTTOM, bottom_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.left_width) { left_region = meta_get_left_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, 0, fgeom.top_height, d->picture, &d->border_layout, BORDER_LEFT, left_region, alpha * 0xffff, shade_alpha, 0); } if (fgeom.right_width) { right_region = meta_get_right_border_region (&fgeom, clip.height); decor_blend_border_picture (xdisplay, d->context, src, clip.width - fgeom.right_width, fgeom.top_height, d->picture, &d->border_layout, BORDER_RIGHT, right_region, alpha * 0xffff, shade_alpha, 0); } cairo_destroy (cr); cairo_surface_destroy (surface); XRenderFreePicture (xdisplay, src); copy_to_front_buffer (d); if (d->frame_window) { GdkWindow *gdk_frame_window = gtk_widget_get_window (d->decor_window); GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface (d->surface, 0, 0, d->width, d->height); gtk_image_set_from_pixbuf (GTK_IMAGE (d->decor_image), pixbuf); g_object_unref (pixbuf); gtk_window_resize (GTK_WINDOW (d->decor_window), d->width, d->height); gdk_window_move (gdk_frame_window, d->context->left_corner_space - 1, d->context->top_corner_space - 1); gdk_window_lower (gdk_frame_window); } if (d->prop_xid) { /* translate from frame to client window space */ if (top_region) XOffsetRegion (top_region, -fgeom.left_width, -fgeom.top_height); if (bottom_region) XOffsetRegion (bottom_region, -fgeom.left_width, 0); if (left_region) XOffsetRegion (left_region, -fgeom.left_width, 0); decor_update_meta_window_property (d, theme, flags, top_region, bottom_region, left_region, right_region); d->prop_xid = 0; } if (top_region) XDestroyRegion (top_region); if (bottom_region) XDestroyRegion (bottom_region); if (left_region) XDestroyRegion (left_region); if (right_region) XDestroyRegion (right_region); }