00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <cairo.h>
00004 #include "mb_types.h"
00005 #include "mb_redraw_man.h"
00006 #include "mb_shapes.h"
00007
00008 #define OK 0
00009 #define ERR -1
00010
00011 #define ARRAY_EXT_SZ 64
00012
00013
00014 DARRAY_DEFINE(geos, geo_t *);
00015
00016
00017
00018
00019
00020
00021
00022
00023 static int add_gen_geo(redraw_man_t *rdman, geo_t *geo) {
00024 int r;
00025
00026 r = geos_add(&rdman->gen_geos, geo);
00027 return r == 0? OK: ERR;
00028 }
00029
00030 static int collect_shapes_at_point(redraw_man_t *rdman,
00031 co_aix x, co_aix y) {
00032 geo_t *geo;
00033 int r;
00034
00035 r = rdman_force_clean(rdman);
00036 if(r != OK)
00037 return ERR;
00038
00039 rdman->gen_geos.num = 0;
00040
00041 for(geo = rdman_geos(rdman, NULL);
00042 geo != NULL;
00043 geo = rdman_geos(rdman, geo)) {
00044 if(geo_pos_is_in(geo, x, y)) {
00045 r = add_gen_geo(rdman, geo);
00046 if(r != OK)
00047 return ERR;
00048 }
00049 }
00050
00051 return OK;
00052 }
00053
00054 static void draw_shape_path(shape_t *shape, cairo_t *cr) {
00055 switch(shape->sh_type) {
00056 case SHT_PATH:
00057 sh_path_draw(shape, cr);
00058 break;
00059 case SHT_TEXT:
00060 sh_text_draw(shape, cr);
00061 break;
00062 case SHT_RECT:
00063 sh_rect_draw(shape, cr);
00064 break;
00065 }
00066 }
00067
00068 static geo_t *find_geo_in_pos(redraw_man_t *rdman,
00069 co_aix x, co_aix y, int *in_stroke) {
00070 geo_t *geo;
00071 geo_t **geos;
00072 shape_t *shape;
00073 cairo_t *cr;
00074 int i;
00075
00076 geos = rdman->gen_geos.ds;
00077 cr = rdman->cr;
00078 for(i = rdman->gen_geos.num - 1; i >= 0; i--) {
00079 geo = geos[i];
00080 if(geo->flags & GEF_HIDDEN)
00081 continue;
00082 shape = geo->shape;
00083 draw_shape_path(shape, cr);
00084 if(shape->fill) {
00085 if(cairo_in_fill(cr, x, y)) {
00086 *in_stroke = 0;
00087 cairo_new_path(rdman->cr);
00088 return geo;
00089 }
00090 }
00091 if(shape->stroke) {
00092 if(cairo_in_stroke(cr, x, y)) {
00093 *in_stroke = 1;
00094 cairo_new_path(rdman->cr);
00095 return geo;
00096 }
00097 }
00098 cairo_new_path(rdman->cr);
00099 }
00100
00101 return NULL;
00102 }
00103
00104 shape_t *find_shape_at_pos(redraw_man_t *rdman,
00105 co_aix x, co_aix y, int *in_stroke) {
00106 geo_t *geo;
00107 int r;
00108
00109 r = collect_shapes_at_point(rdman, x, y);
00110 if(r != OK)
00111 return NULL;
00112
00113 geo = find_geo_in_pos(rdman, x, y, in_stroke);
00114 if(geo == NULL)
00115 return NULL;
00116
00117 return geo->shape;
00118 }