00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include "scbstrokes.h"
00024 #include "scblog.h"
00025 #include "scbstroke.h"
00026
00027
00028
00029
00030 void _stroke_release(gpointer data, gpointer user_data)
00031 {
00032 if (data)
00033 {
00034 scb_stroke_free((ScbStrokePtr)data);
00035 }
00036 }
00037
00038 void _stroke_dump(gpointer data, gpointer user_data)
00039 {
00040 if (data)
00041 {
00042 scb_stroke_dump((ScbStrokePtr)data);
00043 }
00044 }
00045
00046
00047
00048
00049 gboolean scb_strokes_new(ScbStrokesPtr ptr)
00050 {
00051 SCB_RET_FALSE_IF(NULL == ptr, "Invalid pointer!");
00052 ptr->strokes = g_list_alloc();
00053 SCB_RET_FALSE_IF(NULL == ptr->strokes, "Could not allocate memory for list!");
00054 return TRUE;
00055 }
00056
00057
00058
00059 void scb_strokes_free(ScbStrokesPtr strokes)
00060 {
00061 SCB_RET_IF(NULL == strokes, "Attempt to release NULL pointer!");
00062
00063
00064 g_list_foreach(strokes->strokes, _stroke_release, NULL);
00065
00066
00067 g_list_free(strokes->strokes);
00068 strokes->strokes = NULL;
00069 }
00070
00071
00072 void scb_strokes_empty(ScbStrokesPtr strokes)
00073 {
00074 SCB_RET_IF(NULL == strokes, "Attempt to release NULL pointer!");
00075
00076 g_list_foreach(strokes->strokes, _stroke_release, NULL);
00077
00078
00079 g_list_free(strokes->strokes);
00080 strokes->strokes = g_list_alloc();
00081 }
00082
00083
00084 int scb_strokes_get_count(const ScbStrokesPtr strokes)
00085 {
00086 SCB_RET_INT_IF(NULL == strokes, SCB_INVALID_COUNT, "Invalid strokes pointer!");
00087
00088
00089 int len = g_list_length(strokes->strokes);
00090 if (len > 0)
00091 {
00092 return len - 1;
00093 }
00094 return SCB_INVALID_COUNT;
00095 }
00096
00097
00098
00099
00100 void scb_strokes_detach(ScbStrokesPtr strokes)
00101 {
00102 if (strokes)
00103 {
00104 g_list_free(strokes->strokes);
00105 strokes->strokes = NULL;
00106 }
00107
00108 }
00109
00110
00111
00112 void scb_strokes_add_stroke(ScbStrokesPtr strokes,
00113 ScbStrokePtr stroke)
00114 {
00115 SCB_RET_IF(NULL == strokes || NULL == stroke, "Invalid storkes or stroke pointer!");
00116 g_list_append(strokes->strokes, stroke);
00117 }
00118
00119 void scb_strokes_add_strokes(ScbStrokesPtr dst,
00120 const ScbStrokesPtr src)
00121 {
00122 SCB_RET_IF(NULL == dst || NULL == src, "Invalid pointer(s)!");
00123 g_list_concat(dst->strokes, src->strokes);
00124 }
00125
00126
00127
00128
00129 ScbStrokePtr scb_strokes_detach_stroke(ScbStrokesPtr strokes,
00130 ScbStrokePtr stroke)
00131 {
00132 SCB_RET_NULL_IF(NULL == strokes || NULL == stroke, "Invalid pointer!");
00133 g_list_remove(strokes->strokes, stroke);
00134 return stroke;
00135 }
00136
00137
00138
00139
00140 ScbStrokesPtr scb_strokes_point_hit_test(ScbStrokesPtr strokes,
00141 ScbDevPointPtr point,
00142 const ScbHitTestCtxPtr ctx)
00143 {
00144 SCB_RET_NULL_IF(NULL == strokes, "Invalid strokes list pointer!");
00145
00146 ScbStrokesPtr result = NULL;
00147 ScbStrokePtr stroke = NULL;
00148 GList* ptr = g_list_first(strokes->strokes);
00149 while(ptr)
00150 {
00151 stroke = (ScbStrokePtr)ptr->data;
00152 if (stroke && scb_stroke_point_hit_test(stroke, point, ctx))
00153 {
00154 SCB_TRACE("point hit");
00155 if (NULL == result)
00156 {
00157 result = g_new0(ScbStrokes, 1);
00158 if (! scb_strokes_new(result))
00159 {
00160 return NULL;
00161 }
00162 }
00163
00164 scb_strokes_add_stroke(result, stroke);
00165 scb_strokes_detach_stroke(strokes, stroke);
00166 }
00167 ptr = g_list_next(ptr);
00168 }
00169 return result;
00170 }
00171
00172
00173
00174 ScbStrokesPtr scb_strokes_line_hit_test(ScbStrokesPtr strokes,
00175 ScbDevPointPtr point1,
00176 ScbDevPointPtr point2,
00177 const ScbHitTestCtxPtr ctx)
00178 {
00179 SCB_RET_NULL_IF(NULL == strokes, "Invalid strokes list pointer!");
00180
00181 ScbStrokesPtr result = NULL;
00182 ScbStrokePtr stroke = NULL;
00183 GList* ptr = g_list_first(strokes->strokes);
00184 while(ptr)
00185 {
00186 stroke = ptr->data;
00187 if (stroke && scb_stroke_line_hit_test(stroke, point1, point2, ctx))
00188 {
00189 SCB_TRACE("line hit");
00190 if (NULL == result)
00191 {
00192 result = g_new0(ScbStrokes, 1);
00193 if (!scb_strokes_new(result))
00194 {
00195 return NULL;
00196 }
00197 }
00198
00199 scb_strokes_add_stroke(result, stroke);
00200 scb_strokes_detach_stroke(strokes, stroke);
00201 }
00202 ptr = g_list_next(ptr);
00203 }
00204 return result;
00205 }
00206
00207
00208 void scb_strokes_erase_fast_draw(ScbStrokesPtr strokes)
00209 {
00210 if (NULL == strokes)
00211 {
00212 return;
00213 }
00214
00215 GList *ptr = g_list_first(strokes->strokes);
00216 ScbStrokePtr stroke = NULL;
00217 while (ptr)
00218 {
00219 stroke = ptr->data;
00220 if (stroke)
00221 {
00222 ScbDevColor old = stroke->style.color;
00223
00224 stroke->style.color = SCB_DEV_COLOR_WHITE;
00225 scb_stroke_fast_draw(stroke);
00226 stroke->style.color = old;
00227 }
00228 ptr = g_list_next(ptr);
00229 }
00230 }
00231
00232
00233
00234
00235 void _stroke_save(gpointer data, gpointer user_data)
00236 {
00237 if (data && user_data)
00238 {
00239 ScbXmlPtr ptr = (ScbXmlPtr)user_data;
00240 scb_stroke_save((ScbStrokePtr)data, ptr);
00241 ++ptr->index;
00242 }
00243 }
00244
00245
00246 gboolean scb_strokes_save(ScbStrokesPtr strokes, ScbXmlPtr ptr)
00247 {
00248
00249 SCB_RET_FALSE_IF(NULL == strokes || NULL == ptr, "Invalid strokes or xml pointer!");
00250
00251
00252 ScbXmlPtr self = scb_xml_clone(ptr);
00253 ermXmlNewString(&self->handle, self->xPath, "strokes", "");
00254 strncat(self->xPath, "/strokes", SCB_MAX_XML_PATH);
00255 self->index = 1;
00256 g_list_foreach(strokes->strokes, _stroke_save, self);
00257 scb_xml_free(self);
00258 return TRUE;
00259 }
00260
00261
00262 gboolean scb_strokes_load(ScbStrokesPtr strokes, ScbXmlPtr ptr)
00263 {
00264
00265 SCB_RET_FALSE_IF(NULL == strokes || NULL == ptr, "Invalid strokes or xml pointer!");
00266
00267
00268
00269 scb_strokes_empty(strokes);
00270 ScbXmlPtr self = scb_xml_clone(ptr);
00271 strncat(self->xPath, "/strokes", SCB_MAX_XML_PATH);
00272 self->index = 1;
00273
00274 while(1)
00275 {
00276 ScbStrokePtr stroke = scb_stroke_new();
00277 if (scb_stroke_load(stroke, self))
00278 {
00279 scb_strokes_add_stroke(strokes, stroke);
00280 ++self->index;
00281 }
00282 else
00283 {
00284 scb_stroke_free(stroke);
00285 break;
00286 }
00287 }
00288 return TRUE;
00289 }
00290
00291
00292 void scb_strokes_dump(ScbStrokesPtr strokes)
00293 {
00294 if (strokes)
00295 {
00296 g_list_foreach(strokes->strokes, _stroke_dump, 0);
00297 }
00298 }