00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "ScribbleMgr.h"
00020 #include "GtkMgr.h"
00021 #include "controller.h"
00022 #include "Settings.h"
00023 #include "PDFViewerLog.h"
00024 #include "utils.h"
00025 #include <math.h>
00026
00027 static const double e = 0.001;
00028
00029 CScribbleMgr::CScribbleMgr(void)
00030 : doc(NULL)
00031 , page(NULL)
00032 , stroke(NULL)
00033 , pageNumber(-1)
00034 , bErased(gFalse)
00035 , bScbDirty(gFalse)
00036 {
00037 scb_init();
00038 }
00039
00040 CScribbleMgr::~CScribbleMgr(void)
00041 {
00042 scb_uninit();
00043 }
00044
00046
00047 void CScribbleMgr::open(const char *dirName)
00048 {
00049 close();
00050
00051
00052 if (NULL == dirName) return;
00053 strncpy(path.scbname, dirName, SCB_MAX_PATH);
00054 char *pos = strrchr(path.scbname, '/');
00055 strcpy(++pos, "scribble.irx");
00056 pos += strlen("scribble.irx");
00057 *pos = 0;
00058
00059
00060 doc = scb_doc_make_sure_exist(&path);
00061 }
00062
00063 void CScribbleMgr::close(GBool bSave)
00064 {
00065 if (doc && bSave && isScbDirty())
00066 {
00067 PV_SCBPRINTF("Save scribble now!");
00068 scb_doc_save(doc);
00069 }
00070 scb_doc_free(doc);
00071 doc = NULL;
00072 memset(&path, 0, sizeof(path));
00073 page = NULL;
00074 stroke = NULL;
00075 setScbDirty(gFalse);
00076 }
00077
00078 void CScribbleMgr::setScbDirty(const GBool b)
00079 {
00080 bScbDirty = b;
00081 }
00082
00083 void CScribbleMgr::save()
00084 {
00085 if (doc && isScbDirty())
00086 {
00087 PV_SCBPRINTF("Save scribble now!");
00088 scb_doc_save(doc);
00089 }
00090 setScbDirty(gFalse);
00091 }
00092
00093 void CScribbleMgr::generatePageId(ScbPageIdPtr pid, const int pn)
00094 {
00095 snprintf(pid->id, SCB_MAX_PAGEID_LEN, "%d", pn);
00096 }
00097
00098 void CScribbleMgr::beginStroke(const int pn, Controller * ctrl,
00099 const int px, const int py,
00100 const int x, const int y,
00101 const int ox, const int oy)
00102 {
00103 PV_SCBPRINTF("Create new stroke!");
00104
00105
00106 pageNumber = pn;
00107 pagePoint.x = px;
00108 pagePoint.y = py;
00109
00110
00111 generatePageId(&id, pn);
00112 page = scb_doc_get_page(doc, &id);
00113 if (NULL == page)
00114 {
00115
00116 page = scb_page_new();
00117 scb_page_set_id(page, &id);
00118 page->style.orientation = ctrl->settings.getRotate();
00119 }
00120
00121
00122 if (NULL == stroke)
00123 {
00124 stroke = scb_stroke_new_with_style(scb_doc_get_current_stroke_style(doc));
00125 stroke->style.zoom = ctrl->calZoom(ctrl->settings.getCurrentPage());
00126 ScbStrokesPtr strokes = scb_page_get_strokes(page);
00127 scb_strokes_add_stroke(strokes, stroke);
00128 }
00129
00130
00131 point.x = ox;
00132 point.y = oy;
00133 point.pressure = 0;
00134 scb_stroke_add_point(stroke, &point);
00135
00136
00137 point.x = x;
00138 point.y = y;
00139 scb_stroke_fast_draw_point(stroke, &point);
00140
00141
00142 setScbDirty();
00143 }
00144
00145 void CScribbleMgr::addPoint(const int pn, Controller * ctrl,
00146 const int px, const int py,
00147 const int x, const int y,
00148 const int ox, const int oy)
00149 {
00150 point.x = ox;
00151 point.y = oy;
00152 scb_stroke_add_point(stroke, &point);
00153
00154 point.x = x;
00155 point.y = y;
00156 scb_stroke_fast_draw_point(stroke, &point);
00157
00158
00159 setScbDirty();
00160 }
00161
00162 void CScribbleMgr::endStroke(const int pn, Controller * ctrl,
00163 const int px, const int py,
00164 const int x, const int y,
00165 const int ox, const int oy)
00166 {
00167 PV_SCBPRINTF("End stroke!");
00168
00169
00170 point.x = ox;
00171 point.y = oy;
00172 scb_stroke_add_point(stroke, &point);
00173
00174
00175 point.x = x;
00176 point.y = y;
00177 scb_stroke_fast_draw_point_done(stroke, &point);
00178
00179
00180 drawStroke(stroke, ctrl, px, py);
00181
00182
00183 scb_doc_add_page(doc, page);
00184 page = NULL;
00185 stroke = NULL;
00186 pageNumber = -1;
00187
00188
00189 setScbDirty();
00190 }
00191
00192
00193 void CScribbleMgr::endStroke(Controller * ctrl,
00194 const int px, const int py,
00195 const int x, const int y)
00196 {
00197
00198 point.x = x;
00199 point.y = y;
00200 scb_stroke_fast_draw_point_done(stroke, &point);
00201
00202
00203 drawStroke(stroke, ctrl, px, py);
00204
00205
00206 scb_doc_add_page(doc, page);
00207 page = NULL;
00208 stroke = NULL;
00209 pageNumber = -1;
00210 }
00211
00212 void CScribbleMgr::onScribblePress(const int pn, Controller * ctrl,
00213 const int px, const int py,
00214 const int x, const int y,
00215 const int ox, const int oy)
00216 {
00217 if (pn > 0 && page && stroke)
00218 {
00219 addPoint(pn, ctrl, px, py, x, y, ox, oy);
00220 return;
00221 }
00222
00223 if (pn > 0 && NULL == page && NULL == stroke)
00224 {
00225 beginStroke(pn, ctrl, px, py, x, y, ox, oy);
00226 }
00227 }
00228
00230
00231
00232
00233 void CScribbleMgr::onScribbleMove(const int pn, Controller * ctrl,
00234 const int px, const int py,
00235 const int x, const int y,
00236 const int ox, const int oy)
00237 {
00238
00239 if (pn < 0 && stroke && page)
00240 {
00241
00242 endStroke(ctrl, pagePoint.x, pagePoint.y, x, y);
00243 return;
00244 }
00245
00246
00247 if (pn > 0 && stroke == NULL && page == NULL)
00248 {
00249 beginStroke(pn, ctrl, px, py, x, y, ox, oy);
00250 return;
00251 }
00252
00253
00254 if (pn > 0 && pageNumber > 0 && pn != pageNumber && stroke && page)
00255 {
00256 endStroke(ctrl, pagePoint.x, pagePoint.y, x, y);
00257 beginStroke(pn, ctrl, px, py, x, y, ox, oy);
00258 return;
00259 }
00260
00261
00262 if (stroke)
00263 {
00264 addPoint(pn, ctrl, px, py, x, y, ox, oy);
00265 }
00266 }
00267
00268 void CScribbleMgr::onScribbleRelease(const int pn, Controller * ctrl,
00269 const int px, const int py,
00270 const int x, const int y,
00271 const int ox, const int oy)
00272 {
00273 if (pn > 0 && stroke && doc && page)
00274 {
00275 endStroke(pn, ctrl, px, py, x, y, ox, oy);
00276 }
00277 }
00278
00279 void CScribbleMgr::setEraseDirty(GBool b)
00280 {
00281 bErased = b;
00282 if (b)
00283 {
00284 setScbDirty();
00285 }
00286 }
00287
00289
00290 void CScribbleMgr::onErasePress(const int pn, Controller * ctrl,
00291 const int x, const int y,
00292 const int ox, const int oy)
00293 {
00294 if (pn < 0) return;
00295 scb_page_erase_init(&eraseCtx);
00296 generatePageId(&id, pn);
00297 page = scb_doc_get_page(doc, &id);
00298 if (NULL == page) return;
00299
00300
00301 pageNumber = pn;
00302 point.x = ox; point.y = oy;
00303 eraseCtx.zoom = ctrl->calZoom(ctrl->settings.getCurrentPage());
00304 ScbStrokesPtr strokes = scb_page_erase_hit_test(page, &point, &eraseCtx);
00305 if (strokes)
00306 {
00307 PV_LOGPRINTF("Erase strokes!");
00308
00309
00310 if (ctrl->settings.getRotate() == 270)
00311 {
00312 drawErasedStrokesLandscape(strokes, ctrl, x, y);
00313 }
00314 else
00315 {
00316 drawErasedStrokesPortrait(strokes, ctrl, x, y);
00317 }
00318
00319
00320 setEraseDirty();
00321
00322
00323 scb_strokes_free(strokes);
00324 }
00325 }
00326
00327 void CScribbleMgr::onEraseMove(const int pn, Controller * ctrl,
00328 const int x, const int y,
00329 const int ox, const int oy)
00330 {
00331 if (pn < 0) return;
00332 if (pageNumber != pn)
00333 {
00334 pageNumber = pn;
00335 scb_page_erase_init(&eraseCtx);
00336 eraseCtx.zoom = ctrl->calZoom(ctrl->settings.getCurrentPage());
00337 }
00338
00339 generatePageId(&id, pn);
00340 page = scb_doc_get_page(doc, &id);
00341 if (NULL == page) return;
00342
00343 point.x = ox; point.y = oy;
00344
00345 ScbStrokesPtr strokes = scb_page_erase_hit_test(page, &point, &eraseCtx);
00346 if (strokes)
00347 {
00348 PV_LOGPRINTF("Erase strokes!");
00349 if (ctrl->settings.getRotate() == 270)
00350 {
00351 drawErasedStrokesLandscape(strokes, ctrl, x, y);
00352 }
00353 else
00354 {
00355 drawErasedStrokesPortrait(strokes, ctrl, x, y);
00356 }
00357
00358
00359 setEraseDirty();
00360
00361
00362 scb_strokes_free(strokes);
00363 }
00364 }
00365
00366 void CScribbleMgr::onEraseRelease(const int pn, Controller * ctrl,
00367 const int x, const int y,
00368 const int ox, const int oy)
00369 {
00370 if (pn < 0 || NULL == page) return;
00371 point.x = ox; point.y = oy;
00372 ScbStrokesPtr strokes = scb_page_erase_hit_test(page, &point, &eraseCtx);
00373
00374
00375 page = NULL;
00376 if (strokes)
00377 {
00378 PV_LOGPRINTF("Erase strokes!");
00379 if (ctrl->settings.getRotate() == 270)
00380 {
00381 drawErasedStrokesLandscape(strokes, ctrl, x, y);
00382 }
00383 else
00384 {
00385 drawErasedStrokesPortrait(strokes, ctrl, x, y);
00386 }
00387
00388
00389 setEraseDirty();
00390
00391
00392 scb_strokes_free(strokes);
00393 }
00394 }
00395
00397
00398 void CScribbleMgr::drawScribblePage(const int pn, Controller * ctrl,
00399 const int x, const int y)
00400 {
00401 #if (PV_PROFILE_ON)
00402 int t1 = ctrl->getHighTimeStamp();
00403 #endif
00404
00405
00406 generatePageId(&id, pn);
00407 ScbPagePtr ptr = scb_doc_get_page(doc, &id);
00408 if (NULL == ptr)
00409 {
00410 PV_LOGPRINTF("page %s not found!", id.id);
00411 return;
00412 }
00413
00414 if (ctrl->settings.getRotate() == 270)
00415 {
00416 drawScribblePageLandscape(ptr, ctrl, x, y);
00417 }
00418 else
00419 {
00420 drawScribblePagePortrait(ptr, ctrl, x, y);
00421 }
00422
00423 #if (PV_PROFILE_ON)
00424 int t2 = ctrl->getHighTimeStamp();
00425 PV_DUMP("Scribble Manager drawScribblePage uses %d\n", t2 - t1);
00426 #endif
00427 }
00428
00429
00430 int CScribbleMgr::calLineSize(const int penSize, const double strokeZoom, const double dispZoom)
00431 {
00432 if (fabs(strokeZoom - dispZoom) < e)
00433 {
00434 return penSize;
00435 }
00436 int ret = (int)(penSize * strokeZoom / dispZoom);
00437 if (ret < 1) return 1;
00438 if (ret > 10) return 10;
00439 return ret;
00440 }
00441
00442 void CScribbleMgr::drawScribblePagePortrait(ScbPagePtr ptr, Controller * ctrl,
00443 const int x, const int y)
00444 {
00445 ScbStrokesPtr strokes = scb_page_get_strokes(ptr);
00446 double z = ctrl->calZoom(ctrl->settings.getCurrentPage());
00447 if (strokes)
00448 {
00449 ScbStrokePtr stroke = NULL;
00450 GList *ptr = g_list_first(strokes->strokes);
00451 while (ptr)
00452 {
00453 stroke = (ScbStrokePtr)ptr->data;
00454 if (stroke)
00455 {
00456
00457 int count = scb_stroke_get_point_count(stroke);
00458 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00459
00460
00461 ScbColor color;
00462 scb_dev_color_to_color(&color, stroke->style.color);
00463 ctrl->gtkMgr.setLineColor(color.pixel);
00464
00465
00466 ctrl->gtkMgr.setLineAttributes(
00467 calLineSize(stroke->style.penSize,
00468 z, stroke->style.zoom));
00469
00470
00471 if (fabs(z - stroke->style.zoom) < e)
00472 {
00473 int i = 0;
00474 int x1 = x + pts[i].x, y1 = y + pts[i].y; ++i;
00475 int x2, y2;
00476 while (i < count)
00477 {
00478 x2 = x + pts[i].x, y2 = y + pts[i].y; ++i;
00479 ctrl->gtkMgr.drawLine(x1, y1, x2, y2);
00480 x1 = x2; y1 = y2;
00481 }
00482
00483 if (count <= 1)
00484 {
00485 ctrl->gtkMgr.drawLine(x1, y1, x1, y1);
00486 }
00487 }
00488 else
00489 {
00490 double ratio = z / stroke->style.zoom;
00491 int i = 0;
00492 int x1 = x + (int)(ratio * pts[i].x), y1 = y + (int)(ratio * pts[i].y); ++i;
00493 int x2, y2;
00494 while (i < count)
00495 {
00496 x2 = x + (int)(ratio * pts[i].x); y2 = y + (int)(ratio * pts[i].y); ++i;
00497 ctrl->gtkMgr.drawLine(x1, y1, x2, y2);
00498 x1 = x2; y1 = y2;
00499 }
00500
00501 if (count <= 1)
00502 {
00503 ctrl->gtkMgr.drawLine(x1, y1, x1, y1);
00504 }
00505 }
00506 }
00507 ptr = g_list_next(ptr);
00508 }
00509 }
00510 }
00511
00512 void CScribbleMgr::drawScribblePageLandscape(ScbPagePtr ptr, Controller * ctrl,
00513 const int x, const int y)
00514 {
00515 ScbStrokesPtr strokes = scb_page_get_strokes(ptr);
00516 double z = ctrl->calZoom(ctrl->settings.getCurrentPage());
00517 if (strokes)
00518 {
00519 ScbStrokePtr stroke = NULL;
00520 GList *ptr = g_list_first(strokes->strokes);
00521 while (ptr)
00522 {
00523 stroke = (ScbStrokePtr)ptr->data;
00524 if (stroke)
00525 {
00526
00527 int count = scb_stroke_get_point_count(stroke);
00528 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00529
00530
00531 ScbColor color;
00532 scb_dev_color_to_color(&color, stroke->style.color);
00533 ctrl->gtkMgr.setLineColor(color.pixel);
00534
00535
00536 ctrl->gtkMgr.setLineAttributes(
00537 calLineSize(stroke->style.penSize,
00538 z, stroke->style.zoom));
00539
00540
00541 if (fabs(z - stroke->style.zoom) < e)
00542 {
00543 int i = 0;
00544 int x1 = y - pts[i].x, y1 = x + pts[i].y; ++i;
00545 int x2, y2;
00546 while (i < count)
00547 {
00548 x2 = y - pts[i].x, y2 = x + pts[i].y; ++i;
00549 ctrl->gtkMgr.drawLine(y1, x1, y2, x2);
00550 x1 = x2; y1 = y2;
00551 }
00552
00553
00554 if (1 >= count)
00555 {
00556 ctrl->gtkMgr.drawLine(y1, x1, y1, x1);
00557 }
00558 }
00559 else
00560 {
00561 double ratio = z / stroke->style.zoom;
00562 int i = 0;
00563 int x1 = y - (int)(ratio * pts[i].x), y1 = x + (int)(ratio * pts[i].y); ++i;
00564 int x2, y2;
00565 while (i < count)
00566 {
00567 x2 = y - (int)(ratio * pts[i].x), y2 = x + (int)(ratio * pts[i].y); ++i;
00568 ctrl->gtkMgr.drawLine(y1, x1, y2, x2);
00569 x1 = x2; y1 = y2;
00570 }
00571
00572
00573 if (1 >= count)
00574 {
00575 ctrl->gtkMgr.drawLine(y1, x1, y1, x1);
00576 }
00577 }
00578 }
00579 ptr = g_list_next(ptr);
00580 }
00581 }
00582 }
00583
00585
00586 void CScribbleMgr::drawErasedStrokesPortrait(ScbStrokesPtr strokes, Controller * ctrl,
00587 const int x, const int y)
00588 {
00589 double z = ctrl->calZoom(ctrl->settings.getCurrentPage());
00590 if (strokes)
00591 {
00592 ScbStrokePtr stroke = NULL;
00593 GList *ptr = g_list_first(strokes->strokes);
00594 while (ptr)
00595 {
00596 stroke = (ScbStrokePtr)ptr->data;
00597 if (stroke)
00598 {
00599
00600 int count = scb_stroke_get_point_count(stroke);
00601 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00602
00603
00604 if (fabs(z - stroke->style.zoom) < e)
00605 {
00606 int i = 0;
00607 while (i < count)
00608 {
00609 pts[i].x += x, pts[i].y += y; ++i;
00610 }
00611 }
00612 else
00613 {
00614 double ratio = z / stroke->style.zoom;
00615 int i = 0;
00616 while (i < count)
00617 {
00618 pts[i].x = x + (int)(pts[i].x * ratio);
00619 pts[i].y = y + (int)(pts[i].y * ratio);
00620 ++i;
00621 }
00622 }
00623 stroke->style.color = SCB_DEV_COLOR_WHITE;
00624 scb_stroke_fast_draw(stroke);
00625 drawStrokeDirectly(stroke, ctrl);
00626 }
00627 ptr = g_list_next(ptr);
00628 }
00629 }
00630 }
00631
00632 void CScribbleMgr::drawErasedStrokesLandscape(ScbStrokesPtr strokes, Controller * ctrl,
00633 const int x, const int y)
00634 {
00635 double z = ctrl->calZoom(ctrl->settings.getCurrentPage());
00636 if (strokes)
00637 {
00638 ScbStrokePtr stroke = NULL;
00639 GList *ptr = g_list_first(strokes->strokes);
00640 while (ptr)
00641 {
00642 stroke = (ScbStrokePtr)ptr->data;
00643 if (stroke)
00644 {
00645
00646 int count = scb_stroke_get_point_count(stroke);
00647 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00648
00649
00650 if (fabs(z - stroke->style.zoom) < e)
00651 {
00652 int i = 0;
00653 while (i < count)
00654 {
00655 pts[i].x = y - pts[i].x;
00656 pts[i].y = x + pts[i].y;
00657 swap(pts[i].x, pts[i].y);
00658 ++i;
00659 }
00660 }
00661 else
00662 {
00663 double ratio = z / stroke->style.zoom;
00664 int i = 0;
00665 while (i < count)
00666 {
00667 pts[i].x = y - (int)(pts[i].x * ratio);
00668 pts[i].y = x + (int)(pts[i].y * ratio);
00669 swap(pts[i].x, pts[i].y);
00670 ++i;
00671 }
00672 }
00673 stroke->style.color = SCB_DEV_COLOR_WHITE;
00674 scb_stroke_fast_draw(stroke);
00675 drawStrokeDirectly(stroke, ctrl);
00676 }
00677 ptr = g_list_next(ptr);
00678 }
00679 }
00680 }
00681
00682 void CScribbleMgr::drawStroke(ScbStrokePtr stroke, Controller * ctrl,
00683 const int px, const int py)
00684 {
00685 if (ctrl->settings.getRotate() == 0)
00686 {
00687
00688 int count = scb_stroke_get_point_count(stroke);
00689 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00690
00691
00692 ScbColor color;
00693 scb_dev_color_to_color(&color, stroke->style.color);
00694 ctrl->gtkMgr.setLineColor(color.pixel);
00695
00696
00697 ctrl->gtkMgr.setLineAttributes(stroke->style.penSize);
00698
00699 int i = 0;
00700 int x1 = px + pts[i].x, y1 = py + pts[i].y; ++i;
00701 int x2, y2;
00702
00703 while (i < count)
00704 {
00705 x2 = px + pts[i].x, y2 = py + pts[i].y; ++i;
00706 ctrl->gtkMgr.drawLine(x1, y1, x2, y2);
00707 x1 = x2; y1 = y2;
00708 }
00709
00710 if (count <= 1)
00711 {
00712 ctrl->gtkMgr.drawLine(x1, y1, x1, y1);
00713 }
00714 }
00715 else if (ctrl->settings.getRotate() == 270)
00716 {
00717
00718 int count = scb_stroke_get_point_count(stroke);
00719 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00720
00721
00722 ScbColor color;
00723 scb_dev_color_to_color(&color, stroke->style.color);
00724 ctrl->gtkMgr.setLineColor(color.pixel);
00725
00726
00727 ctrl->gtkMgr.setLineAttributes(stroke->style.penSize);
00728 int i = 0;
00729 int x1 = py - pts[i].x, y1 = px + pts[i].y; ++i;
00730 int x2, y2;
00731 while (i < count)
00732 {
00733 x2 = py - pts[i].x, y2 = px + pts[i].y; ++i;
00734 ctrl->gtkMgr.drawLine(y1, x1, y2, x2);
00735 x1 = x2; y1 = y2;
00736 }
00737
00738 if (count <= 1)
00739 {
00740 ctrl->gtkMgr.drawLine(y1, x1, y1, x1);
00741 }
00742 }
00743 }
00744
00745 void CScribbleMgr::drawStrokeDirectly(ScbStrokePtr stroke, Controller * ctrl)
00746 {
00747
00748 int count = scb_stroke_get_point_count(stroke);
00749 ScbPoint * pts = (ScbPoint *)scb_stroke_get_point_data(stroke);
00750
00751
00752 ScbColor color;
00753 scb_dev_color_to_color(&color, stroke->style.color);
00754 ctrl->gtkMgr.setLineColor(color.pixel);
00755
00756
00757 ctrl->gtkMgr.setLineAttributes(stroke->style.penSize);
00758
00759 for(int i = 0; i < count - 1; ++i)
00760 {
00761 ctrl->gtkMgr.drawLine(pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y);
00762 }
00763 }
00764
00765