Esempio n. 1
0
/* 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
	
}
Esempio n. 2
0
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);
                }
            }
        }
    }
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
static int
cr_clip (lua_State *L) {
    cairo_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_CONTEXT);
    cairo_clip(*obj);
    return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
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* 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;
}
Esempio n. 7
0
void
HippoCanvas::onPaint(WPARAM wParam, LPARAM lParam)
{
    RECT region;
    if (GetUpdateRect(window_, &region, 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(&region_hippo, &region);

            if (hippo_rectangle_intersect(&viewport_hippo, &region_hippo, &region_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, &region_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);
    }
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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);
            }
        }
    }
Esempio n. 10
0
/* 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(&gtk_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);
}
Esempio n. 11
0
/* 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);
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
void cairo_context::clip()
{
    cairo_clip(cairo_.get());
    check_object_status_and_throw_exception(*this);
}
Esempio n. 14
0
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;
    }
}
Esempio n. 15
0
static gboolean
gimp_color_bar_expose (GtkWidget      *widget,
                       GdkEventExpose *event)
{
  GimpColorBar    *bar = GIMP_COLOR_BAR (widget);
  cairo_t         *cr;
  GtkAllocation    allocation;
  cairo_surface_t *surface;
  cairo_pattern_t *pattern;
  guchar          *src;
  guchar          *dest;
  gint             x, y;
  gint             width, height;
  gint             i;

  cr = gdk_cairo_create (event->window);

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

  gtk_widget_get_allocation (widget, &allocation);

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

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

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

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

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1);

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

  cairo_surface_mark_dirty (surface);

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

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

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

  cairo_paint (cr);

  cairo_destroy (cr);

  return TRUE;
}
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);
}
Esempio n. 17
0
/**
 * 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;
}
Esempio n. 18
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
    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;
}
Esempio n. 19
0
/* 
 * 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)
}
Esempio n. 20
0
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);
    }
}
Esempio n. 21
0
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 (&params->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 (&params->parentbg, 0.92, &shadow);
			ge_cairo_set_color (cr, &shadow);
			cairo_stroke (cr);
		}
		else
		{
			if (!(params->disabled))
				params->style_functions->draw_inset (cr, &params->parentbg, 0, 0, width, height, params->radius+1, params->corners);
			else
				/*Draw a lighter inset */
				clearlooks_glossy_draw_light_inset (cr, &params->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);
}
Esempio n. 27
0
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;
}
Esempio n. 28
0
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);
}
Esempio n. 29
0
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);
}
Esempio n. 30
-1
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;
}