/* this track selector function is used to disregard file names in track identifiers */ static void flattened_file_track_selector(GtBlock *block, GtStr *result, GT_UNUSED void *data) { gt_assert(block && result); gt_str_reset(result); gt_str_append_cstr(result, gt_block_get_type(block)); }
static void default_track_selector(GtBlock *block, GtStr *result, GT_UNUSED void *data) { GtGenomeNode *top; char *basename; gt_assert(block && result); gt_str_reset(result); top = (GtGenomeNode*) gt_block_get_top_level_feature(block); /* we take the basename of the filename to have nicer output in the generated graphic. this might lead to ``collapsed'' tracks, if two files with different paths have the same basename. */ basename = gt_basename(gt_genome_node_get_filename(top)); gt_str_append_cstr(result, basename); gt_free(basename); gt_str_append_char(result, GT_FILENAME_TYPE_SEPARATOR); gt_str_append_cstr(result, gt_block_get_type(block)); }
static void add_recursive(GtDiagram *d, GtFeatureNode *node, GtFeatureNode* parent, GtFeatureNode *original_node) { NodeInfoElement *ni; GtFeatureNode *rep = GT_UNDEF_REPR; gt_assert(d && node && original_node); if (!parent) return; ni = nodeinfo_get(d, node); if (gt_feature_node_is_multi(original_node)) { rep = gt_feature_node_get_multi_representative(original_node); } /* end of recursion, insert into target block */ if (parent == node) { GtBlock *block ; block = nodeinfo_find_block(ni, gt_feature_node_get_type(node), rep); if (!block) { block = gt_block_new_from_node(node); nodeinfo_add_block(ni, gt_feature_node_get_type(node), rep, block); } gt_block_insert_element(block, original_node); gt_log_log("add %s to target %s", gt_feature_node_get_type(original_node), gt_block_get_type(block)); } else { /* not at target type block yet, set up reverse entry and follow */ NodeInfoElement *parent_ni; /* set up reverse entry */ ni->parent = parent; parent_ni = gt_hashmap_get(d->nodeinfo, parent); if (parent_ni) { gt_log_log("recursion: %s -> %s", gt_feature_node_get_type(node), gt_feature_node_get_type(parent)); add_recursive(d, parent, parent_ni->parent, original_node); } } }
static int layout_tracks(void *key, void *value, void *data, GtError *err) { unsigned long i, max = 50; GtTrack *track = NULL; GtLayoutTraverseInfo *lti = (GtLayoutTraverseInfo*) data; GtArray *list = (GtArray*) value; GtStr *gt_track_key; GtBlock *block; int had_err = 0; bool split = true; double tmp = 50; gt_assert(list); /* to get a deterministic layout, we sort the GtBlocks for each type */ if (lti->layout->block_ordering_func) { gt_array_sort_stable_with_data(list, blocklist_block_compare, lti->layout); } /* XXX: get first block for track property lookups, this should be reworked to allow arbitrary track keys! */ block = *(GtBlock**) gt_array_get(list, 0); gt_track_key = gt_str_new_cstr((char*) key); /* obtain default settings*/ if (gt_style_get_bool(lti->layout->style, "format", "split_lines", &split, NULL, err) == GT_STYLE_QUERY_ERROR) { had_err = 1; } if (!had_err) { if (gt_style_get_num(lti->layout->style, "format", "max_num_lines", &tmp, NULL, err) == GT_STYLE_QUERY_ERROR) { had_err = 1; } } /* obtain track-specific settings, should be changed to query arbitrary track keys! */ if (!had_err) { if (gt_style_get_bool(lti->layout->style, gt_block_get_type(block), "split_lines", &split, NULL, err) == GT_STYLE_QUERY_ERROR) { had_err = 1; } } if (!had_err) { if (gt_style_get_num(lti->layout->style, gt_block_get_type(block), "max_num_lines", &tmp, NULL, err) == GT_STYLE_QUERY_ERROR) { had_err = 1; } } if (!had_err) { max = (unsigned long) tmp; track = gt_track_new(gt_track_key, max, split, gt_line_breaker_captions_new(lti->layout, lti->layout->width, lti->layout->style)); lti->layout->nof_tracks++; for (i = 0; !had_err && i < gt_array_size(list); i++) { block = *(GtBlock**) gt_array_get(list, i); had_err = gt_track_insert_block(track, block, err); } } if (!had_err) { gt_hashmap_add(lti->layout->tracks, gt_cstr_dup(gt_str_get(gt_track_key)), track); } else { gt_track_delete(track); } gt_str_delete(gt_track_key); 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; }