liberscribble/include/scbstroke.h File Reference

#include "scbcolor.h"
#include "scbpoints.h"
#include "scbtype.h"
#include "scbxml.h"
#include <glib.h>

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _ScbStrokeStyle
struct  _ScbStroke
struct  _ScbHitTestCtx

Typedefs

typedef struct _ScbStrokeStyle ScbStrokeStyle
typedef ScbStrokeStyleScbStrokeStylePtr
typedef struct _ScbStroke ScbStroke
typedef ScbStrokeScbStrokePtr
typedef struct _ScbHitTestCtx ScbHitTestCtx
typedef ScbHitTestCtxScbHitTestCtxPtr

Functions

ScbStrokePtr scb_stroke_new ()
ScbStrokePtr scb_stroke_new_with_style (ScbStrokeStylePtr ptr)
void scb_stroke_free (ScbStrokePtr stroke)
int scb_stroke_get_point_count (ScbStrokePtr stroke)
ScbPointPtr scb_stroke_get_point_data (ScbStrokePtr stroke)
int scb_stroke_add_point (ScbStrokePtr stroke, ScbDevPointPtr point)
void scb_stroke_fast_draw_point (ScbStrokePtr stroke, ScbDevPointPtr point)
void scb_stroke_fast_draw_point_done (ScbStrokePtr stroke, ScbDevPointPtr point)
void scb_stroke_fast_draw (ScbStrokePtr stroke)
gboolean scb_stroke_point_hit_test (ScbStrokePtr stroke, ScbDevPointPtr point, const ScbHitTestCtxPtr ctx)
gboolean scb_stroke_line_hit_test (ScbStrokePtr stroke, ScbDevPointPtr point1, ScbDevPointPtr point2, const ScbHitTestCtxPtr ctx)
void scb_stroke_set_color (ScbStrokePtr stroke, const ScbDevColor color)
ScbDevColor scb_stroke_get_color (ScbStrokePtr stroke)
gboolean scb_stroke_save (ScbStrokePtr stroke, ScbXmlPtr)
gboolean scb_stroke_load (ScbStrokePtr stroke, ScbXmlPtr)
void scb_stroke_dump (ScbStrokePtr ptr)


Typedef Documentation

typedef struct _ScbHitTestCtx ScbHitTestCtx

Definition at line 60 of file scbstroke.h.

typedef struct _ScbStroke ScbStroke

Definition at line 53 of file scbstroke.h.

Copyright (C) 2005-2008 iRex Technologies B.V. All rights reserved.

Definition at line 45 of file scbstroke.h.


Function Documentation

int scb_stroke_add_point ( ScbStrokePtr  stroke,
ScbDevPointPtr  point 
)

Definition at line 170 of file scbstroke.c.

00171 {
00172     SCB_RET_INT_IF(NULL == stroke, SCB_RET_ERR, "stroke pointer is NULL!");
00173     SCB_RET_INT_IF(NULL == point, SCB_RET_ERR, "Invalid point pointer!");
00174 
00175     // for debug. report points whose x or y is incorrect. 
00176     // It maybe not correct, the coordinates can be very large. 
00177 #if (SCB_DEBUG_ON)
00178     // if (point->x >=  1024 || point->y >= 1024)
00179     // {
00180         // SCB_WARN("Odd points found! (%d %d)", point->x, point->y);
00181     // }
00182 #endif 
00183 
00184     scb_points_append(&stroke->points, point);
00185     
00186     // adjust rectangle
00187     if (stroke->rect.left > point->x)
00188     {
00189         stroke->rect.left = point->x;
00190     }
00191     if (stroke->rect.right < point->x)
00192     {
00193         stroke->rect.right = point->x;
00194     }
00195 
00196     if (stroke->rect.top > point->y)
00197     {
00198         stroke->rect.top = point->y;
00199     }
00200     if (stroke->rect.bottom < point->y)
00201     {
00202         stroke->rect.bottom = point->y;
00203     }
00204     return SCB_RET_OK;
00205 }

Here is the call graph for this function:

void scb_stroke_dump ( ScbStrokePtr  ptr  ) 

Definition at line 624 of file scbstroke.c.

00625 {
00626     SCB_RET_IF(NULL == ptr || NULL == ptr->points.points, "");
00627     
00628     int count = ptr->points.points->len;
00629     ScbPointPtr p = (ScbPointPtr)ptr->points.points->data;
00630     int *pp = (int *)ptr->points.pressures->data;
00631     while(count > 0)
00632     {
00633         SCB_DUMP("\t(%d,\t%d,\t%d)", p->x, p->y, *pp);
00634         --count; ++ p; ++pp;
00635     }
00636 }

void scb_stroke_fast_draw ( ScbStrokePtr  stroke  ) 

Definition at line 299 of file scbstroke.c.

00300 {
00301     SCB_RET_IF(NULL == stroke || NULL == stroke->points.points, "NULL pointer!");
00302 
00303     // construct a temp PointsBufPtr, copy stroke data into points buf
00304     DrvPointsBuf tmp;
00305     gboolean end_of_stroke;
00306     int i = 0;
00307     int len = stroke->points.points->len;
00308     ScbPointPtr pt = (ScbPointPtr)stroke->points.points->data;
00309 
00310     // do nothing
00311     if (len < 0) return;
00312 
00313     // collect valid points
00314     tmp.count = 0;
00315 
00316     // construct the buffer
00317     end_of_stroke = FALSE;
00318     for(i = 0; i < len; ++i, ++pt)
00319     {
00320         // split stroke in smaller ones containing max. SCB_DEF_FAST_DRAW_BUF_LEN valid points
00321         if (   pt->x >= SCB_DEF_BOUNDARY_LEFT  &&  pt->x <= SCB_DEF_BOUNDARY_RIGHT 
00322             && pt->y >= SCB_DEF_BOUNDARY_TOP   &&  pt->y <= SCB_DEF_BOUNDARY_BOTTOM )
00323         {                    
00324             // valid point: add to stroke to be drawn
00325             tmp.points[tmp.count].x = pt->x;
00326             tmp.points[tmp.count].y = pt->y;
00327             tmp.points[tmp.count].size = stroke->style.penSize;
00328             tmp.points[tmp.count].pen_down = TRUE;
00329             tmp.points[tmp.count].color = stroke->style.color;
00330             ++tmp.count;
00331             if (   i         >= len - 1
00332                 || tmp.count >= SCB_DEF_FAST_DRAW_BUF_LEN)
00333             {
00334                 end_of_stroke = TRUE;
00335             }
00336         }                
00337         else
00338         { 
00339             // invalid point: end stroke to be drawn, if any
00340             if (tmp.count > 0)
00341             {
00342                 end_of_stroke = TRUE;
00343             }
00344         }
00345 
00346         // draw the valid (sub)stroke as needed
00347         if (end_of_stroke)
00348         {
00349             // force pen_up for last point of stroke
00350             tmp.points[tmp.count - 1].pen_down = FALSE;                
00351             scb_driver_draw(&tmp);
00352             tmp.count = 0;
00353             end_of_stroke = FALSE;
00354         }
00355     }
00356 }

Here is the call graph for this function:

void scb_stroke_fast_draw_point ( ScbStrokePtr  stroke,
ScbDevPointPtr  point 
)

Definition at line 255 of file scbstroke.c.

00256 {
00257     SCB_RET_IF(NULL == stroke || NULL == point, "NULL storke or point!");
00258         
00259     if (scb_fast_draw_now())
00260     {
00261         // draw it right now
00262         scb_fast_draw();
00263 
00264         // reset
00265         scb_fast_draw_reset_context();
00266     }
00267 
00268     // record this point
00269     scb_fast_draw_record(point, 
00270         stroke->style.penSize, 
00271         stroke->style.color, 
00272         TRUE);
00273 }

Here is the call graph for this function:

void scb_stroke_fast_draw_point_done ( ScbStrokePtr  stroke,
ScbDevPointPtr  point 
)

Definition at line 279 of file scbstroke.c.

00280 {
00281     SCB_RET_IF(NULL == stroke || NULL == point, "NULL storke or point!");
00282         
00283     // add the last point 
00284     scb_fast_draw_record(point, 
00285         stroke->style.penSize,
00286         stroke->style.color,
00287         FALSE);
00288 
00289     // fast draw 
00290     scb_fast_draw();
00291 
00292     // reset
00293     scb_fast_draw_reset_context();
00294 }

Here is the call graph for this function:

void scb_stroke_free ( ScbStrokePtr  stroke  ) 

Definition at line 158 of file scbstroke.c.

00159 {
00160     SCB_RET_IF(NULL == stroke, "Attempt to release NULL pointer!");
00161     if (stroke->points.points)
00162     {
00163         scb_points_free(&stroke->points);
00164     }
00165     g_free(stroke);
00166 }

Here is the call graph for this function:

ScbDevColor scb_stroke_get_color ( ScbStrokePtr  stroke  ) 

Definition at line 612 of file scbstroke.c.

00613 {
00614     if (NULL == stroke)
00615     {
00616         return SCB_DEV_COLOR_UNKNOWN;
00617     }
00618     return stroke->style.color;
00619 }

int scb_stroke_get_point_count ( ScbStrokePtr  stroke  ) 

Definition at line 208 of file scbstroke.c.

00209 {
00210     SCB_RET_INT_IF(NULL == stroke || NULL == stroke->points.points, SCB_INVALID_COUNT, "Invalid pointer(s)!");
00211     return stroke->points.points->len;
00212 }

ScbPointPtr scb_stroke_get_point_data ( ScbStrokePtr  stroke  ) 

Definition at line 216 of file scbstroke.c.

00217 {
00218     SCB_RET_NULL_IF(NULL == stroke, "Invalid pointer!");
00219     return scb_points_get_data(&stroke->points);
00220 }

Here is the call graph for this function:

gboolean scb_stroke_line_hit_test ( ScbStrokePtr  stroke,
ScbDevPointPtr  point1,
ScbDevPointPtr  point2,
const ScbHitTestCtxPtr  ctx 
)

Definition at line 413 of file scbstroke.c.

00417 {
00418     SCB_RET_FALSE_IF(NULL == stroke || NULL == point1 || NULL == point2 || NULL == ctx, 
00419         "Invalid pointer(s)!");
00420 
00421     // fast check
00422     ScbRect tmp; 
00423     double ratio = 1.0;
00424     ScbDevPoint p1, p2;
00425     if (fabs(stroke->style.zoom - ctx->zoom) >= e)
00426     {
00427         ratio = stroke->style.zoom / ctx->zoom;
00428         p1.x = (int)point1->x * ratio; p1.y = (int)point1->y * ratio;
00429         p2.x = (int)point2->x * ratio; p2.y = (int)point2->y * ratio;
00430     }
00431     else
00432     {
00433         p1 = *point1; p2 = *point2;
00434     }
00435 
00436 
00437     tmp.left    = MIN(p1.x, p2.x) - ctx->size;
00438     tmp.right   = MAX(p1.x, p2.x) + ctx->size;
00439     tmp.top     = MIN(p1.y, p2.y) - ctx->size;
00440     tmp.bottom  = MAX(p1.y, p2.y) + ctx->size;
00441     if (!scb_is_rect_intersect(&stroke->rect, &tmp))
00442     {
00443         return FALSE;
00444     }
00445 
00446     // check each line segment in stroke
00447     int len = stroke->points.points->len;
00448     ScbPointPtr begin = (ScbPointPtr)stroke->points.points->data;
00449     ScbPointPtr end   = begin;
00450 
00451     // only one point
00452     if (len == 1)
00453     {
00454         if (scb_is_lines_intersect((ScbPointPtr)&p1, (ScbPointPtr)&p2, begin, end))
00455         {
00456 #if (SCB_DEBUG_ON)
00457             SCB_TRACE("one point hit!");
00458             SCB_TRACE("line in stroke: (%d %d) - (%d %d)", 
00459                 begin->x, begin->y, end->x, end->y);
00460             SCB_TRACE("user line: (%d %d) - (%d %d)",
00461                 p1.x, p1.y, p2.x, p2.y);
00462 #endif
00463             return TRUE;
00464         }
00465         return FALSE;
00466     }
00467 
00468     // others
00469     while (len > 1)
00470     {
00471         ++end;
00472         if (scb_is_lines_intersect((ScbPointPtr)&p1, (ScbPointPtr)&p2, begin, end))
00473         {
00474             // for debug
00475 #if (SCB_DEBUG_ON)
00476             SCB_TRACE("line in stroke: (%d %d) - (%d %d)", 
00477                 begin->x, begin->y, end->x, end->y);
00478             SCB_TRACE("user line: (%d %d) - (%d %d)",
00479                 p1.x, p1.y, p2.x, p2.y);
00480 #endif
00481             return TRUE;
00482         }
00483         begin = end; --len;
00484     }
00485     return FALSE;
00486 }

Here is the call graph for this function:

gboolean scb_stroke_load ( ScbStrokePtr  stroke,
ScbXmlPtr   
)

Definition at line 545 of file scbstroke.c.

00546 {
00547     // check
00548     SCB_RET_FALSE_IF(NULL == stroke || NULL == ptr, "Invalid pointer!");
00549         
00550     // construct xpath
00551     char xPath[SCB_MAX_XML_PATH] = {0};
00552     strncpy(xPath, ptr->xPath, SCB_MAX_XML_PATH);
00553     char * addr = xPath + strnlen(xPath, SCB_MAX_XML_PATH);
00554     snprintf(addr, SCB_MAX_XML_PATH, "/stroke[%d]", ptr->index);
00555     // SCB_TRACE("xPath %s", xPath);
00556     
00557     // read attributes
00558     const int MAX_BUF_LEN = SCB_MAX_XML_PATH;
00559     char buf[SCB_MAX_XML_PATH] = {0};
00560     ermXmlGetAttributeString(&ptr->handle, xPath, "color", buf, MAX_BUF_LEN);
00561     stroke->style.color = scb_html_color_to_dev_color(buf, MAX_BUF_LEN);
00562     ermXmlGetAttributeInt(&ptr->handle, xPath, "layer", &stroke->style.layer);
00563     ermXmlGetAttributeInt(&ptr->handle, xPath, "penSize", (int *)&stroke->style.penSize);
00564     ermXmlGetAttributeString(&ptr->handle, xPath, "linestyle", buf, MAX_BUF_LEN);
00565     stroke->style.lineStyle = scb_line_style_from_str(buf);
00566     ermXmlGetAttributeString(&ptr->handle, xPath, "zoom", buf, MAX_BUF_LEN);
00567     sscanf(buf, "%lf", &stroke->style.zoom);
00568 
00569     // read stroke data from stroke node
00570     int len = 0;
00571     const char *data  = ermXmlGetStringBuffer(&ptr->handle, xPath, &len);
00572     addr = (char *)data;           // remember the address
00573     if (len <= 0 || NULL == data)
00574     {
00575 #if (SCB_DEBUG_ON)
00576         // in fact, it's not an error. when no data could read, just return false
00577         // SCB_TRACE("No data in this stroke!");
00578 #endif
00579         return FALSE;
00580     }
00581 
00582     // here, we assume that the xmlchar is zero terminated
00583     ScbDevPoint point;
00584     while (data && 0 != *data)
00585     {
00586         if (3 != sscanf(data, "%d %d %d", &point.x, &point.y, &point.pressure))
00587         {
00588             break;
00589         }            
00590 
00591         scb_stroke_add_point(stroke, &point);
00592         data = strchr(data, '\n');              // to next begin
00593         if (NULL == data)
00594         {
00595             SCB_ERROR("Could not find new line!");
00596             ermXmlFreeStringBuffer(addr);
00597             return FALSE;
00598         }
00599         ++data;
00600     }
00601     ermXmlFreeStringBuffer(addr);
00602     return TRUE;
00603 }

Here is the call graph for this function:

ScbStrokePtr scb_stroke_new (  ) 

Definition at line 97 of file scbstroke.c.

00098 {
00099     ScbStrokePtr ptr = g_new0(ScbStroke, 1);
00100     SCB_RET_NULL_IF(NULL == ptr, "Not enough memory for stroke!");
00101     
00102     // allocate points array
00103     if (!scb_points_new(&ptr->points, SCB_DEF_STROKE_POINTSIZE))
00104     {
00105         // could not alloc memory for list
00106         g_free(ptr);
00107         return NULL;
00108     }
00109 
00110     // init the stroke paramters
00111     ptr->style.color     = SCB_DEV_COLOR_BLACK;
00112     ptr->style.layer     = SCB_DEF_STROKE_LAYER;
00113     ptr->style.lineStyle = SCB_DEF_STROKE_LINESTYLE;
00114     ptr->style.penSize   = SCB_DEF_STROKE_PENSIZE;
00115 
00116     // init out bound rect. used to fast hit test
00117     ptr->rect.left   = INT_MAX;
00118     ptr->rect.top    = INT_MAX;
00119     ptr->rect.right  = INT_MIN;
00120     ptr->rect.bottom = INT_MIN;
00121 
00122     // init fast draw context 
00123     scb_fast_draw_reset_context();
00124     return ptr;
00125 }

Here is the call graph for this function:

ScbStrokePtr scb_stroke_new_with_style ( ScbStrokeStylePtr  ptr  ) 

Definition at line 127 of file scbstroke.c.

00128 {
00129     SCB_RET_NULL_IF(NULL == pStyle, "Invalid pointer!");
00130 
00131     ScbStrokePtr ptr = g_new0(ScbStroke, 1);
00132     SCB_RET_NULL_IF(NULL == ptr, "Not enough memory for stroke!");
00133     
00134     // allocate points array
00135     if (!scb_points_new(&ptr->points, SCB_DEF_STROKE_POINTSIZE))
00136     {
00137         // could not alloc memory for list
00138         g_free(ptr);
00139         return NULL;
00140     }
00141 
00142     // init the stroke paramters
00143     ptr->style  = *pStyle;
00144 
00145     // init out bound rect. used to fast hit test
00146     ptr->rect.left   = INT_MAX;
00147     ptr->rect.top    = INT_MAX;
00148     ptr->rect.right  = INT_MIN;
00149     ptr->rect.bottom = INT_MIN;
00150 
00151     // init fast draw context 
00152     scb_fast_draw_reset_context();
00153     return ptr;
00154 }

Here is the call graph for this function:

gboolean scb_stroke_point_hit_test ( ScbStrokePtr  stroke,
ScbDevPointPtr  point,
const ScbHitTestCtxPtr  ctx 
)

Definition at line 362 of file scbstroke.c.

00365 {
00366     SCB_RET_FALSE_IF(NULL == stroke || NULL == point || NULL == ctx, 
00367         "Invalid pointer(s)!");
00368 
00369     // fast check
00370     ScbRect tmp; 
00371     double ratio = 1.0;
00372     if (fabs(stroke->style.zoom - ctx->zoom) >= e)
00373     {
00374         ratio = stroke->style.zoom / ctx->zoom;
00375     }
00376     tmp.left    = point->x * ratio - ctx->size;
00377     tmp.right   = point->x * ratio + ctx->size;
00378     tmp.top     = point->y * ratio - ctx->size;
00379     tmp.bottom  = point->y * ratio + ctx->size;
00380     if (!scb_is_rect_intersect(&stroke->rect, &tmp))
00381     {
00382         return FALSE;
00383     }
00384 
00385     // check each point in stroke
00386     ScbRect src;
00387     int size = stroke->style.penSize;
00388     int len = stroke->points.points->len;
00389     ScbPointPtr pts = (ScbPointPtr)stroke->points.points->data;
00390     while (len)
00391     {
00392         src.left    = pts->x - size;
00393         src.right   = pts->x + size;
00394         src.top     = pts->y - size;
00395         src.bottom  = pts->y + size;
00396         if (scb_is_rect_intersect(&src, &tmp))
00397         {
00398 #if (SCB_DEBUG_ON)
00399             SCB_TRACE("\nrect1: (%d %d %d %d)\nrect2: (%d %d %d %d)",
00400                 src.left, src.top, src.right, src.bottom,
00401                 tmp.left, tmp.top, tmp.right, tmp.bottom);
00402 #endif
00403             return TRUE;
00404         }
00405         ++pts; --len;
00406     }
00407     return FALSE;
00408 }

Here is the call graph for this function:

gboolean scb_stroke_save ( ScbStrokePtr  stroke,
ScbXmlPtr   
)

Definition at line 496 of file scbstroke.c.

00497 {
00498     // construct xpath
00499     char xPath[SCB_MAX_XML_PATH] = {0};
00500     strncpy(xPath, ptr->xPath, SCB_MAX_XML_PATH);
00501     strncat(xPath, "/stroke", SCB_MAX_XML_PATH);
00502     snprintf(xPath, SCB_MAX_XML_PATH, "%s/stroke[%d]", ptr->xPath, ptr->index);
00503     // SCB_TRACE("xPath: %s", xPath);
00504     
00505     // create node, construct data, from stroke data to string
00506     const int LINE_BYTES = 33; // 2147483647 2147483647 2147483647\n
00507     int count = scb_stroke_get_point_count(stroke);
00508     if (count)
00509     {
00510         int len = LINE_BYTES * count;
00511         char *buf = g_new0(char, len);
00512         if (NULL == buf) return FALSE;
00513         char *tmp = buf;
00514         ScbPointPtr point = (ScbPointPtr)stroke->points.points->data;
00515         int* ppressure = (int *)stroke->points.pressures->data;
00516         // write information into buf
00517         while (count > 0)
00518         {
00519             tmp += snprintf(tmp, LINE_BYTES, "%d %d %d\n", 
00520                     point->x, point->y, *ppressure);
00521             --count; ++point; ++ppressure;
00522         }            
00523         ermXmlNewString(&ptr->handle, ptr->xPath, "stroke", buf);
00524         g_free(buf);
00525     }
00526 
00527     // set attributes
00528     ermXmlSetAttributeString(&ptr->handle, xPath, "color", 
00529         scb_dev_color_to_html_color(stroke->style.color), SCB_MAX_COLOR_LEN);
00530     ermXmlSetAttributeInt(&ptr->handle, xPath, "layer", stroke->style.layer);
00531     ermXmlSetAttributeInt(&ptr->handle, xPath, "penSize", stroke->style.penSize);
00532     ermXmlSetAttributeString(&ptr->handle, xPath, "linestyle", 
00533         scb_line_style_to_str(stroke->style.lineStyle), SCB_MAX_XML_PATH);
00534     // zoom factor
00535     char tmp[20] = {0}; snprintf(tmp, 20, "%lf", stroke->style.zoom);
00536     ermXmlSetAttributeString(&ptr->handle, xPath, "zoom", 
00537         tmp, SCB_MAX_XML_PATH);
00538 
00539     return TRUE;
00540 }

Here is the call graph for this function:

void scb_stroke_set_color ( ScbStrokePtr  stroke,
const ScbDevColor  color 
)

Definition at line 605 of file scbstroke.c.

00606 {
00607     SCB_RET_IF(NULL == stroke, "Invalid pointer!");
00608     stroke->style.color = color;
00609 }


Generated on Sun Dec 14 17:15:04 2008 by  doxygen 1.5.6