GtCanvas* gt_canvas_cairo_file_new(GtStyle *style, GtGraphicsOutType output_type, GtUword width, GtUword height, GtImageInfo *image_info, GtError *err) { GtCanvas *canvas; GtColor bgcolor = {1.0, 1.0, 1.0, 1.0}; GtCanvasCairoFile *ccf; GtStyleQueryStatus status; double margins = 10.0; gt_assert(style && width > 0 && height > 0); status = gt_style_get_color(style, "format", "background_color", &bgcolor, NULL, err); switch (status) { case GT_STYLE_QUERY_ERROR: return NULL; case GT_STYLE_QUERY_NOT_SET: bgcolor.red = bgcolor.green = bgcolor.blue = bgcolor.alpha = 1.0; break; default: break; } if (gt_style_get_num(style, "format", "margins", &margins, NULL, err) == GT_STYLE_QUERY_ERROR) { return NULL; } canvas = gt_canvas_create(gt_canvas_cairo_file_class()); canvas->pvt->g = gt_graphics_cairo_new(output_type, width, height); (void) gt_graphics_set_background_color(canvas->pvt->g, bgcolor); (void) gt_graphics_set_margins(canvas->pvt->g, margins, 0); canvas->pvt->margins = margins; if (image_info) gt_image_info_set_height(image_info, height); canvas->pvt->sty = style; canvas->pvt->y += 0.5; canvas->pvt->ii = image_info; canvas->pvt->width = width; canvas->pvt->height = height; canvas->pvt->bt = NULL; ccf = canvas_cairo_file_cast(canvas); ccf->type = output_type; return canvas; }
int gt_canvas_cairo_visit_custom_track(GtCanvas *canvas, GtCustomTrack *ct, GtError *err) { bool show_track_captions = true; double space; int had_err = 0; GtColor color; gt_assert(canvas && ct); if (gt_style_get_bool(canvas->pvt->sty, "format", "show_track_captions", &show_track_captions, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_color(canvas->pvt->sty, "format", "track_title_color", &color, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (show_track_captions) { double theight = gt_graphics_get_text_height(canvas->pvt->g), captionspace = CAPTION_BAR_SPACE_DEFAULT; if (gt_style_get_num(canvas->pvt->sty, "format", "track_caption_font_size", &theight, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } /* draw track title */ gt_graphics_set_font(canvas->pvt->g, "Sans", SLANT_NORMAL, WEIGHT_NORMAL, theight); gt_graphics_draw_colored_text(canvas->pvt->g, canvas->pvt->margins, canvas->pvt->y, color, gt_custom_track_get_title(ct)); if (gt_style_get_num(canvas->pvt->sty, "format", "track_caption_space", &captionspace, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } canvas->pvt->y += theight + captionspace; } /* call rendering function */ had_err = gt_custom_track_render(ct, canvas->pvt->g, canvas->pvt->y, canvas->pvt->viewrange, canvas->pvt->sty, err); canvas->pvt->y += gt_custom_track_get_height(ct); /* put spacers after track */ space = TRACK_VSPACE_DEFAULT; if (gt_style_get_num(canvas->pvt->sty, "format", "track_vspace", &space, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } canvas->pvt->y += space; return had_err; }
int gt_canvas_cairo_visit_track_pre(GtCanvas *canvas, GtTrack *track, GtError *err) { int had_err = 0; unsigned long exceeded; bool show_track_captions = true; GtColor color; gt_assert(canvas && track); if (gt_style_get_bool(canvas->pvt->sty, "format", "show_track_captions", &show_track_captions, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_color(canvas->pvt->sty, "format", "track_title_color", &color, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } /* debug */ gt_log_log("processing track %s", gt_str_get(gt_track_get_title(track))); if (show_track_captions) { double theight = gt_graphics_get_text_height(canvas->pvt->g), captionspace = CAPTION_BAR_SPACE_DEFAULT; if (gt_style_get_num(canvas->pvt->sty, "format", "track_caption_font_size", &theight, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "track_caption_space", &captionspace, NULL, err ) == GT_STYLE_QUERY_ERROR) { return -1; } gt_graphics_set_font(canvas->pvt->g, "Sans", SLANT_NORMAL, WEIGHT_NORMAL, theight); canvas->pvt->y += theight; /* draw track title */ gt_graphics_draw_colored_text(canvas->pvt->g, canvas->pvt->margins, canvas->pvt->y, color, gt_str_get(gt_track_get_title(track))); /* draw 'line maximum exceeded' message */ if ((exceeded = gt_track_get_number_of_discarded_blocks(track)) > 0) { char buf[BUFSIZ]; const char *msg; double width; GtColor red; red.red = LINE_EXCEEDED_MSG_R; red.green = LINE_EXCEEDED_MSG_G; red.blue = LINE_EXCEEDED_MSG_B; red.alpha = 1.0; if (exceeded == 1) { msg = "(1 block not shown due to exceeded line limit)"; strncpy(buf, msg, BUFSIZ); } else { msg = "(%lu blocks not shown due to exceeded line limit)"; /*@ignore@*/ snprintf(buf, BUFSIZ, msg, exceeded); /*@end@*/ } width = gt_graphics_get_text_width(canvas->pvt->g, gt_str_get(gt_track_get_title(track))); gt_graphics_draw_colored_text(canvas->pvt->g, canvas->pvt->margins+width+10.0, canvas->pvt->y, red, buf); } canvas->pvt->y += captionspace; } return had_err; }
int gt_canvas_cairo_visit_block(GtCanvas *canvas, GtBlock *block, GtError *err) { int had_err = 0, arrow_status = ARROW_NONE; GtRange block_range; GtDrawingRange draw_range; GtColor grey, fillcolor, strokecolor; double block_start, block_width, bar_height = BAR_HEIGHT_DEFAULT, min_len_block = MIN_LEN_BLOCK_DEFAULT, arrow_width = ARROW_WIDTH_DEFAULT, stroke_width = STROKE_WIDTH_DEFAULT; const char *caption, *btype; GtStrand strand; double maxbarheight; btype = gt_block_get_type(block); gt_assert(canvas && block); grey.red = grey.green = grey.blue = DEFAULT_GREY_TONE; grey.alpha = 0.5; strand = gt_block_get_strand(block); block_range = gt_block_get_range(block); if (gt_block_get_max_height(block, &maxbarheight, canvas->pvt->sty, err)) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "bar_height", &bar_height, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "min_len_block", &min_len_block,NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "arrow_width", &arrow_width, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "stroke_width", &stroke_width, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_color_with_track(canvas->pvt->sty, btype, "stroke", &strokecolor, gt_block_get_top_level_feature(block), gt_track_get_title(canvas->pvt->current_track), err) == GT_STYLE_QUERY_ERROR) { return -1; } if (strand == GT_STRAND_REVERSE || strand == GT_STRAND_BOTH) arrow_status = ARROW_LEFT; if (strand == GT_STRAND_FORWARD || strand == GT_STRAND_BOTH) arrow_status = (arrow_status == ARROW_LEFT ? ARROW_BOTH : ARROW_RIGHT); /* calculate scaled drawing coordinates for this canvas */ draw_range = gt_coords_calc_generic_range(block_range, canvas->pvt->viewrange); draw_range.start *= canvas->pvt->width-2*canvas->pvt->margins; draw_range.end *= canvas->pvt->width-2*canvas->pvt->margins; block_start = draw_range.start + canvas->pvt->margins; block_width = draw_range.end - draw_range.start; /* draw block caption */ if (gt_block_caption_is_visible(block)) { caption = gt_str_get(gt_block_get_caption(block)); if (caption) { double theight = gt_graphics_get_text_height(canvas->pvt->g), captionspace = CAPTION_BAR_SPACE_DEFAULT; if (gt_style_get_num(canvas->pvt->sty, "format", "block_caption_space", &captionspace, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } if (gt_style_get_num(canvas->pvt->sty, "format", "block_caption_font_size", &theight, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } gt_graphics_set_font(canvas->pvt->g, "Sans", SLANT_NORMAL, WEIGHT_NORMAL, theight); gt_graphics_draw_text_clip(canvas->pvt->g, block_start, canvas->pvt->y - bar_height/2 - captionspace, caption); } } /* do not draw further details in very small blocks */ if (!gt_block_has_only_one_fullsize_element(block) && gt_double_smaller_double(block_width, min_len_block)) { /* optimise drawing for very narrow blocks, if <= 1px/pt width, draw as simple lines */ if (canvas->pvt->bt && draw_range.end-draw_range.start <= 1.1) { if (!gt_bittab_bit_is_set(canvas->pvt->bt, (unsigned long) draw_range.start)) { gt_graphics_draw_vertical_line(canvas->pvt->g, block_start, canvas->pvt->y - bar_height/2, strokecolor, bar_height, stroke_width); gt_bittab_set_bit(canvas->pvt->bt, (unsigned long) draw_range.start); } } else { if (gt_style_get_color_with_track(canvas->pvt->sty, btype, "fill", &fillcolor, gt_block_get_top_level_feature(block), gt_track_get_title(canvas->pvt->current_track), err) == GT_STYLE_QUERY_ERROR) { return -1; } gt_graphics_draw_box(canvas->pvt->g, block_start, canvas->pvt->y - bar_height/2, block_width, bar_height, fillcolor, arrow_status, arrow_width, stroke_width, strokecolor, true); /* draw arrowheads at clipped margins */ if (draw_range.clip == CLIPPED_LEFT || draw_range.clip == CLIPPED_BOTH) gt_graphics_draw_arrowhead(canvas->pvt->g, canvas->pvt->margins - 10, canvas->pvt->y - 4, grey, ARROW_LEFT); if (draw_range.clip == CLIPPED_RIGHT || draw_range.clip == CLIPPED_BOTH) gt_graphics_draw_arrowhead(canvas->pvt->g, canvas->pvt->width-canvas->pvt->margins + 10, canvas->pvt->y - 4, grey, ARROW_RIGHT); } /* register coordinates in GtImageInfo object if available */ if (canvas->pvt->ii) { GtRecMap *rm = gt_rec_map_new(block_start, canvas->pvt->y - bar_height/2, block_start + block_width, canvas->pvt->y + bar_height/2, (GtFeatureNode*) /* XXX */ gt_block_get_top_level_feature(block)); gt_image_info_add_rec_map(canvas->pvt->ii, rm); gt_rec_map_set_omitted_children(rm, true); } /* signal break */ return 1; } /* get stroke color */ if (gt_style_get_color(canvas->pvt->sty, "format", "default_stroke_color", &strokecolor, NULL, err) == GT_STYLE_QUERY_ERROR) { return -1; } /* draw parent block boundaries */ gt_graphics_draw_dashes(canvas->pvt->g, block_start, canvas->pvt->y - bar_height/2, block_width, bar_height, ARROW_NONE, arrow_width, stroke_width, strokecolor); return had_err; }