/* Draw part of the widget by blitting surface buffer to window */ static void vga_paint(GtkWidget *widget, GdkRectangle *area) { VGAText * vga; /* Sanity checks */ g_return_if_fail(widget != NULL); g_return_if_fail(VGA_IS_TEXT(widget)); g_return_if_fail(area != NULL); vga = VGA_TEXT(widget); if (!GTK_WIDGET_DRAWABLE(widget)) { fprintf(stderr, "vga_paint(): widget not drawable!\n"); return; } printf("vga_paint(): area x,y = %d,%d, width=%d, height=%d\n", area->x, area->y, area->width, area->height); #if 0 vga_render_area(widget, vga, area); #else cairo_t *cr; cr = gdk_cairo_create(widget->window); /* Set clip region for speed */ cairo_rectangle(cr, area->x, area->y, area->width, area->height); cairo_clip(cr); cairo_set_source_surface(cr, vga->pvt->surface_buf, 0, 0); cairo_paint(cr); cairo_destroy(cr); #endif /* * FIXME: The algorithm seems to work great. I watch the debug output * as it runs trying various things and it always calculates the * right starting/stopping row/col. However, still sometimes things * are not drawn, but I'm lead to believe right now that the problem * lies elsewhere. * UPDATE: Correct. We now use vga_render_area() which is a * pixel-level based refresh rather than character level. It * works fine. Commenting out approach below. * */ #if 0 row_start = area->y / vga->pvt->font->height; /* verified */ num_rows = area->height / vga->pvt->font->height + 1; row_stop = MIN(row_start + num_rows, vga->pvt->rows); num_cols = area->width / vga->pvt->font->width + 1; col_start = area->x / vga->pvt->font->width; col_stop = MIN(col_start + num_cols, vga->pvt->cols); #ifdef VGA_DEBUG fprintf(stderr, "area->y = %d, area->height = %d\n", area->y, area->height); fprintf(stderr, "area->x = %d, area->width = %d\n", area->x, area->width); fprintf(stderr, "row_start = %d, row_stop = %d\n", row_start, row_stop); fprintf(stderr, "col_start = %d, col_stop = %d\n", col_start, col_stop); fprintf(stderr, "\tnum_cols = %d\n", num_cols); #endif for (y = row_start; y < row_stop; y++) for (x = col_start; x < col_stop; x++) { vga_paint_charcell(widget, vga, vga->pvt->video_buf[y*80+x], x*vga->pvt->font->width, y*vga->pvt->font->height); } #endif }
void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int x, int y, int width, int height) { const char *ctitle; int cwidth; int calign_right; col_info_t *cinf; int minheight; int res = ddb_listview_column_get_info (listview, column, &ctitle, &cwidth, &calign_right, &minheight, (void **)&cinf); if (res == -1) { return; } DB_playItem_t *playing_track = deadbeef->streamer_get_playing_track (); int theming = !gtkui_override_listview_colors (); if (cinf->id == DB_COLUMN_ALBUM_ART) { if (theming) { #if GTK_CHECK_VERSION(3,0,0) cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); gtk_paint_flat_box (gtk_widget_get_style (theme_treeview), cr, GTK_STATE_NORMAL, GTK_SHADOW_NONE, theme_treeview, "cell_even_ruled", x-1, y, width+2, height); cairo_reset_clip (cr); #else GdkRectangle clip = { .x = x, .y = y, .width = width, .height = height, }; gtk_paint_flat_box (gtk_widget_get_style (theme_treeview), gtk_widget_get_window (listview->list), GTK_STATE_NORMAL, GTK_SHADOW_NONE, &clip, theme_treeview, "cell_even_ruled", x-1, y, width+2, height); #endif } else { GdkColor clr; gtkui_get_listview_even_row_color (&clr); cairo_set_source_rgb (cr, clr.red/65535.f, clr.green/65535.f, clr.blue/65535.f); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); } int art_width = width - ART_PADDING_HORZ * 2; int art_y = y; // dest y int art_h = height; int sy; // source y if (group_y < ART_PADDING_VERT) { art_y = y - group_y + ART_PADDING_VERT; art_h = height - (art_y - y); sy = group_y; } else { sy = group_y - ART_PADDING_VERT; } if (art_width > 0) { if (group_it) { int h = cwidth - group_y; h = min (height, art_h); const char *album = deadbeef->pl_find_meta (group_it, "album"); const char *artist = deadbeef->pl_find_meta (group_it, "artist"); if (!album || !*album) { album = deadbeef->pl_find_meta (group_it, "title"); } GdkPixbuf *pixbuf = get_cover_art (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, art_width); if (pixbuf) { int pw = gdk_pixbuf_get_width (pixbuf); int ph = gdk_pixbuf_get_height (pixbuf); if (sy < ph) { pw = min (art_width, pw); ph -= sy; ph = min (ph, h); gdk_cairo_set_source_pixbuf (cr, pixbuf, (x + ART_PADDING_HORZ)-0, (art_y)-sy); cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph); cairo_fill (cr); } g_object_unref (pixbuf); } } } }
/* * vga_render_area: * @vga: VGAText structure pointer * @area: Area to refresh * * For the given rectangular area, render the contents of the VGA buffer * onto the surface buffer (NOT on-screen). */ static void vga_render_area(VGAText *vga, GdkRectangle * area) { int x, y, x2, y2; int char_x, char_y, x_drawn, y_drawn, row, col; x2 = area->x + area->width; /* Last column in area + 1 */ y2 = area->y + area->height; /* Last row in area + 1 */ x2 = MIN(x2, vga->pvt->font->width * vga->pvt->cols); y2 = MIN(y2, vga->pvt->font->height * vga->pvt->rows); y = area->y; vga_charcell * cell; char text[2]; cairo_t *cr; guchar attr; int cols_sameattr; int col_topaint; int num_cols; int last_col; vga_charcell *video_buf; //printf("vga_render_area(): x,y = (%d,%d), width=%d, height=%d\n", area->x, area->y, area->width, area->height); /* We must create/destroy the context in each expose event */ //cr = gdk_cairo_create(da->window); cr = cairo_create(vga->pvt->surface_buf); #if 1 /* Set clip region for speed */ cairo_rectangle(cr, area->x, area->y, area->width, area->height); cairo_clip(cr); #endif cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); //cairo_set_operator(cr, CAIRO_OPERATOR_OVER); #if 1 cairo_set_font_face(cr, vga->pvt->font->face); cairo_set_font_size(cr, 1.0); #endif if (vga->pvt->render_sec_buf) video_buf = vga->pvt->sec_buf; else video_buf = vga->pvt->video_buf; #define NEW_WAY #ifdef NEW_WAY while (y < y2) { //printf("while loop: y (%d) < y2 (%d)\n", y, y2); row = PIXEL_TO_ROW(y, vga->pvt->font); char_y = row * vga->pvt->font->height; y_drawn = (char_y + vga->pvt->font->height) - y; col = PIXEL_TO_COL(area->x, vga->pvt->font); num_cols = PIXEL_TO_COL(x2-1, vga->pvt->font) - col + 1; cols_sameattr = 0; x = col * vga->pvt->font->width; col_topaint = col; cell = &(video_buf[row * 80 + col]); attr = cell->attr; last_col = col + num_cols - 1; //printf("col_topaint = %d, last_col = %d, num_cols=%d\n", col_topaint, last_col, num_cols); while (col <= last_col) { cell = &(video_buf[row * 80 + col]); //printf("CHAR: '%c', cell attr = 0x%02x, old attr was 0x%02x\n", cell->c, cell->attr, attr); if (cell->attr == attr) { cols_sameattr++; } else { vga_set_textattr(vga, attr); //printf("vga_block_paint() - mid line, cols_sameattr=%d\n", cols_sameattr); vga_block_paint(vga, cr, col_topaint, row, cols_sameattr); attr = cell->attr; col_topaint += cols_sameattr; cols_sameattr = 1; } col++; } /* Paint last chunk of row */ vga_set_textattr(vga, cell->attr); //printf("vga_block_paint() - last chunk, col_to_paint=%d, cols=%d\n", col_topaint, last_col-col_topaint); vga_block_paint(vga, cr, col_topaint, row, last_col - col_topaint + 1); y += vga->pvt->font->height; } #else /* !NEW_WAY */ while (y < y2) { row = PIXEL_TO_ROW(y, vga->pvt->font); char_y = row * vga->pvt->font->height; y_drawn = (char_y + vga->pvt->font->height) - y; x = area->x; while (x < x2) { /* * x : pixel position to start drawing at (top left) * y : pixel position to start drawing at (top left) * row : row of character (usually 0-24) * col : column of character (usually 0-79) * char_x : pixel coordinate of beginning of whole character * char_y : pixel coordinate of beginning of whole character * x_drawn : number of columns to draw of character * y_drawn : number of rows to draw of character */ col = PIXEL_TO_COL(x, vga->pvt->font); char_x = col * vga->pvt->font->width; x_drawn = (char_x + vga->pvt->font->width) - x; cell = &(video_buf[row * 80 + col]); #ifdef USE_DEPRECATED_GDK vga_set_textattr(vga, cell->attr); gdk_gc_set_ts_origin(vga->pvt->gc, char_x, char_y-(16 * cell->c)); gdk_draw_rectangle(da->window, vga->pvt->gc, TRUE, x, y, x_drawn, y_drawn); #else /* NEW WAY, TESTING TO SEE HOW MUCH CAIRO FONTS ARE SLOWING ME DOWN */ /* SPeed seems similar... although things aren't getting wiped now */ #if 1 guchar *data; int row, col, i, j; vga_set_textattr(vga, cell->attr); /* Background */ //printf("Char at (%d, %d)\n", x, y); cairo_translate(cr, x, y); gdk_cairo_set_source_color(cr, vga_palette_get_color(vga->pvt->pal, vga->pvt->bg)); cairo_rectangle(cr, 0, 0, vga->pvt->font->width, vga->pvt->font->height); cairo_fill(cr); /* Foreground character */ data = vga_font_get_glyph_data(vga->pvt->font, cell->c); gdk_cairo_set_source_color(cr, vga_palette_get_color(vga->pvt->pal, vga->pvt->fg)); for (i = 0; i < vga->pvt->font->bytes_per_glyph; i++) { row = i; for (j = 0; j < 8; j++) { if (data[i] & (1 << j)) { col = 7 - j; cairo_rectangle(cr, col * 1.0, row, 1.0, 1.0); cairo_fill(cr); } } } #endif #endif x += x_drawn; } y += y_drawn; } #endif /* NEW_WAY */ cairo_destroy(cr); }
static int cr_clip (lua_State *L) { cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT); cairo_clip(*obj); return 0; }
bool wxGTKCairoDCImpl::DoStretchBlit(int xdest, int ydest, int dstWidth, int dstHeight, wxDC* source, int xsrc, int ysrc, int srcWidth, int srcHeight, wxRasterOperationMode rop, bool useMask, int xsrcMask, int ysrcMask) { wxCHECK_MSG(IsOk(), false, "invalid DC"); wxCHECK_MSG(source && source->IsOk(), false, "invalid source DC"); cairo_t* cr = NULL; if (m_graphicContext) cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext()); cairo_t* cr_src = NULL; wxGraphicsContext* gc_src = source->GetGraphicsContext(); if (gc_src) cr_src = static_cast<cairo_t*>(gc_src->GetNativeContext()); if (cr == NULL || cr_src == NULL) return false; const int xsrc_dev = source->LogicalToDeviceX(xsrc); const int ysrc_dev = source->LogicalToDeviceY(ysrc); cairo_surface_t* surfaceSrc = cairo_get_target(cr_src); cairo_surface_flush(surfaceSrc); cairo_surface_t* surfaceTmp = NULL; // If destination (this) and source wxDC refer to the same Cairo context // it means that we operate on one surface and results of drawing // can be invalid if destination and source regions overlap. // In such situation we have to copy source surface to the temporary // surface and use this copy in the drawing operations. if ( cr == cr_src ) { // Check if destination and source regions overlap. // If necessary, copy source surface to the temporary one. if (wxRect(xdest, ydest, dstWidth, dstHeight) .Intersects(wxRect(xsrc, ysrc, srcWidth, srcHeight))) { const int w = cairo_image_surface_get_width(surfaceSrc); const int h = cairo_image_surface_get_height(surfaceSrc); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) if ( cairo_version() >= CAIRO_VERSION_ENCODE(1, 12, 0) ) { surfaceTmp = cairo_surface_create_similar_image(surfaceSrc, cairo_image_surface_get_format(surfaceSrc), w, h); } else #endif // Cairo 1.12 { surfaceTmp = cairo_surface_create_similar(surfaceSrc, CAIRO_CONTENT_COLOR_ALPHA, w, h); } cairo_t* crTmp = cairo_create(surfaceTmp); cairo_set_source_surface(crTmp, surfaceSrc, 0, 0); cairo_rectangle(crTmp, 0.0, 0.0, w, h); cairo_set_operator(crTmp, CAIRO_OPERATOR_SOURCE); cairo_fill(crTmp); cairo_destroy(crTmp); cairo_surface_flush(surfaceTmp); surfaceSrc = surfaceTmp; } } cairo_save(cr); cairo_translate(cr, xdest, ydest); cairo_rectangle(cr, 0, 0, dstWidth, dstHeight); double sx, sy; source->GetUserScale(&sx, &sy); cairo_scale(cr, dstWidth / (sx * srcWidth), dstHeight / (sy * srcHeight)); cairo_set_source_surface(cr, surfaceSrc, -xsrc_dev, -ysrc_dev); const wxRasterOperationMode rop_save = m_logicalFunction; SetLogicalFunction(rop); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); cairo_surface_t* maskSurf = NULL; if (useMask) { const wxBitmap& bitmap = source->GetImpl()->GetSelectedBitmap(); if (bitmap.IsOk()) { wxMask* mask = bitmap.GetMask(); if (mask) maskSurf = *mask; } } if (maskSurf) { int xsrcMask_dev = xsrc_dev; int ysrcMask_dev = ysrc_dev; if (xsrcMask != -1) xsrcMask_dev = source->LogicalToDeviceX(xsrcMask); if (ysrcMask != -1) ysrcMask_dev = source->LogicalToDeviceY(ysrcMask); cairo_clip(cr); cairo_mask_surface(cr, maskSurf, -xsrcMask_dev, -ysrcMask_dev); } else { cairo_fill(cr); } cairo_restore(cr); if ( surfaceTmp ) { cairo_surface_destroy(surfaceTmp); } m_logicalFunction = rop_save; return true; }
bool wxGTKCairoDCImpl::DoStretchBlit(int xdest, int ydest, int dstWidth, int dstHeight, wxDC* source, int xsrc, int ysrc, int srcWidth, int srcHeight, wxRasterOperationMode rop, bool useMask, int xsrcMask, int ysrcMask) { wxCHECK_MSG(IsOk(), false, "invalid DC"); wxCHECK_MSG(source && source->IsOk(), false, "invalid source DC"); cairo_t* cr = NULL; if (m_graphicContext) cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext()); cairo_t* cr_src = NULL; wxGraphicsContext* gc_src = source->GetGraphicsContext(); if (gc_src) cr_src = static_cast<cairo_t*>(gc_src->GetNativeContext()); if (cr == NULL || cr_src == NULL) return false; const int xsrc_dev = source->LogicalToDeviceX(xsrc); const int ysrc_dev = source->LogicalToDeviceY(ysrc); cairo_surface_t* surface = cairo_get_target(cr_src); cairo_surface_flush(surface); cairo_save(cr); cairo_translate(cr, xdest, ydest); cairo_rectangle(cr, 0, 0, dstWidth, dstHeight); double sx, sy; source->GetUserScale(&sx, &sy); cairo_scale(cr, dstWidth / (sx * srcWidth), dstHeight / (sy * srcHeight)); cairo_set_source_surface(cr, surface, -xsrc_dev, -ysrc_dev); const wxRasterOperationMode rop_save = m_logicalFunction; SetLogicalFunction(rop); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); cairo_surface_t* maskSurf = NULL; if (useMask) { const wxBitmap& bitmap = source->GetImpl()->GetSelectedBitmap(); if (bitmap.IsOk()) { wxMask* mask = bitmap.GetMask(); if (mask) maskSurf = *mask; } } if (maskSurf) { int xsrcMask_dev = xsrc_dev; int ysrcMask_dev = ysrc_dev; if (xsrcMask != -1) xsrcMask_dev = source->LogicalToDeviceX(xsrcMask); if (ysrcMask != -1) ysrcMask_dev = source->LogicalToDeviceY(ysrcMask); cairo_clip(cr); cairo_mask_surface(cr, maskSurf, -xsrcMask_dev, -ysrcMask_dev); } else { cairo_fill(cr); } cairo_restore(cr); m_logicalFunction = rop_save; return true; }
void HippoCanvas::onPaint(WPARAM wParam, LPARAM lParam) { RECT region; if (GetUpdateRect(window_, ®ion, true)) { int regionWidth = region.right - region.left; int regionHeight = region.bottom - region.top; #if 0 g_debug("SIZING: %p paint region %d,%d %dx%d", window_, region.left, region.top, regionWidth, regionHeight); #endif // go ahead and request/resize if necessary, so we paint the right thing ensureRequestAndAllocation(); PAINTSTRUCT paint; HDC hdc = BeginPaint(window_, &paint); //g_debug("paint.fErase=%d", paint.fErase); cairo_surface_t *surface = cairo_win32_surface_create(hdc); cairo_surface_t *buffer = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR, regionWidth, regionHeight); cairo_t *cr = cairo_create(buffer); hippo_canvas_context_win_update_pango(context_, cr); // make the buffer's coordinates look like the real coordinates cairo_translate(cr, - region.left, - region.top); // Paint a background rectangle to the buffer cairo_rectangle(cr, region.left, region.top, regionWidth, regionHeight); cairo_clip(cr); // FIXME not the right background color (on linux it's the default gtk background) // should use system color, maybe GetThemeSysColorBrush is right. Note that // this rectangle draws the little corner between the scrollbars in // addition to the viewport background. hippo_cairo_set_source_rgba32(cr, 0xffffffff); cairo_paint(cr); // Draw canvas item to the buffer if (root_ != (HippoCanvasItem*) NULL) { RECT viewport; HippoRectangle viewport_hippo; HippoRectangle region_hippo; getViewport(&viewport); hippo_rectangle_from_rect(&viewport_hippo, &viewport); hippo_rectangle_from_rect(®ion_hippo, ®ion); if (hippo_rectangle_intersect(&viewport_hippo, ®ion_hippo, ®ion_hippo)) { // we have to clip so we don't draw outside the viewport - the canvas // doesn't have its own window cairo_save(cr); cairo_rectangle(cr, region_hippo.x, region_hippo.y, region_hippo.width, region_hippo.height); cairo_clip(cr); int x, y; getCanvasOrigin(&x, &y); hippo_canvas_item_process_paint(root_, cr, ®ion_hippo, x, y); cairo_restore(cr); } } // pop the update region clip and the translation off the buffer cairo_destroy(cr); // Copy the buffer to the window cairo_t *window_cr = cairo_create(surface); cairo_rectangle(window_cr, region.left, region.top, regionWidth, regionHeight); cairo_clip(window_cr); cairo_set_source_surface(window_cr, buffer, region.left, region.top); cairo_paint(window_cr); cairo_destroy(window_cr); cairo_surface_destroy(buffer); cairo_surface_destroy(surface); EndPaint(window_, &paint); } }
static gboolean gimp_tag_popup_list_expose (GtkWidget *widget, GdkEventExpose *event, GimpTagPopup *popup) { GdkWindow *window = gtk_widget_get_window (widget); GtkStyle *style = gtk_widget_get_style (widget); cairo_t *cr; PangoAttribute *attribute; PangoAttrList *attributes; gint i; cr = gdk_cairo_create (event->window); gdk_cairo_region (cr, event->region); cairo_clip (cr); cairo_set_line_width (cr, 1.0); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); for (i = 0; i < popup->tag_count; i++) { PopupTagData *tag_data = &popup->tag_data[i]; pango_layout_set_text (popup->layout, gimp_tag_get_name (tag_data->tag), -1); switch (tag_data->state) { case GTK_STATE_SELECTED: attributes = pango_attr_list_copy (popup->combo_entry->selected_item_attr); break; case GTK_STATE_INSENSITIVE: attributes = pango_attr_list_copy (popup->combo_entry->insensitive_item_attr); break; default: attributes = pango_attr_list_copy (popup->combo_entry->normal_item_attr); break; } if (tag_data == popup->prelight && tag_data->state != GTK_STATE_INSENSITIVE) { attribute = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); pango_attr_list_insert (attributes, attribute); } pango_layout_set_attributes (popup->layout, attributes); pango_attr_list_unref (attributes); if (tag_data->state == GTK_STATE_SELECTED) { gdk_cairo_set_source_color (cr, &popup->combo_entry->selected_item_color); cairo_rectangle (cr, tag_data->bounds.x - 1, tag_data->bounds.y - popup->scroll_y, tag_data->bounds.width + 2, tag_data->bounds.height); cairo_fill (cr); cairo_translate (cr, 0.5, 0.5); cairo_move_to (cr, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y - 1); cairo_line_to (cr, tag_data->bounds.x + tag_data->bounds.width - 1, tag_data->bounds.y - popup->scroll_y - 1); cairo_move_to (cr, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height); cairo_line_to (cr, tag_data->bounds.x + tag_data->bounds.width - 1, tag_data->bounds.y - popup->scroll_y + tag_data->bounds.height); cairo_stroke (cr); cairo_translate (cr, -0.5, -0.5); } cairo_move_to (cr, (tag_data->bounds.x + GIMP_TAG_POPUP_PADDING), (tag_data->bounds.y - popup->scroll_y + GIMP_TAG_POPUP_PADDING)); pango_cairo_show_layout (cr, popup->layout); if (tag_data == popup->prelight && tag_data->state != GTK_STATE_INSENSITIVE && ! popup->single_select_disabled) { gtk_paint_focus (style, window, tag_data->state, &event->area, widget, NULL, tag_data->bounds.x, tag_data->bounds.y - popup->scroll_y, tag_data->bounds.width, tag_data->bounds.height); } } cairo_destroy (cr); return FALSE; }
void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, DdbListviewIter group_it, int column, int group_y, int group_height, int group_pinned, int grp_next_y, int x, int y, int width, int height) { const char *ctitle; int cwidth; int calign_right; col_info_t *cinf; int minheight; int res = ddb_listview_column_get_info (listview, column, &ctitle, &cwidth, &calign_right, &minheight, (void **)&cinf); if (res == -1) { return; } DB_playItem_t *playing_track = deadbeef->streamer_get_playing_track (); int theming = !gtkui_override_listview_colors (); if (cinf->id == DB_COLUMN_ALBUM_ART) { if (theming) { #if GTK_CHECK_VERSION(3,0,0) cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); gtk_paint_flat_box (gtk_widget_get_style (theme_treeview), cr, GTK_STATE_NORMAL, GTK_SHADOW_NONE, theme_treeview, "cell_even_ruled", x-1, y, width+2, height); cairo_reset_clip (cr); #else GdkRectangle clip = { .x = x, .y = y, .width = width, .height = height, }; gtk_paint_flat_box (gtk_widget_get_style (theme_treeview), gtk_widget_get_window (listview->list), GTK_STATE_NORMAL, GTK_SHADOW_NONE, &clip, theme_treeview, "cell_even_ruled", x-1, y, width+2, height); #endif } else { GdkColor clr; gtkui_get_listview_even_row_color (&clr); cairo_set_source_rgb (cr, clr.red/65535.f, clr.green/65535.f, clr.blue/65535.f); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); } int real_art_width = width - ART_PADDING_HORZ * 2; if (real_art_width > 0 && group_it) { const char *album = deadbeef->pl_find_meta (group_it, "album"); const char *artist = deadbeef->pl_find_meta (group_it, "artist"); if (!album || !*album) { album = deadbeef->pl_find_meta (group_it, "title"); } if (listview->new_cover_size != real_art_width) { listview->new_cover_size = real_art_width; if (listview->cover_refresh_timeout_id) { g_source_remove (listview->cover_refresh_timeout_id); listview->cover_refresh_timeout_id = 0; } if (listview->cover_size == -1) { listview->cover_size = real_art_width; } else { if (!listview->cover_refresh_timeout_id) { listview->cover_refresh_timeout_id = g_timeout_add (1000, deferred_cover_load_cb, listview); } } } int art_width = listview->cover_size; int art_y = y; // dest y int art_h = height; int sy; // source y if (group_y < ART_PADDING_VERT) { art_y = y - group_y + ART_PADDING_VERT; art_h = height - (art_y - y); sy = group_y; } else { sy = group_y - ART_PADDING_VERT; } int h = cwidth - group_y; h = min (height, art_h); int hq = 0; GdkPixbuf *pixbuf = get_cover_art_callb (deadbeef->pl_find_meta (((DB_playItem_t *)group_it), ":URI"), artist, album, real_art_width == art_width ? art_width : -1, redraw_playlist_single, listview); if (!pixbuf) { pixbuf = cover_get_default_pixbuf (); } if (pixbuf) { art_width = gdk_pixbuf_get_width (pixbuf); float art_scale = (float)real_art_width / art_width; int pw = real_art_width; int ph; if (gdk_pixbuf_get_width (pixbuf) < gdk_pixbuf_get_height (pixbuf)) { art_scale *= (float)gdk_pixbuf_get_width (pixbuf) / gdk_pixbuf_get_height (pixbuf); } if (group_pinned == 1 && gtkui_groups_pinned) { ph = group_height; } else { ph = pw; } if (sy < ph) { cairo_save (cr); if (group_pinned == 1 && gtkui_groups_pinned) { int ph_real = gdk_pixbuf_get_height (pixbuf); if (grp_next_y <= ph_real * art_scale + listview->grouptitle_height) { cairo_rectangle (cr, x + ART_PADDING_HORZ, grp_next_y - ph_real * art_scale, pw, ph); cairo_translate (cr, (x + ART_PADDING_HORZ)-0, grp_next_y - ph_real * art_scale); } else { cairo_rectangle (cr, x + ART_PADDING_HORZ, listview->grouptitle_height, pw, ph); cairo_translate (cr, (x + ART_PADDING_HORZ)-0, listview->grouptitle_height); } } else { ph -= sy; ph = min (ph, h); cairo_rectangle (cr, x + ART_PADDING_HORZ, art_y, pw, ph); cairo_translate (cr, (x + ART_PADDING_HORZ)-0, art_y - sy); } cairo_scale (cr, art_scale, art_scale); gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); cairo_pattern_set_filter (cairo_get_source(cr), gtkui_is_default_pixbuf (pixbuf) ? CAIRO_FILTER_GAUSSIAN : CAIRO_FILTER_FAST); cairo_fill (cr); cairo_restore (cr); } g_object_unref (pixbuf); } } }
/* Standard Border Function */ void hc_draw_shadow(GtkStyle * style, cairo_t * cr, GtkStateType state_type, GtkShadowType shadow_type, GtkWidget * widget, const gchar * detail, gint x, gint y, gint width, gint height) { /* Border Uses Foreground Color */ CairoColor foreground = HC_STYLE(style)->color_cube.fg[state_type]; gint line_width; gint clip_x = x, clip_y = y, clip_width = width, clip_height = height; /***********************************************/ /* GTK Sanity Checks */ /***********************************************/ CHECK_ARGS /***********************************************/ /* GTK Special Cases - adjust Size/Offset */ /***********************************************/ line_width = HC_STYLE(style)->edge_thickness; if (CHECK_DETAIL (detail, "menubar") && ge_is_panel_widget_item(widget)) { return; } /* Spin Button */ if ((CHECK_DETAIL(detail, "spinbutton_up")) || (CHECK_DETAIL(detail, "spinbutton_down"))) { /* Overdraw Height By Half The Line Width - Prevents Double line Between buttons */ height += floor(line_width / 2); /* If Down Button Offset By Half Line Width */ if (CHECK_DETAIL(detail, "spinbutton_down")) { y -= floor(line_width / 2); } /* Overdraw Width By Line Width - Prevents Double line Between Entry And Buttons */ width += line_width; /* If LTR Offset X By Line Width */ if (ge_widget_is_ltr (widget)) { x -= line_width; } /* Force Border To Use Foreground Widget State */ if (widget) { foreground = HC_STYLE(style)->color_cube.fg[gtk_widget_get_state(widget)]; } } /* Entry - Force Border To Use Foreground Matching Widget State */ if (CHECK_DETAIL(detail, "entry") && !ge_is_combo(widget)) { foreground = HC_STYLE(style)->color_cube.fg[widget ? gtk_widget_get_state(widget) : GTK_STATE_NORMAL]; } /* Combo Box Button's */ if (CHECK_DETAIL(detail, "button") && ge_is_in_combo_box(widget)) { /* Overdraw Width By Line Width - Prevents Double Line Between Entry and Button. */ width += line_width; /* If LTR Offset X By Line Width */ if (ge_widget_is_ltr (widget)) { x -= line_width; } /* Force Border To Use Foreground Matching Parent State */ if ((widget) && (gtk_widget_get_parent(widget))) { gtk_widget_ensure_style(gtk_widget_get_parent(widget)); ge_gdk_color_to_cairo(>k_widget_get_style(gtk_widget_get_parent(widget))->fg[gtk_widget_get_state (widget)], &foreground); } } /***********************************************/ /* Draw Border */ /***********************************************/ /* Clip Border Too Passed Size */ cairo_rectangle(cr, clip_x, clip_y, clip_width, clip_height); cairo_clip(cr); /* Set Line Style */ ge_cairo_set_color(cr, &foreground); cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); cairo_set_line_width (cr, line_width); ge_cairo_inner_rectangle (cr, x, y, width, height); cairo_stroke(cr); }
/* Border Function For Notebooks Tabs */ void hc_draw_extension (GtkStyle *style, cairo_t *cr, GtkStateType state_type, GtkShadowType shadow_type, GtkWidget *widget, const gchar *detail, gint x, gint y, gint width, gint height, GtkPositionType gap_side) { /* Fill Uses Background Color */ CairoColor *background = &HC_STYLE(style)->color_cube.bg[state_type]; /* Border Uses Foreground Color */ CairoColor *foreground = &HC_STYLE(style)->color_cube.fg[state_type]; gint line_width; gint widget_x = 0, widget_y = 0, widget_width = 0, widget_height = 0; gint clip_x = x, clip_y = y, clip_width = width, clip_height = height; /***********************************************/ /* GTK Sanity Checks */ /***********************************************/ CHECK_ARGS /***********************************************/ /* GTK Special Cases - adjust Size/Offset */ /***********************************************/ line_width = HC_STYLE(style)->edge_thickness; /* What all this is for - GTK doesn't overlap Extensions and Notebooks, but rather a tab is drawn with a "gap" side. Instead of long draw cases per gap side, perform a standard draw, but clipped to size, and overdraw edge thickness + one on gap side. To fake the apearance of overlap on edge aligned tabs increase clip by edge thickness on gap side. */ if (widget && (GE_IS_NOTEBOOK (widget))) { GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); widget_x = (allocation.x + gtk_container_get_border_width (GTK_CONTAINER (widget))); widget_y = (allocation.y + gtk_container_get_border_width (GTK_CONTAINER (widget))); widget_width = (allocation.width - 2*gtk_container_get_border_width (GTK_CONTAINER (widget))); widget_height = (allocation.height - 2*gtk_container_get_border_width (GTK_CONTAINER (widget))); } switch (gap_side) { case GTK_POS_TOP: if (GTK_CHECK_VERSION(2,10,0) || ((widget && GE_IS_NOTEBOOK (widget)) && ((x==widget_x) || ((x + width) == (widget_x + widget_width))))) { clip_height += line_width; if (!GTK_CHECK_VERSION(2,10,0)) { height -= floor(line_width/2.0); } } y -= (line_width + 1); height += (line_width + 1); break; case GTK_POS_LEFT: if (GTK_CHECK_VERSION(2,10,0) || ((widget && GE_IS_NOTEBOOK (widget)) && ((y==widget_y) || ((y + height) == (widget_y + widget_height))))) { clip_width += line_width; if (!GTK_CHECK_VERSION(2,10,0)) { x -= floor(line_width/2.0); } } x -= (line_width + 1); width += (line_width + 1); break; default: case GTK_POS_BOTTOM: height += (line_width + 1); break; case GTK_POS_RIGHT: width += (line_width + 1); break; } /***********************************************/ /* Draw Border */ /***********************************************/ /* Clip Too Size */ cairo_rectangle(cr, clip_x, clip_y, clip_width, clip_height); cairo_clip(cr); /* Set Fill Style */ ge_cairo_set_color(cr, background); /* Fill Rectangle */ cairo_rectangle (cr, x, y, width, height); cairo_fill(cr); /* Set Line Style */ ge_cairo_set_color(cr, foreground); cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); cairo_set_line_width (cr, line_width); ge_cairo_inner_rectangle (cr, x, y, width, height); cairo_stroke(cr); }
static gboolean um_crop_area_expose (GtkWidget *widget, GdkEventExpose *event) { cairo_t *cr; GdkRectangle area; GdkRectangle crop; gint width, height; UmCropArea *uarea = UM_CROP_AREA (widget); if (uarea->priv->browse_pixbuf == NULL) return FALSE; update_pixbufs (uarea); width = gdk_pixbuf_get_width (uarea->priv->pixbuf); height = gdk_pixbuf_get_height (uarea->priv->pixbuf); crop_to_widget (uarea, &crop); area.x = 0; area.y = 0; area.width = width; area.height = crop.y; gdk_rectangle_intersect (&area, &event->area, &area); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], uarea->priv->color_shifted, area.x, area.y, area.x, area.y, area.width, area.height, GDK_RGB_DITHER_NONE, 0, 0); area.x = 0; area.y = crop.y; area.width = crop.x; area.height = crop.height; gdk_rectangle_intersect (&area, &event->area, &area); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], uarea->priv->color_shifted, area.x, area.y, area.x, area.y, area.width, area.height, GDK_RGB_DITHER_NONE, 0, 0); area.x = crop.x; area.y = crop.y; area.width = crop.width; area.height = crop.height; gdk_rectangle_intersect (&area, &event->area, &area); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], uarea->priv->pixbuf, area.x, area.y, area.x, area.y, area.width, area.height, GDK_RGB_DITHER_NONE, 0, 0); area.x = crop.x + crop.width; area.y = crop.y; area.width = width - area.x; area.height = crop.height; gdk_rectangle_intersect (&area, &event->area, &area); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], uarea->priv->color_shifted, area.x, area.y, area.x, area.y, area.width, area.height, GDK_RGB_DITHER_NONE, 0, 0); area.x = 0; area.y = crop.y + crop.height; area.width = width; area.height = height - area.y; gdk_rectangle_intersect (&area, &event->area, &area); gdk_draw_pixbuf (widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], uarea->priv->color_shifted, area.x, area.y, area.x, area.y, area.width, area.height, GDK_RGB_DITHER_NONE, 0, 0); cr = gdk_cairo_create (widget->window); gdk_cairo_rectangle (cr, &event->area); cairo_clip (cr); if (uarea->priv->active_region != OUTSIDE) { gint x1, x2, y1, y2; gdk_cairo_set_source_color (cr, &widget->style->white); cairo_set_line_width (cr, 1.0); x1 = crop.x + crop.width / 3.0; x2 = crop.x + 2 * crop.width / 3.0; y1 = crop.y + crop.height / 3.0; y2 = crop.y + 2 * crop.height / 3.0; cairo_move_to (cr, x1 + 0.5, crop.y); cairo_line_to (cr, x1 + 0.5, crop.y + crop.height); cairo_move_to (cr, x2 + 0.5, crop.y); cairo_line_to (cr, x2 + 0.5, crop.y + crop.height); cairo_move_to (cr, crop.x, y1 + 0.5); cairo_line_to (cr, crop.x + crop.width, y1 + 0.5); cairo_move_to (cr, crop.x, y2 + 0.5); cairo_line_to (cr, crop.x + crop.width, y2 + 0.5); cairo_stroke (cr); } gdk_cairo_set_source_color (cr, &widget->style->black); cairo_set_line_width (cr, 1.0); cairo_rectangle (cr, crop.x + 0.5, crop.y + 0.5, crop.width - 1.0, crop.height - 1.0); cairo_stroke (cr); gdk_cairo_set_source_color (cr, &widget->style->white); cairo_set_line_width (cr, 2.0); cairo_rectangle (cr, crop.x + 2.0, crop.y + 2.0, crop.width - 4.0, crop.height - 4.0); cairo_stroke (cr); cairo_destroy (cr); return FALSE; }
void cairo_context::clip() { cairo_clip(cairo_.get()); check_object_status_and_throw_exception(*this); }
static void gimp_ruler_draw_pos (GimpRuler *ruler, cairo_t *cr) { GtkWidget *widget = GTK_WIDGET (ruler); GtkStyle *style = gtk_widget_get_style (widget); GimpRulerPrivate *priv = GIMP_RULER_GET_PRIVATE (ruler); GtkStateType state = gtk_widget_get_state (widget); GtkAllocation allocation; gint x, y; gint width, height; gint bs_width, bs_height; gint xthickness; gint ythickness; if (! gtk_widget_is_drawable (widget)) return; gtk_widget_get_allocation (widget, &allocation); xthickness = style->xthickness; ythickness = style->ythickness; if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { width = allocation.width; height = allocation.height - ythickness * 2; bs_width = height / 2 + 2; bs_width |= 1; /* make sure it's odd */ bs_height = bs_width / 2 + 1; } else { width = allocation.width - xthickness * 2; height = allocation.height; bs_height = width / 2 + 2; bs_height |= 1; /* make sure it's odd */ bs_width = bs_height / 2 + 1; } if ((bs_width > 0) && (bs_height > 0)) { gdouble lower; gdouble upper; gdouble position; gdouble increment; if (! cr) { cr = gdk_cairo_create (gtk_widget_get_window (widget)); cairo_rectangle (cr, allocation.x, allocation.y, allocation.width, allocation.height); cairo_clip (cr); cairo_translate (cr, allocation.x, allocation.y); /* If a backing store exists, restore the ruler */ if (priv->backing_store) { cairo_set_source_surface (cr, priv->backing_store, 0, 0); cairo_rectangle (cr, priv->xsrc, priv->ysrc, bs_width, bs_height); cairo_fill (cr); } } else { cairo_reference (cr); } position = gimp_ruler_get_position (ruler); gimp_ruler_get_range (ruler, &lower, &upper, NULL); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { increment = (gdouble) width / (upper - lower); x = ROUND ((position - lower) * increment) + (xthickness - bs_width) / 2 - 1; y = (height + bs_height) / 2 + ythickness; } else { increment = (gdouble) height / (upper - lower); x = (width + bs_width) / 2 + xthickness; y = ROUND ((position - lower) * increment) + (ythickness - bs_height) / 2 - 1; } gdk_cairo_set_source_color (cr, &style->fg[state]); cairo_move_to (cr, x, y); if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_line_to (cr, x + bs_width / 2.0, y + bs_height); cairo_line_to (cr, x + bs_width, y); } else { cairo_line_to (cr, x + bs_width, y + bs_height / 2.0); cairo_line_to (cr, x, y + bs_height); } cairo_fill (cr); cairo_destroy (cr); priv->xsrc = x; priv->ysrc = y; } }
static gboolean gimp_color_bar_expose (GtkWidget *widget, GdkEventExpose *event) { GimpColorBar *bar = GIMP_COLOR_BAR (widget); cairo_t *cr; GtkAllocation allocation; cairo_surface_t *surface; cairo_pattern_t *pattern; guchar *src; guchar *dest; gint x, y; gint width, height; gint i; cr = gdk_cairo_create (event->window); gdk_cairo_region (cr, event->region); cairo_clip (cr); gtk_widget_get_allocation (widget, &allocation); x = y = gtk_container_get_border_width (GTK_CONTAINER (bar)); width = allocation.width - 2 * x; height = allocation.height - 2 * y; if (width < 1 || height < 1) return TRUE; cairo_translate (cr, allocation.x + x, allocation.y + y); cairo_rectangle (cr, 0, 0, width, height); cairo_clip (cr); surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1); for (i = 0, src = bar->buf, dest = cairo_image_surface_get_data (surface); i < 256; i++, src += 3, dest += 4) { GIMP_CAIRO_RGB24_SET_PIXEL(dest, src[0], src[1], src[2]); } cairo_surface_mark_dirty (surface); pattern = cairo_pattern_create_for_surface (surface); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT); cairo_surface_destroy (surface); if (bar->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_scale (cr, (gdouble) width / 256.0, 1.0); } else { cairo_translate (cr, 0, height); cairo_scale (cr, 1.0, (gdouble) height / 256.0); cairo_rotate (cr, - G_PI / 2); } cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_paint (cr); cairo_destroy (cr); return TRUE; }
static void ag_chart_renderer_render(GtkCellRenderer *renderer, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { AgChartRendererPrivate *priv = ag_chart_renderer_get_instance_private( AG_CHART_RENDERER(renderer) ); int margin; GtkStyleContext *context = gtk_widget_get_style_context(widget); GdkPixbuf *pixbuf; gtk_style_context_save(context); gtk_style_context_add_class(context, "ag-chart-renderer"); if (priv->css_class) { gtk_style_context_add_class(context, priv->css_class); } cairo_save(cr); gdk_cairo_rectangle(cr, cell_area); cairo_clip(cr); cairo_translate(cr, cell_area->x, cell_area->y); margin = MAX( AG_CHART_RENDERER_TILE_MARGIN, (int)((cell_area->width - AG_CHART_RENDERER_TILE_SIZE) / 2) ); g_object_get(renderer, "pixbuf", &pixbuf, NULL); if (pixbuf != NULL) { GdkRectangle area = { margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE }; GTK_CELL_RENDERER_CLASS(ag_chart_renderer_parent_class)->render( renderer, cr, widget, &area, &area, flags ); } else { gtk_render_frame( context, cr, margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE ); gtk_render_background( context, cr, margin, margin, AG_CHART_RENDERER_TILE_SIZE, AG_CHART_RENDERER_TILE_SIZE ); } gtk_style_context_restore(context); if (priv->toggle_visible) { gint xpad, ypad, x_offset, check_x, check_y; gtk_cell_renderer_get_padding( GTK_CELL_RENDERER(renderer), &xpad, &ypad ); if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) { x_offset = xpad; } else { x_offset = cell_area->width - AG_CHART_RENDERER_CHECK_ICON_SIZE - xpad; } check_x = x_offset; check_y = cell_area->height - AG_CHART_RENDERER_CHECK_ICON_SIZE - ypad; gtk_style_context_save(context); gtk_style_context_add_class(context, GTK_STYLE_CLASS_CHECK); if (priv->checked) { gtk_style_context_set_state(context, GTK_STATE_FLAG_CHECKED); } gtk_render_background( context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE ); gtk_render_frame( context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE ); gtk_render_check( context, cr, check_x, check_y, AG_CHART_RENDERER_CHECK_ICON_SIZE, AG_CHART_RENDERER_CHECK_ICON_SIZE ); gtk_style_context_restore(context); } cairo_restore(cr); }
/** * 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; GtkBorder tile_border; gint padding, tile_size; gint idx, cur_x, cur_y; GList *l; 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); /* Render the thumbnail itself */ gtk_render_background (context, cr, 0, 0, base_size, base_size); gtk_render_frame (context, cr, 0, 0, base_size, base_size); /* Now, render the tiles inside */ gtk_style_context_remove_class (context, "documents-collection-icon"); gtk_style_context_add_class (context, "documents-collection-icon-tile"); /* TODO: do not hardcode 4, but scale to another layout if more * pixbufs are provided. */ padding = MAX (floor (base_size / 10), 4); gtk_style_context_get_border (context, GTK_STATE_FLAG_NORMAL, &tile_border); tile_size = (base_size - (3 * padding)) / 2 - MAX (tile_border.left + tile_border.right, tile_border.top + tile_border.bottom); l = pixbufs; idx = 0; cur_x = padding; cur_y = padding; while (l != NULL && idx < 4) { GdkPixbuf *pix; gboolean is_thumbnail; gint pix_width, pix_height, scale_size; pix = l->data; is_thumbnail = (gdk_pixbuf_get_option (pix, "-documents-has-thumb") != NULL); /* Only draw a box for thumbnails */ if (is_thumbnail) { gtk_render_background (context, cr, cur_x, cur_y, tile_size + tile_border.left + tile_border.right, tile_size + tile_border.top + tile_border.bottom); gtk_render_frame (context, cr, cur_x, cur_y, tile_size + tile_border.left + tile_border.right, tile_size + tile_border.top + tile_border.bottom); } 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 + tile_border.left, cur_y + tile_border.top); 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 + tile_border.left + tile_border.right; } else { cur_x = padding; cur_y += tile_size + padding + tile_border.top + tile_border.bottom; } 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 draw (cairo_t *cr, int width, int height) { const cairo_test_context_t *ctx = cairo_test_get_context (cr); cairo_surface_t *surface; cairo_t *cr2; cairo_rectangle_list_t *rectangle_list; const char *phase; cairo_bool_t uses_clip_rects; surface = cairo_surface_create_similar (cairo_get_group_target (cr), CAIRO_CONTENT_COLOR, 100, 100); /* don't use cr accidentally */ cr = NULL; cr2 = cairo_create (surface); cairo_surface_destroy (surface); /* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures * on surface types that don't use rectangle lists for clipping. * Default to FALSE for the internal surface types, (meta, test-fallback, etc.) */ switch (cairo_surface_get_type (surface)) { case CAIRO_SURFACE_TYPE_IMAGE: case CAIRO_SURFACE_TYPE_XLIB: case CAIRO_SURFACE_TYPE_XCB: case CAIRO_SURFACE_TYPE_GLITZ: case CAIRO_SURFACE_TYPE_WIN32: case CAIRO_SURFACE_TYPE_BEOS: case CAIRO_SURFACE_TYPE_DIRECTFB: uses_clip_rects = TRUE; break; case CAIRO_SURFACE_TYPE_QUARTZ: case CAIRO_SURFACE_TYPE_PDF: case CAIRO_SURFACE_TYPE_PS: case CAIRO_SURFACE_TYPE_SVG: case CAIRO_SURFACE_TYPE_OS2: default: uses_clip_rects = FALSE; break; } /* first, test basic stuff. This should not be clipped, it should return the surface rectangle. */ phase = "No clip set"; rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); /* Test simple clip rect. */ phase = "Simple clip rect"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 80, 80); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* Test everything clipped out. */ phase = "All clipped out"; cairo_save (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 0)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test two clip rects */ phase = "Two clip rects"; cairo_save (cr2); cairo_rectangle (cr2, 10, 10, 10, 10); cairo_rectangle (cr2, 20, 20, 10, 10); cairo_clip (cr2); cairo_rectangle (cr2, 15, 15, 10, 10); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 2) || !check_clip_extents (ctx, phase, cr2, 15, 15, 10, 10) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 15, 15, 5, 5) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 20, 20, 5, 5)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); /* test non-rectangular clip */ phase = "Nonrectangular clip"; cairo_save (cr2); cairo_move_to (cr2, 0, 0); cairo_line_to (cr2, 100, 100); cairo_line_to (cr2, 100, 0); cairo_close_path (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); /* can't get this in one tight user-space rectangle */ if (!check_unrepresentable (ctx, phase, rectangle_list) || !check_clip_extents (ctx, phase, cr2, 0, 0, 100, 100)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with same transform"; cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 5, 5, 40, 40) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 5, 5, 40, 40)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, simple scale, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_scale (cr2, 2, 2); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_count (ctx, phase, uses_clip_rects, rectangle_list, 1) || !check_clip_extents (ctx, phase, cr2, 10, 10, 80, 80) || !check_rectangles_contain (ctx, phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); phase = "User space, rotation, getting clip with no transform"; cairo_save (cr2); cairo_save (cr2); cairo_rotate (cr2, 12); cairo_rectangle (cr2, 5, 5, 40, 40); cairo_restore (cr2); cairo_clip (cr2); rectangle_list = cairo_copy_clip_rectangle_list (cr2); if (!check_unrepresentable (ctx, phase, rectangle_list)) { cairo_rectangle_list_destroy (rectangle_list); return CAIRO_TEST_FAILURE; } cairo_rectangle_list_destroy (rectangle_list); cairo_restore (cr2); cairo_destroy (cr2); return CAIRO_TEST_SUCCESS; }
/* * render functions */ static void begin_render(DiaRenderer *self, const Rectangle *update) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); real onedu = 0.0; real lmargin = 0.0, tmargin = 0.0; gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */ cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page; if (renderer->surface && !renderer->cr) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); /* remember current state, so we can start from new with every page */ cairo_save (renderer->cr); if (paginated && renderer->dia) { DiagramData *data = renderer->dia; /* Dia's paper.width already contains the scale, cairo needs it without * Similar for margins, Dia's without, but cairo wants them? */ real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin) * (72.0 / 2.54) + 0.5; real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin) * (72.0 / 2.54) + 0.5; /* "Changes the size of a PDF surface for the current (and * subsequent) pages." Pagination setup? */ cairo_pdf_surface_set_size (renderer->surface, width, height); lmargin = data->paper.lmargin / data->paper.scaling; tmargin = data->paper.tmargin / data->paper.scaling; } cairo_scale (renderer->cr, renderer->scale, renderer->scale); /* to ensure no clipping at top/left we need some extra gymnastics, * otherwise a box with a line witdh one one pixel might loose the * top/left border as in bug #147386 */ ensure_minimum_one_device_unit (renderer, &onedu); if (update && paginated) { cairo_rectangle (renderer->cr, lmargin, tmargin, update->right - update->left, update->bottom - update->top); cairo_clip (renderer->cr); cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin); } else cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu); /* no more blurred UML diagrams */ cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
static void hippo_canvas_text_paint_below_children(HippoCanvasBox *box, cairo_t *cr, GdkRegion *damaged_region) { HippoCanvasText *text = HIPPO_CANVAS_TEXT(box); guint32 color_rgba; if (box->color_set) { color_rgba = box->color_rgba; } else { HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(text)); color_rgba = hippo_canvas_style_get_foreground_color(style); } /* It would seem more natural to compute whether we are ellipsized or * not when we are allocated to some width, but we don't have a layout * at that point. We could do it in get_content_height_request(), but * the parent could theoretically give us more width than it asked us * about (and there are also some quirks in HippoCanvasBox where it * will call get_content_height_request() with a width if 0 at odd times), * so doing it here is more reliable. We use is_ellipsized only for * computing whether to show a tooltip, and we make the assumption that * if the user hasn't seen the text item drawn, they won't need a * tooltip for it. */ text->is_ellipsized = FALSE; if ((color_rgba & 0xff) != 0 && text->text != NULL) { PangoLayout *layout; int layout_width, layout_height; int x, y, w, h; int allocation_width, allocation_height; int space_left = box->border_left + box->padding_left; int space_right = box->border_right + box->padding_right; hippo_canvas_item_get_allocation(HIPPO_CANVAS_ITEM(box), &allocation_width, &allocation_height); layout = create_layout(text, allocation_width - space_left - space_right); pango_layout_get_size(layout, &layout_width, &layout_height); layout_width /= PANGO_SCALE; layout_height /= PANGO_SCALE; text->is_ellipsized = layout_is_ellipsized(layout); hippo_canvas_box_align(box, layout_width, layout_height, &x, &y, &w, &h); /* we can't really "fill" so we fall back to center if we seem to be * in fill mode */ if (w > layout_width) { x += (w - layout_width) / 2; } if (h > layout_height) { y += (h - layout_height) / 2; } /* Clipping is needed since the layout size could exceed our * allocation if we got a too-small allocation. * FIXME It would be better to ellipsize or something instead, though. */ cairo_save(cr); cairo_rectangle(cr, 0, 0, allocation_width, allocation_height); cairo_clip(cr); cairo_move_to (cr, x, y); hippo_cairo_set_source_rgba32(cr, color_rgba); pango_cairo_show_layout(cr, layout); cairo_restore(cr); g_object_unref(layout); } }
static void gnc_header_draw_offscreen (GncHeader *header) { SheetBlockStyle *style = header->style; Table *table = header->sheet->table; VirtualLocation virt_loc; VirtualCell *vcell; guint32 color_type; GtkStyleContext *stylectxt = gtk_widget_get_style_context (GTK_WIDGET(header)); GdkRGBA color; int row_offset; CellBlock *cb; int i; cairo_t *cr; virt_loc.vcell_loc.virt_row = 0; virt_loc.vcell_loc.virt_col = 0; virt_loc.phys_row_offset = 0; virt_loc.phys_col_offset = 0; gtk_style_context_save (stylectxt); // Get the background color type and apply the css class color_type = gnc_table_get_bg_color (table, virt_loc, NULL); gnucash_get_style_classes (header->sheet, stylectxt, color_type); if (header->surface) cairo_surface_destroy (header->surface); header->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, header->width, header->height); cr = cairo_create (header->surface); // Fill background color of header gtk_render_background (stylectxt, cr, 0, 0, header->width, header->height); gdk_rgba_parse (&color, "black"); cairo_set_source_rgb (cr, color.red, color.green, color.blue); cairo_rectangle (cr, 0.5, 0.5, header->width - 1.0, header->height - 1.0); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); // Draw bottom horizontal line, makes bottom line thicker cairo_move_to (cr, 0.5, header->height - 1.5); cairo_line_to (cr, header->width - 1.0, header->height - 1.5); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); /*font = gnucash_register_font;*/ vcell = gnc_table_get_virtual_cell (table, table->current_cursor_loc.vcell_loc); cb = vcell ? vcell->cellblock : NULL; row_offset = 0; for (i = 0; i < style->nrows; i++) { int col_offset = 0; int h = 0, j; virt_loc.phys_row_offset = i; /* TODO: This routine is duplicated in several places. Can we abstract at least the cell drawing routine? That way we'll be sure everything is drawn consistently, and cut down on maintenance issues. */ for (j = 0; j < style->ncols; j++) { CellDimensions *cd; double text_x, text_y, text_w, text_h; BasicCell *cell; const char *text; int w; PangoLayout *layout; virt_loc.phys_col_offset = j; cd = gnucash_style_get_cell_dimensions (style, i, j); h = cd->pixel_height; if (header->in_resize && (j == header->resize_col)) w = header->resize_col_width; else w = cd->pixel_width; cell = gnc_cellblock_get_cell (cb, i, j); if (!cell || !cell->cell_name) { col_offset += w; continue; } cairo_rectangle (cr, col_offset - 0.5, row_offset + 0.5, w, h); cairo_set_line_width (cr, 1.0); cairo_stroke (cr); virt_loc.vcell_loc = table->current_cursor_loc.vcell_loc; text = gnc_table_get_label (table, virt_loc); if (!text) text = ""; layout = gtk_widget_create_pango_layout (GTK_WIDGET (header->sheet), text); switch (gnc_table_get_align (table, virt_loc)) { default: case CELL_ALIGN_LEFT: pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); break; case CELL_ALIGN_RIGHT: pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); break; case CELL_ALIGN_CENTER: pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); break; } text_x = col_offset + CELL_HPADDING; text_y = row_offset + 1; text_w = MAX (0, w - (2 * CELL_HPADDING)); text_h = h - 2; cairo_save (cr); cairo_rectangle (cr, text_x, text_y, text_w, text_h); cairo_clip (cr); gtk_render_layout (stylectxt, cr, text_x, text_y, layout); cairo_restore (cr); g_object_unref (layout); col_offset += w; } row_offset += h; } gtk_style_context_restore (stylectxt); cairo_destroy (cr); }
static void draw_window (GtkWidget *widget, GdkDrawable *drawable, const WnckWindowDisplayInfo *win, const GdkRectangle *winrect, GtkStateType state) { cairo_t *cr; GdkPixbuf *icon; int icon_x, icon_y, icon_w, icon_h; gboolean is_active; GdkColor *color; is_active = win->is_active; cr = gdk_cairo_create (drawable); cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height); cairo_clip (cr); if (is_active) color = &widget->style->light[state]; else color = &widget->style->bg[state]; cairo_set_source_rgb (cr, color->red / 65535., color->green / 65535., color->blue / 65535.); cairo_rectangle (cr, winrect->x + 1, winrect->y + 1, MAX (0, winrect->width - 2), MAX (0, winrect->height - 2)); cairo_fill (cr); icon = win->icon; icon_w = icon_h = 0; if (icon) { icon_w = gdk_pixbuf_get_width (icon); icon_h = gdk_pixbuf_get_height (icon); /* If the icon is too big, fall back to mini icon. * We don't arbitrarily scale the icon, because it's * just too slow on my Athlon 850. */ if (icon_w > (winrect->width - 2) || icon_h > (winrect->height - 2)) { icon = win->mini_icon; if (icon) { icon_w = gdk_pixbuf_get_width (icon); icon_h = gdk_pixbuf_get_height (icon); /* Give up. */ if (icon_w > (winrect->width - 2) || icon_h > (winrect->height - 2)) icon = NULL; } } } if (icon) { icon_x = winrect->x + (winrect->width - icon_w) / 2; icon_y = winrect->y + (winrect->height - icon_h) / 2; cairo_save (cr); gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y); cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h); cairo_clip (cr); cairo_paint (cr); cairo_restore (cr); } if (is_active) color = &widget->style->fg[state]; else color = &widget->style->fg[state]; cairo_set_source_rgb (cr, color->red / 65535., color->green / 65535., color->blue / 65535.); cairo_set_line_width (cr, 1.0); cairo_rectangle (cr, winrect->x + 0.5, winrect->y + 0.5, MAX (0, winrect->width - 1), MAX (0, winrect->height - 1)); cairo_stroke (cr); cairo_destroy (cr); }
int main (int argc, const char *argv[]) { cairo_surface_t *surface; struct chart chart; test_report_t *t; int i; chart.use_html = 0; chart.width = 640; chart.height = 480; chart.reports = xcalloc (argc-1, sizeof (cairo_perf_report_t)); chart.names = xcalloc (argc-1, sizeof (cairo_perf_report_t)); chart.num_reports = 0; for (i = 1; i < argc; i++) { if (strcmp (argv[i], "--html") == 0) { chart.use_html = 1; } else if (strncmp (argv[i], "--width=", 8) == 0) { chart.width = atoi (argv[i] + 8); } else if (strncmp (argv[i], "--height=", 9) == 0) { chart.height = atoi (argv[i] + 9); } else if (strcmp (argv[i], "--name") == 0) { if (i + 1 < argc) chart.names[chart.num_reports] = argv[++i]; } else if (strncmp (argv[i], "--name=", 7) == 0) { chart.names[chart.num_reports] = argv[i] + 7; } else { cairo_perf_report_load (&chart.reports[chart.num_reports++], argv[i], i, test_report_cmp_name); } } for (chart.relative = 0; chart.relative <= 1; chart.relative++) { surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, chart.width, chart.height + (FONT_SIZE + PAD) + 2*PAD); chart.cr = cairo_create (surface); cairo_surface_destroy (surface); cairo_set_source_rgb (chart.cr, 0, 0, 0); cairo_paint (chart.cr); find_ranges (&chart); for (i = 0; i < chart.num_tests; i++) test_background (&chart, i); if (chart.relative) { add_relative_lines (&chart); add_slower_faster_guide (&chart); } else add_absolute_lines (&chart); cairo_save (chart.cr); cairo_rectangle (chart.cr, 0, 0, chart.width, chart.height); cairo_clip (chart.cr); cairo_perf_reports_compare (&chart, !chart.relative); cairo_restore (chart.cr); add_base_line (&chart); add_legend (&chart); cairo_surface_write_to_png (cairo_get_target (chart.cr), chart.relative ? "relative.png" : "absolute.png"); cairo_destroy (chart.cr); } /* Pointless memory cleanup, (would be a great place for talloc) */ for (i = 0; i < chart.num_reports; i++) { for (t = chart.reports[i].tests; t->name; t++) { free (t->samples); free (t->backend); free (t->name); } free (chart.reports[i].tests); free (chart.reports[i].configuration); } free (chart.names); free (chart.reports); return 0; }
static void clearlooks_glossy_draw_progressbar_fill (cairo_t *cr, const ClearlooksColors *colors, const WidgetParameters *params, const ProgressBarParameters *progressbar, int x, int y, int width, int height, gint offset) { boolean is_horizontal = progressbar->orientation < 2; double tile_pos = 0; double stroke_width; double radius; int x_step; cairo_pattern_t *pattern; CairoColor a; CairoColor b; CairoColor e; CairoColor border; CairoColor shadow; radius = MAX (0, params->radius - params->xthickness); cairo_save (cr); if (!is_horizontal) ge_cairo_exchange_axis (cr, &x, &y, &width, &height); if ((progressbar->orientation == CL_ORIENTATION_RIGHT_TO_LEFT) || (progressbar->orientation == CL_ORIENTATION_BOTTOM_TO_TOP)) ge_cairo_mirror (cr, CR_MIRROR_HORIZONTAL, &x, &y, &width, &height); /* Clamp the radius so that the _height_ fits ... */ radius = MIN (radius, height / 2.0); stroke_width = height*2; x_step = (((float)stroke_width/10)*offset); /* This looks weird ... */ cairo_translate (cr, x, y); cairo_save (cr); /* This is kind of nasty ... Clip twice from each side in case the length * of the fill is smaller than twice the radius. */ ge_cairo_rounded_rectangle (cr, 0, 0, width + radius, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); cairo_clip (cr); ge_cairo_rounded_rectangle (cr, -radius, 0, width + radius, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); cairo_clip (cr); /* Draw the background gradient */ ge_shade_color (&colors->spot[1], 1.16, &a); ge_shade_color (&colors->spot[1], 1.08, &b); ge_shade_color (&colors->spot[1], 1.08, &e); pattern = cairo_pattern_create_linear (0, 0, 0, height); cairo_pattern_add_color_stop_rgb (pattern, 0.0, a.r, a.g, a.b); cairo_pattern_add_color_stop_rgb (pattern, 0.5, b.r, b.g, b.b); cairo_pattern_add_color_stop_rgb (pattern, 0.5, colors->spot[1].r, colors->spot[1].g, colors->spot[1].b); cairo_pattern_add_color_stop_rgb (pattern, 1.0, e.r, e.g, e.b); cairo_set_source (cr, pattern); cairo_paint (cr); cairo_pattern_destroy (pattern); /* Draw the Strokes */ while (stroke_width > 0 && tile_pos <= width+x_step) { cairo_move_to (cr, stroke_width/2-x_step, 0); cairo_line_to (cr, stroke_width-x_step, 0); cairo_line_to (cr, stroke_width/2-x_step, height); cairo_line_to (cr, -x_step, height); cairo_translate (cr, stroke_width, 0); tile_pos += stroke_width; } cairo_set_source_rgba (cr, colors->spot[2].r, colors->spot[2].g, colors->spot[2].b, 0.15); cairo_fill (cr); cairo_restore (cr); /* rounded clip region */ /* inner highlight border * This is again kinda ugly. Draw once from each side, clipping away the other. */ cairo_set_source_rgba (cr, colors->spot[0].r, colors->spot[0].g, colors->spot[0].b, 0.3); /* left side */ cairo_save (cr); cairo_rectangle (cr, 0, 0, width / 2, height); cairo_clip (cr); if (progressbar->pulsing) ge_cairo_rounded_rectangle (cr, 1.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); else ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); cairo_stroke (cr); cairo_restore (cr); /* clip */ /* right side */ cairo_save (cr); cairo_rectangle (cr, width / 2, 0, (width+1) / 2, height); cairo_clip (cr); if (progressbar->value < 1.0 || progressbar->pulsing) ge_cairo_rounded_rectangle (cr, -1.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); else ge_cairo_rounded_rectangle (cr, -0.5 - radius, 0.5, width + radius, height - 1, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); cairo_stroke (cr); cairo_restore (cr); /* clip */ /* Draw the dark lines and the shadow */ cairo_save (cr); /* Again, this weird clip area. */ ge_cairo_rounded_rectangle (cr, -1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPLEFT | CR_CORNER_BOTTOMLEFT); cairo_clip (cr); ge_cairo_rounded_rectangle (cr, -radius - 1.0, 0, width + radius + 2.0, height, radius, CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMRIGHT); cairo_clip (cr); border = colors->spot[2]; border.a = 0.5; ge_shade_color (&colors->shade[6], 0.92, &shadow); shadow.a = 0.2; if (progressbar->pulsing) { /* At the beginning of the bar. */ cairo_move_to (cr, 0.5 + radius, height + 0.5); ge_cairo_rounded_corner (cr, 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); ge_cairo_rounded_corner (cr, 0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); ge_cairo_set_color (cr, &border); cairo_stroke (cr); cairo_move_to (cr, -0.5 + radius, height + 0.5); ge_cairo_rounded_corner (cr, -0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMLEFT); ge_cairo_rounded_corner (cr, -0.5, -0.5, radius + 1, CR_CORNER_TOPLEFT); ge_cairo_set_color (cr, &shadow); cairo_stroke (cr); } if (progressbar->value < 1.0 || progressbar->pulsing) { /* At the end of the bar. */ cairo_move_to (cr, width - 0.5 - radius, -0.5); ge_cairo_rounded_corner (cr, width - 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); ge_cairo_rounded_corner (cr, width - 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); ge_cairo_set_color (cr, &border); cairo_stroke (cr); cairo_move_to (cr, width + 0.5 - radius, -0.5); ge_cairo_rounded_corner (cr, width + 0.5, -0.5, radius + 1, CR_CORNER_TOPRIGHT); ge_cairo_rounded_corner (cr, width + 0.5, height + 0.5, radius + 1, CR_CORNER_BOTTOMRIGHT); ge_cairo_set_color (cr, &shadow); cairo_stroke (cr); } cairo_restore (cr); cairo_restore (cr); /* rotation, mirroring */ }
static void clearlooks_glossy_draw_tab (cairo_t *cr, const ClearlooksColors *colors, const WidgetParameters *params, const TabParameters *tab, int x, int y, int width, int height) { const CairoColor *border = &colors->shade[5]; const CairoColor *stripe_fill = &colors->spot[1]; const CairoColor *stripe_border = &colors->spot[2]; const CairoColor *fill; CairoColor hilight; cairo_pattern_t *pattern; double radius; double strip_size; double length; radius = MIN (params->radius, MIN ((width - 2.0) / 2.0, (height - 2.0) / 2.0)); /* Set clip */ cairo_rectangle (cr, x, y, width, height); cairo_clip (cr); cairo_new_path (cr); /* Translate and set line width */ cairo_set_line_width (cr, 1.0); cairo_translate (cr, x+0.5, y+0.5); /* Make the tabs slightly bigger than they should be, to create a gap */ /* And calculate the strip size too, while you're at it */ if (tab->gap_side == CL_GAP_TOP || tab->gap_side == CL_GAP_BOTTOM) { height += 3.0; length = height; strip_size = 2.0/height; /* 2 pixel high strip */ if (tab->gap_side == CL_GAP_TOP) cairo_translate (cr, 0.0, -3.0); /* gap at the other side */ } else { width += 3.0; length = width; strip_size = 2.0/width; if (tab->gap_side == CL_GAP_LEFT) cairo_translate (cr, -3.0, 0.0); /* gap at the other side */ } /* Set the fill color */ fill = &colors->bg[params->state_type]; /* Set tab shape */ ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); /* Draw fill */ ge_cairo_set_color (cr, fill); cairo_fill (cr); ge_shade_color (fill, 1.3, &hilight); /* Draw highlight */ if (!params->active) { ShadowParameters shadow; shadow.shadow = CL_SHADOW_OUT; shadow.corners = params->corners; /* This is the only usage of clearlooks_glossy_draw_highlight_and_shade, * the function assumes currently that the input is translated by 0.5 px. */ clearlooks_glossy_draw_highlight_and_shade (cr, &colors->bg[0], &shadow, width, height, radius); } if (params->active) { CairoColor shadow, hilight, f1, f2; switch (tab->gap_side) { case CL_GAP_TOP: pattern = cairo_pattern_create_linear (0, height-2, 0, 0); break; case CL_GAP_BOTTOM: pattern = cairo_pattern_create_linear (0, 1, 0, height); break; case CL_GAP_LEFT: pattern = cairo_pattern_create_linear (width-2, 0, 1, 0); break; case CL_GAP_RIGHT: pattern = cairo_pattern_create_linear (1, 0, width-2, 0); break; default: pattern = NULL; } ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); ge_shade_color (fill, 1.06, &shadow); ge_shade_color (fill, 1.18, &hilight); ge_shade_color (fill, 1.12, &f1); ge_shade_color (fill, 1.06, &f2); cairo_pattern_add_color_stop_rgb (pattern, 0.0, hilight.r, hilight.g, hilight.b); cairo_pattern_add_color_stop_rgb (pattern, 1.0/length, hilight.r, hilight.g, hilight.b); cairo_pattern_add_color_stop_rgb (pattern, 1.0/length, f1.r, f1.g, f1.b); cairo_pattern_add_color_stop_rgb (pattern, 0.45, f2.r, f2.g, f2.b); cairo_pattern_add_color_stop_rgb (pattern, 0.45, fill->r, fill->g, fill->b); cairo_pattern_add_color_stop_rgb (pattern, 1.0, shadow.r, shadow.g, shadow.b); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); } else { /* Draw shade */ switch (tab->gap_side) { case CL_GAP_TOP: pattern = cairo_pattern_create_linear (0, height-2, 0, 0); break; case CL_GAP_BOTTOM: pattern = cairo_pattern_create_linear (0, 0, 0, height); break; case CL_GAP_LEFT: pattern = cairo_pattern_create_linear (width-2, 0, 0, 0); break; case CL_GAP_RIGHT: pattern = cairo_pattern_create_linear (0, 0, width, 0); break; default: pattern = NULL; } ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); cairo_pattern_add_color_stop_rgba (pattern, 0.0, stripe_fill->r, stripe_fill->g, stripe_fill->b, 0.5); cairo_pattern_add_color_stop_rgba (pattern, 0.8, fill->r, fill->g, fill->b, 0.0); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); } ge_cairo_rounded_rectangle (cr, 0, 0, width-1, height-1, radius, params->corners); if (params->active) { ge_cairo_set_color (cr, border); cairo_stroke (cr); } else { switch (tab->gap_side) { case CL_GAP_TOP: pattern = cairo_pattern_create_linear (2, height-2, 2, 2); break; case CL_GAP_BOTTOM: pattern = cairo_pattern_create_linear (2, 2, 2, height); break; case CL_GAP_LEFT: pattern = cairo_pattern_create_linear (width-2, 2, 2, 2); break; case CL_GAP_RIGHT: pattern = cairo_pattern_create_linear (2, 2, width, 2); break; default: pattern = NULL; } cairo_pattern_add_color_stop_rgb (pattern, 0.0, stripe_border->r, stripe_border->g, stripe_border->b); cairo_pattern_add_color_stop_rgb (pattern, 0.8, border->r, border->g, border->b); cairo_set_source (cr, pattern); cairo_stroke (cr); cairo_pattern_destroy (pattern); } }
static void clearlooks_glossy_draw_button (cairo_t *cr, const ClearlooksColors *colors, const WidgetParameters *params, int x, int y, int width, int height) { double xoffset = 0, yoffset = 0; CairoColor fill = colors->bg[params->state_type]; CairoColor border_normal = colors->shade[6]; CairoColor border_disabled = colors->shade[4]; double radius; cairo_pattern_t *pattern; cairo_save (cr); cairo_translate (cr, x, y); cairo_set_line_width (cr, 1.0); /* Shadows and shadow */ if (params->xthickness == 3 || params->ythickness == 3) { if (params->xthickness == 3) xoffset = 1; if (params->ythickness == 3) yoffset = 1; } radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0, (height - 2.0 - 2*yoffset) / 2.0)); if (params->xthickness == 3 || params->ythickness == 3) { /* if (params->enable_shadow && !params->active && !params->disabled) */ if (!params->active && (params->prelight || params->enable_shadow)) { /* shadow becomes a shadow to have 3d prelight buttons :) */ CairoColor shadow; radius = MIN (params->radius, MIN ((width - 2.0 - 2*xoffset) / 2.0 - 1.0, (height - 2.0 - 2*yoffset) / 2.0 - 1.0)); ge_cairo_rounded_rectangle (cr, 0.5, 0.5, width-1, height-1, radius+1, params->corners); ge_shade_color (¶ms->parentbg, 0.96, &shadow); ge_cairo_set_color (cr, &shadow); cairo_stroke (cr); ge_cairo_rounded_rectangle (cr, 1.5, 1.5, width-2, height-2, radius+1, params->corners); ge_shade_color (¶ms->parentbg, 0.92, &shadow); ge_cairo_set_color (cr, &shadow); cairo_stroke (cr); } else { if (!(params->disabled)) params->style_functions->draw_inset (cr, ¶ms->parentbg, 0, 0, width, height, params->radius+1, params->corners); else /*Draw a lighter inset */ clearlooks_glossy_draw_light_inset (cr, ¶ms->parentbg, 0, 0, width, height, params->radius+1, params->corners); } } clearlooks_draw_glossy_gradient (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, height-(yoffset*2)-2, &fill, params->disabled, radius, params->corners); /* Pressed button shadow */ if (params->active) { CairoColor shadow; ge_shade_color (&fill, 0.92, &shadow); cairo_save (cr); ge_cairo_rounded_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, height, radius, params->corners & (CR_CORNER_TOPLEFT | CR_CORNER_TOPRIGHT | CR_CORNER_BOTTOMLEFT)); cairo_clip (cr); cairo_rectangle (cr, xoffset+1, yoffset+1, width-(xoffset*2)-2, 3); pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+1, yoffset+4); cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_rectangle (cr, xoffset+1, yoffset+1, 3, height-(yoffset*2)-2); pattern = cairo_pattern_create_linear (xoffset+1, yoffset+1, xoffset+4, yoffset+1); cairo_pattern_add_color_stop_rgba (pattern, 0.0, shadow.r, shadow.g, shadow.b, 0.58); cairo_pattern_add_color_stop_rgba (pattern, 1.0, shadow.r, shadow.g, shadow.b, 0.0); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_restore (cr); } /* Default button highlight */ if (params->is_default && !params->active && !params->disabled) { const CairoColor *shadow = &colors->spot[0]; double hh = (height-5)/2.0 + 1; cairo_rectangle (cr, 3.5, 3.5, width-7, height-7); ge_cairo_set_color (cr, shadow); cairo_stroke (cr); shadow = &colors->spot[0]; cairo_move_to (cr, 2.5, 2.5+hh); cairo_rel_line_to (cr, 0, -hh); cairo_rel_line_to (cr, width-5, 0); cairo_rel_line_to (cr, 0, hh); ge_cairo_set_color (cr, shadow); cairo_stroke (cr); hh--; shadow = &colors->spot[1]; cairo_move_to (cr, 2.5, 2.5+hh); cairo_rel_line_to (cr, 0, hh); cairo_rel_line_to (cr, width-5, 0); cairo_rel_line_to (cr, 0, -hh); ge_cairo_set_color (cr, shadow); cairo_stroke (cr); } /* Border */ if (params->is_default || (params->prelight && params->enable_shadow)) border_normal = colors->spot[2]; /* ge_mix_color (&border_normal, &colors->spot[2], 0.5, &border_normal); */ if (params->disabled) ge_cairo_set_color (cr, &border_disabled); else clearlooks_set_mixed_color (cr, &border_normal, &fill, 0.2); ge_cairo_rounded_rectangle (cr, xoffset + 0.5, yoffset + 0.5, width-(xoffset*2)-1, height-(yoffset*2)-1, radius, params->corners); cairo_stroke (cr); cairo_restore (cr); }
static gboolean gtk_bubble_window_draw (GtkWidget *widget, cairo_t *cr) { GtkStyleContext *context; GtkAllocation allocation; GtkWidget *child; GtkBorder border; GdkRGBA border_color; gint rect_x1, rect_x2, rect_y1, rect_y2; gint initial_x, initial_y, final_x, final_y; gint gap_start, gap_end; GtkPositionType gap_side; GtkStateFlags state; context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); gtk_widget_get_allocation (widget, &allocation); if (gtk_widget_is_composited (widget)) { cairo_save (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (cr, 0, 0, 0, 0); cairo_paint (cr); cairo_restore (cr); } gtk_bubble_window_get_rect_coords (GTK_BUBBLE_WINDOW (widget), &rect_x1, &rect_y1, &rect_x2, &rect_y2); /* Render the rect background */ gtk_render_background (context, cr, rect_x1, rect_y1, rect_x2 - rect_x1, rect_y2 - rect_y1); gtk_bubble_window_get_gap_coords (GTK_BUBBLE_WINDOW (widget), &initial_x, &initial_y, NULL, NULL, &final_x, &final_y, &gap_side); if (POS_IS_VERTICAL (gap_side)) { gap_start = initial_x; gap_end = final_x; } else { gap_start = initial_y; gap_end = final_y; } /* Now render the frame, without the gap for the arrow tip */ gtk_render_frame_gap (context, cr, rect_x1, rect_y1, rect_x2 - rect_x1, rect_y2 - rect_y1, gap_side, gap_start, gap_end); /* Clip to the arrow shape */ cairo_save (cr); gtk_bubble_window_apply_tail_path (GTK_BUBBLE_WINDOW (widget), cr); cairo_clip (cr); /* Render the arrow background */ gtk_render_background (context, cr, 0, 0, allocation.width, allocation.height); /* Render the border of the arrow tip */ gtk_style_context_get_border (context, state, &border); if (border.bottom > 0) { gtk_style_context_get_border_color (context, state, &border_color); gtk_bubble_window_apply_tail_path (GTK_BUBBLE_WINDOW (widget), cr); gdk_cairo_set_source_rgba (cr, &border_color); cairo_set_line_width (cr, border.bottom); cairo_stroke (cr); } /* We're done */ cairo_restore (cr); child = gtk_bin_get_child (GTK_BIN (widget)); if (child) gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr); return TRUE; }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) { drawSimpleText(context, run, point, from, to); return; } #endif cairo_t* cr = context->platformContext()->cr(); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters16(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); // Get the region where this text will be laid out. We will use it to clip // the Cairo context, for when we are only painting part of the text run and // to calculate the size of the shadow buffer. PangoRegionType partialRegion = 0; char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; #if PLATFORM(GTK) partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); #else partialRegion = getClipRegionFromPangoLayoutLine(layoutLine, ranges); #endif drawGlyphsShadow(context, point, layoutLine, partialRegion); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); float red, green, blue, alpha; context->fillColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); #if PLATFORM(GTK) gdk_cairo_region(cr, partialRegion); #else appendRegionToCairoContext(cr, partialRegion); #endif cairo_clip(cr); pango_cairo_show_layout_line(cr, layoutLine); if (context->textDrawingMode() & TextModeStroke) { Color strokeColor = context->strokeColor(); strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); pango_cairo_layout_line_path(cr, layoutLine); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); destroyPangoRegion(partialRegion); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
void PluginView::paint(GraphicsContext* context, const IntRect& rect) { if (!m_isStarted || m_status != PluginStatusLoadedSuccessfully) { paintMissingPluginIcon(context, rect); return; } if (context->paintingDisabled()) return; setNPWindowIfNeeded(); if (m_isWindowed) return; if (!m_drawable) return; Display* display = getPluginDisplay(nullptr); const bool syncX = m_pluginDisplay && m_pluginDisplay != display; IntRect exposedRect(rect); exposedRect.intersect(frameRect()); exposedRect.move(-frameRect().x(), -frameRect().y()); RefPtr<cairo_surface_t> drawableSurface = adoptRef(cairo_xlib_surface_create(display, m_drawable, m_visual, m_windowRect.width(), m_windowRect.height())); if (m_isTransparent) { // If we have a 32 bit drawable and the plugin wants transparency, // we'll clear the exposed area to transparent first. Otherwise, // we'd end up with junk in there from the last paint, or, worse, // uninitialized data. RefPtr<cairo_t> cr = adoptRef(cairo_create(drawableSurface.get())); if (!(cairo_surface_get_content(drawableSurface.get()) & CAIRO_CONTENT_ALPHA)) { // Attempt to fake it when we don't have an alpha channel on our // pixmap. If that's not possible, at least clear the window to // avoid drawing artifacts. // This Would not work without double buffering, but we always use it. cairo_set_source_surface(cr.get(), cairo_get_group_target(context->platformContext()->cr()), -m_windowRect.x(), -m_windowRect.y()); cairo_set_operator(cr.get(), CAIRO_OPERATOR_SOURCE); } else cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr.get(), exposedRect.x(), exposedRect.y(), exposedRect.width(), exposedRect.height()); cairo_fill(cr.get()); } XEvent xevent; memset(&xevent, 0, sizeof(XEvent)); XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose; exposeEvent.type = GraphicsExpose; exposeEvent.display = display; exposeEvent.drawable = m_drawable; exposeEvent.x = exposedRect.x(); exposeEvent.y = exposedRect.y(); exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode dispatchNPEvent(xevent); if (syncX) XSync(m_pluginDisplay, false); // sync changes by plugin cairo_t* cr = context->platformContext()->cr(); cairo_save(cr); cairo_set_source_surface(cr, drawableSurface.get(), frameRect().x(), frameRect().y()); cairo_rectangle(cr, frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y(), exposedRect.width(), exposedRect.height()); cairo_clip(cr); if (m_isTransparent) cairo_set_operator(cr, CAIRO_OPERATOR_OVER); else cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_restore(cr); }
static gboolean UpdatePreviewWindow( GtkWidget* widget, cairo_t* cairo_p, APPLICATION* app ) #endif { // 描画領域のサイズ取得用 GtkAllocation preview_allocation; #if GTK_MAJOR_VERSION <= 2 // 描画用のCairo情報 cairo_t *cairo_p; #endif // 描画領域1行分のバイト数 int stride; // 拡大率更新のフラグ int update_zoom = 0; if(app->window_num == 0) { return FALSE; } gtk_widget_get_allocation(app->preview_window.image, &preview_allocation); stride = preview_allocation.width * 4; if(app->preview_window.width != preview_allocation.width || app->preview_window.height != preview_allocation.height) { app->preview_window.pixels = (uint8*)MEM_REALLOC_FUNC( app->preview_window.pixels, preview_allocation.height * stride); app->preview_window.reverse_buff = (uint8*)MEM_REALLOC_FUNC( app->preview_window.reverse_buff, stride); app->preview_window.width = preview_allocation.width; app->preview_window.height = preview_allocation.height; if(app->preview_window.cairo_p != NULL) { cairo_destroy(app->preview_window.cairo_p); cairo_surface_destroy(app->preview_window.surface_p); } // CAIRO情報作り直し app->preview_window.surface_p = cairo_image_surface_create_for_data(app->preview_window.pixels, CAIRO_FORMAT_ARGB32, preview_allocation.width, preview_allocation.height, stride); app->preview_window.cairo_p = cairo_create(app->preview_window.surface_p); // 拡大率の更新 update_zoom++; } // 描画領域の変更やウィンドウサイズの変更があれば拡大率を更新 if(update_zoom != 0 || app->draw_window[app->active_window] != app->preview_window.draw) { gdouble zoom_x = (gdouble)preview_allocation.width / app->draw_window[app->active_window]->width; gdouble zoom_y = (gdouble)preview_allocation.height / app->draw_window[app->active_window]->height; if(zoom_x < zoom_y) { app->preview_window.zoom = zoom_x; app->preview_window.rev_zoom = 1 / zoom_x; } else { app->preview_window.zoom = zoom_y; app->preview_window.rev_zoom = 1 / zoom_y; } app->preview_window.draw_width = (int32)(app->draw_window[app->active_window]->width * app->preview_window.zoom); app->preview_window.draw_height = (int32)(app->draw_window[app->active_window]->height * app->preview_window.zoom); } // 画像を拡大縮小して描画 cairo_scale(app->preview_window.cairo_p, app->preview_window.zoom, app->preview_window.zoom); cairo_set_source_surface(app->preview_window.cairo_p, app->draw_window[app->active_window]->mixed_layer->surface_p, 0, 0); cairo_paint(app->preview_window.cairo_p); // 拡大率を元に戻す cairo_scale(app->preview_window.cairo_p, app->preview_window.rev_zoom, app->preview_window.rev_zoom); // 左右反転表示中ならピクセルデータを反転 if((app->draw_window[app->active_window]->flags & DRAW_WINDOW_DISPLAY_HORIZON_REVERSE) != 0) { uint8 *src, *ref; int x, y; for(y=0; y<app->preview_window.draw_height; y++) { ref = app->preview_window.reverse_buff; src = &app->preview_window.pixels[y*stride+app->preview_window.draw_width*4-4]; for(x=0; x<app->preview_window.draw_width; x++, ref += 4, src -= 4) { ref[0] = src[0], ref[1] = src[1], ref[2] = src[2], ref[3] = src[3]; } (void)memcpy(src+4, app->preview_window.reverse_buff, app->preview_window.draw_width * 4); } } // 画面更新 #if GTK_MAJOR_VERSION <= 2 //cairo_p = kaburagi_cairo_create((struct _GdkWindow*)app->preview_window.image->window); cairo_p = gdk_cairo_create(app->preview_window.image->window); #endif cairo_rectangle(cairo_p, 0, 0, app->preview_window.draw_width, app->preview_window.draw_height); cairo_clip(cairo_p); cairo_set_source_surface(cairo_p, app->preview_window.surface_p, 0, 0); cairo_paint(cairo_p); #if GTK_MAJOR_VERSION <= 2 cairo_destroy(cairo_p); #endif return TRUE; }