# # Patch managed by http://www.mn-logistik.de/unsupported/pxa250/patcher # --- FreeNote_1.6.1_arm/FmtEngine.cpp~compile 2003-12-23 15:53:46.000000000 +0100 +++ FreeNote_1.6.1_arm/FmtEngine.cpp 2004-02-01 18:42:32.000000000 +0100 @@ -1,409 +1,410 @@ -/* FreeNote for Sharp SLA300, B500, C7x0 Linux PDA - Copyright (C) 2003 Joe Kanemori. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/* -2003/12/16-19 FreeNote ver 1.5.5pre -・曲線描画ロジックの改良 - -2003/12/14 FreeNote 1.5.4pre -・曲線描画ロジックの改良 - -2003/11/30-2003/12/04 FreeNote 1.5.3pre -・ベジェ関数のスペルミスを修正 - -2003/11/16 FreeNote 1.5.2pre -・円描画のロジックを追加 - -2003/11/13 FreeNote 1.5.1pre -・スムージング追加 -2003/11/10-12 -・曲線整形モード追加 -2003/11/09 追加 -*/ -#include "fmtengine.h" -#include -#include -#include -int SNAP_SIZE = 32; -int PHASE1_ANGLE = 30; -int PHASE2_ANGLE = 30; -double Surface(const QPoint& p1, const QPoint& p2) -{ - return 0.5 * abs(p1.x() * p2.y() - p1.y() * p2.x()); -} - -bool IsLinear(const QPoint& p1, const QPoint& p2, const QPoint& p3) -{ - double s1 = Surface(p1, p2); - double s2 = Surface(p2, p3); - double s3 = Surface(p1, p3); - if (s1 + s2 == s3) { - return true; - } else { - return false; - } -} - -const double Angle(const QPoint& p1, const QPoint& p2) -{ - return qATan2((double)(p2.y() - p1.y()), (double)(p2.x() - p1.x())); -} - -const double DiffAngle(const QPoint& p1, const QPoint& p2, const QPoint& p3) -{ - return fabs(Angle(p1, p2) - Angle(p2, p3)); -} - -const double ToDegree(double t) -{ - return t * 180 / M_PI; -} - -const double ToRadian(double d) -{ - return d * M_PI / 180; -} - -const double Distance(const QPoint& p1, const QPoint& p2) -{ - return hypot(p1.x() - p2.x(), p1.y() - p2.y()); -} - -const QPoint SnapPoint(const QPoint& p) -{ - int x = ((int)(p.x() + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; - int y = ((int)(p.y() + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; - return QPoint(x, y); -} - -const QPoint ArrangePoint(const QPoint& p1, const QPoint& p2) -{ - int x = p2.x(); - int y = p2.y(); - if (p1.x() - SNAP_SIZE / 2 <= x && p1.x() + SNAP_SIZE / 2 >= x) { - x = p1.x(); - } - if (p1.y() - SNAP_SIZE / 2 <= y && p1.y() + SNAP_SIZE / 2 >= y) { - y = p1.y(); - } - return QPoint(x, y); -} - -FNPointList ReducePoints(FNPointList& p) -{ - if (3 >= p.count()) { - return p; - } - FNPointList rt; - rt.append(p.first()); - QPoint* p1 = p.first(); - QPoint* p2 = p.at(1); - QPoint* p3 = NULL; - for (uint i = 2; i < p.count(); ++i) { - p3 = p.at(i); - if (false == IsLinear(*p1, *p2, *p3)) { - rt.append(p2); - p1 = p2; - } - p2 = p3; - } - rt.append(p3); - return rt; -} - -FNPointList ExtractAngle2(FNPointList& p, const int deg) -{ - FNPointList rt; - rt.append(p.first()); - QPoint* st = p.first(); - QPoint* mp = p.at(1); - QPoint* ed = p.last(); - for (uint i = 2; i < p.count(); ++i) { - ed = p.at(i); - if (ToRadian(deg) <= DiffAngle(*st, *mp, *ed)) { - st = mp; - rt.append(mp); - } - mp = ed; - } - rt.append(ed); - return rt; -} - -FNPointList ExtractAngle(FNPointList& p, const int deg) -{ - FNPointList rt; - rt.append(p.first()); - QPoint* st = p.first(); - QPoint* mp = p.at(1); - QPoint* ed = p.last(); - for (uint i = 2; i < p.count(); ++i) { - ed = p.at(i); - if (ToRadian(deg) <= DiffAngle(*st, *mp, *ed)) { - st = mp; - rt.append(mp); - } - mp = ed; - } - if (SNAP_SIZE / 2 > Distance(*p.first(), *p.last()) && 3 < p.count()) { - rt.append(p.first()); - } else { - rt.append(ed); - } - return rt; -} - -FNPointList SumupPoints(FNPointList& p) -{ - if (3 >= p.count()) { - return p; - } - FNPointList rt; - rt.append(p.first()); - QPoint* p1 = p.first(); - QPoint* p2 = NULL; - double pred = 0; - for (uint i = 1; i < p.count() - 1; ++i) { - p2 = p.at(i); - double d = Distance(*p1, *p2); - if (SNAP_SIZE / 2 < d || pred > d) { - rt.append(p2); - p1 = p2; - d = 0; - } - pred = d; - } - rt.append(p.last()); - return rt; -} - -FNPointList SnapPoints(FNPointList& p) -{ - FNPointList rt; - for (uint i = 0; i < p.count(); ++i) { - QPoint tp = SnapPoint(*p.at(i)); - p.at(i)->setX(tp.x()); - p.at(i)->setY(tp.y()); - rt.append(p.at(i)); - } - return rt; -} - -FNPointList ArrangePoints(FNPointList& p) -{ - if (3 >= p.count() && 2 != p.count()) { - return p; - } - FNPointList rt; - rt.append(p.first()); - QPoint* p1 = p.first(); - QPoint* p2 = NULL; - for (uint i = 1; i < p.count(); ++i) { - p2 = p.at(i); - QPoint tp = ArrangePoint(*p1, *p2); - p2->setX(tp.x()); - p2->setY(tp.y()); - rt.append(p2); - p1 = p2; - } - if (*p.first() == *p.last()) { - QPoint tp = ArrangePoint(*p1, *p.first()); - rt.first()->setX(tp.x()); - rt.first()->setY(tp.y()); - } - return rt; -} - -FNPointList TuningPoints(FNPointList& p) -{ - FNPointList rt; - if (3 >= p.count()) { - for (uint i = 0; i < p.count(); ++i) { - rt.append(new QPoint(*p.at(i))); - } - return rt; - } - rt.append(new QPoint(*p.at(0))); - for (uint i = 1; i < p.count() - 1; ++i) { - QPoint* p1 = p.at(i); - QPoint* p2 = p.at(i + 1); - rt.append(new QPoint(*p1)); - if (i < p.count() - 2) { - rt.append(new QPoint((p1->x() + p2->x())/2, (p1->y() + p2->y())/2)); - } - } - rt.append(new QPoint(*p.at(p.count()-1))); - return rt; -} - -FNPointList ToBezier(FNPointList& p) { - FNPointList rt; - rt.append(new QPoint(*p.at(0))); - for (uint i = 0; i < p.count() - 2; i += 2) { - int x1 = p.at(i)->x(); - int xa = p.at(i + 1)->x(); - int x4 = p.at(i + 2)->x(); - - int x2 = (x1 + xa) / 2; - int x3 = (xa + x4) / 2; - - int y1 = p.at(i)->y(); - int ya = p.at(i + 1)->y(); - int y4 = p.at(i + 2)->y(); - - int y2 = (y1 + ya) / 2; - int y3 = (ya + y4) / 2; - - rt.append(new QPoint(x2 ,y2)); - rt.append(new QPoint(x3 ,y3)); - rt.append(new QPoint(x4 ,y4)); - } - return rt; -} - -FNPointList ToCurves(FNPointList& p) { - if (3 <= p.count()) { - //ベジェによる補完 - return ToBezier(p); - } else { - FNPointList rt; - for (uint i = 0; i < p.count(); ++i) { - rt.append(new QPoint(*p.at(i))); - } - return rt; - } -} - -FNPointList AutoFormat(FNPointList& p) -{ - FNPointList tp = ExtractAngle(p, PHASE1_ANGLE); - uint n; - do { - n = tp.count(); - tp = SumupPoints(tp); - tp = ExtractAngle(tp, PHASE1_ANGLE); - tp = ArrangePoints(tp); - } while (n > tp.count()); - tp = SnapPoints(tp); - tp = ReducePoints(tp); - FNPointList rt; - if (2 == tp.count()) { - if (*tp.first() == *tp.last()) { - return rt; - } - } - for (uint i = 0; i < tp.count(); ++i) { - rt.append(new QPoint(*tp.at(i))); - } - return rt; -} - -FNPointList ToEllipse(int x, int y, int w, int h) { - FNPointList rt; - QPointArray pa; - pa.makeEllipse(x, y, w, h); - for (uint i = 0; i < pa.count(); ++i) { - rt.append(new QPoint(pa.point(i))); - } - return rt; -} - -FNPointList AutoCurve(FNPointList& p) -{ - FNPointList tp2; - tp2.setAutoDelete(true); - FNPointList tp4; - tp4.setAutoDelete(true); - QPoint sp = SnapPoint(*p.at(0)); - QPoint ep = SnapPoint(*p.at(p.count()-1)); - if (sp == ep) { - //楕円 - int sx = p.at(0)->x(); - int sy = p.at(0)->y(); - int ex = sx; - int ey = sy; - for (uint i = 1; i < p.count(); ++i) { - QPoint tp = *p.at(i); - if (sx > tp.x()) { - sx = tp.x(); - } else if (ex < tp.x()) { - ex = tp.x(); - } - if (sy > tp.y()) { - sy = tp.y(); - } else if (ey < tp.y()) { - ey = tp.y(); - } - } - sp = SnapPoint(QPoint(sx, sy)); - ep = SnapPoint(QPoint(ex, ey)); - tp2.append(new QPoint(sp.x(), sp.y())); - tp2.append(new QPoint(ep.x(), ep.y())); - } else { - FNPointList tp = ExtractAngle2(p, PHASE2_ANGLE); - uint n; - do { - n = tp.count(); - tp = SumupPoints(tp); - tp = ExtractAngle2(tp, PHASE2_ANGLE); - tp = SnapPoints(tp); - } while (n > tp.count()); - tp = SumupPoints(tp); - tp = ReducePoints(tp); - tp4 = TuningPoints(tp); - tp2 = ToCurves(tp4); - } - FNPointList rt; - if (2 == tp2.count()) { - if (*tp2.first() == *tp2.last()) { - return rt; - } - } - for (uint i = 0; i < tp2.count(); ++i) { - rt.append(new QPoint(*tp2.at(i))); - } - return rt; -} - -FNPointList Smoothing(FNPointList& p) -{ - int tsnap = SNAP_SIZE; - SNAP_SIZE=8; - FNPointList tp = ExtractAngle2(p, PHASE2_ANGLE); - tp = SumupPoints(tp); - tp = ReducePoints(tp); - FNPointList tp4 = TuningPoints(tp); - tp4.setAutoDelete(true); - FNPointList tp2 = ToCurves(tp4); - tp2.setAutoDelete(true); - FNPointList rt; - for (uint i = 0; i < tp2.count(); ++i) { - rt.append(new QPoint(*tp2.at(i))); - } - SNAP_SIZE = tsnap; - return rt; -} - -FNPointList Reduce(FNPointList& p) -{ - FNPointList tp = ReducePoints(p); - FNPointList rt; - for (uint i = 0; i < tp.count(); ++i) { - rt.append(new QPoint(*tp.at(i))); - } - return rt; -} +/* FreeNote for Sharp SLA300, B500, C7x0 Linux PDA + Copyright (C) 2003 Joe Kanemori. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* +2003/12/16-19 FreeNote ver 1.5.5pre +・曲線描画ロジックの改良 + +2003/12/14 FreeNote 1.5.4pre +・曲線描画ロジックの改良 + +2003/11/30-2003/12/04 FreeNote 1.5.3pre +・ベジェ関数のスペルミスを修正 + +2003/11/16 FreeNote 1.5.2pre +・円描画のロジックを追加 + +2003/11/13 FreeNote 1.5.1pre +・スムージング追加 +2003/11/10-12 +・曲線整形モード追加 +2003/11/09 追加 +*/ +#include "fmtengine.h" +#include +#include +#include +#include // abs +int SNAP_SIZE = 32; +int PHASE1_ANGLE = 30; +int PHASE2_ANGLE = 30; +double Surface(const QPoint& p1, const QPoint& p2) +{ + return 0.5 * abs(p1.x() * p2.y() - p1.y() * p2.x()); +} + +bool IsLinear(const QPoint& p1, const QPoint& p2, const QPoint& p3) +{ + double s1 = Surface(p1, p2); + double s2 = Surface(p2, p3); + double s3 = Surface(p1, p3); + if (s1 + s2 == s3) { + return true; + } else { + return false; + } +} + +const double Angle(const QPoint& p1, const QPoint& p2) +{ + return qATan2((double)(p2.y() - p1.y()), (double)(p2.x() - p1.x())); +} + +const double DiffAngle(const QPoint& p1, const QPoint& p2, const QPoint& p3) +{ + return fabs(Angle(p1, p2) - Angle(p2, p3)); +} + +const double ToDegree(double t) +{ + return t * 180 / M_PI; +} + +const double ToRadian(double d) +{ + return d * M_PI / 180; +} + +const double Distance(const QPoint& p1, const QPoint& p2) +{ + return hypot(p1.x() - p2.x(), p1.y() - p2.y()); +} + +const QPoint SnapPoint(const QPoint& p) +{ + int x = ((int)(p.x() + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; + int y = ((int)(p.y() + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; + return QPoint(x, y); +} + +const QPoint ArrangePoint(const QPoint& p1, const QPoint& p2) +{ + int x = p2.x(); + int y = p2.y(); + if (p1.x() - SNAP_SIZE / 2 <= x && p1.x() + SNAP_SIZE / 2 >= x) { + x = p1.x(); + } + if (p1.y() - SNAP_SIZE / 2 <= y && p1.y() + SNAP_SIZE / 2 >= y) { + y = p1.y(); + } + return QPoint(x, y); +} + +FNPointList ReducePoints(FNPointList& p) +{ + if (3 >= p.count()) { + return p; + } + FNPointList rt; + rt.append(p.first()); + QPoint* p1 = p.first(); + QPoint* p2 = p.at(1); + QPoint* p3 = NULL; + for (uint i = 2; i < p.count(); ++i) { + p3 = p.at(i); + if (false == IsLinear(*p1, *p2, *p3)) { + rt.append(p2); + p1 = p2; + } + p2 = p3; + } + rt.append(p3); + return rt; +} + +FNPointList ExtractAngle2(FNPointList& p, const int deg) +{ + FNPointList rt; + rt.append(p.first()); + QPoint* st = p.first(); + QPoint* mp = p.at(1); + QPoint* ed = p.last(); + for (uint i = 2; i < p.count(); ++i) { + ed = p.at(i); + if (ToRadian(deg) <= DiffAngle(*st, *mp, *ed)) { + st = mp; + rt.append(mp); + } + mp = ed; + } + rt.append(ed); + return rt; +} + +FNPointList ExtractAngle(FNPointList& p, const int deg) +{ + FNPointList rt; + rt.append(p.first()); + QPoint* st = p.first(); + QPoint* mp = p.at(1); + QPoint* ed = p.last(); + for (uint i = 2; i < p.count(); ++i) { + ed = p.at(i); + if (ToRadian(deg) <= DiffAngle(*st, *mp, *ed)) { + st = mp; + rt.append(mp); + } + mp = ed; + } + if (SNAP_SIZE / 2 > Distance(*p.first(), *p.last()) && 3 < p.count()) { + rt.append(p.first()); + } else { + rt.append(ed); + } + return rt; +} + +FNPointList SumupPoints(FNPointList& p) +{ + if (3 >= p.count()) { + return p; + } + FNPointList rt; + rt.append(p.first()); + QPoint* p1 = p.first(); + QPoint* p2 = NULL; + double pred = 0; + for (uint i = 1; i < p.count() - 1; ++i) { + p2 = p.at(i); + double d = Distance(*p1, *p2); + if (SNAP_SIZE / 2 < d || pred > d) { + rt.append(p2); + p1 = p2; + d = 0; + } + pred = d; + } + rt.append(p.last()); + return rt; +} + +FNPointList SnapPoints(FNPointList& p) +{ + FNPointList rt; + for (uint i = 0; i < p.count(); ++i) { + QPoint tp = SnapPoint(*p.at(i)); + p.at(i)->setX(tp.x()); + p.at(i)->setY(tp.y()); + rt.append(p.at(i)); + } + return rt; +} + +FNPointList ArrangePoints(FNPointList& p) +{ + if (3 >= p.count() && 2 != p.count()) { + return p; + } + FNPointList rt; + rt.append(p.first()); + QPoint* p1 = p.first(); + QPoint* p2 = NULL; + for (uint i = 1; i < p.count(); ++i) { + p2 = p.at(i); + QPoint tp = ArrangePoint(*p1, *p2); + p2->setX(tp.x()); + p2->setY(tp.y()); + rt.append(p2); + p1 = p2; + } + if (*p.first() == *p.last()) { + QPoint tp = ArrangePoint(*p1, *p.first()); + rt.first()->setX(tp.x()); + rt.first()->setY(tp.y()); + } + return rt; +} + +FNPointList TuningPoints(FNPointList& p) +{ + FNPointList rt; + if (3 >= p.count()) { + for (uint i = 0; i < p.count(); ++i) { + rt.append(new QPoint(*p.at(i))); + } + return rt; + } + rt.append(new QPoint(*p.at(0))); + for (uint i = 1; i < p.count() - 1; ++i) { + QPoint* p1 = p.at(i); + QPoint* p2 = p.at(i + 1); + rt.append(new QPoint(*p1)); + if (i < p.count() - 2) { + rt.append(new QPoint((p1->x() + p2->x())/2, (p1->y() + p2->y())/2)); + } + } + rt.append(new QPoint(*p.at(p.count()-1))); + return rt; +} + +FNPointList ToBezier(FNPointList& p) { + FNPointList rt; + rt.append(new QPoint(*p.at(0))); + for (uint i = 0; i < p.count() - 2; i += 2) { + int x1 = p.at(i)->x(); + int xa = p.at(i + 1)->x(); + int x4 = p.at(i + 2)->x(); + + int x2 = (x1 + xa) / 2; + int x3 = (xa + x4) / 2; + + int y1 = p.at(i)->y(); + int ya = p.at(i + 1)->y(); + int y4 = p.at(i + 2)->y(); + + int y2 = (y1 + ya) / 2; + int y3 = (ya + y4) / 2; + + rt.append(new QPoint(x2 ,y2)); + rt.append(new QPoint(x3 ,y3)); + rt.append(new QPoint(x4 ,y4)); + } + return rt; +} + +FNPointList ToCurves(FNPointList& p) { + if (3 <= p.count()) { + //ベジェによる補完 + return ToBezier(p); + } else { + FNPointList rt; + for (uint i = 0; i < p.count(); ++i) { + rt.append(new QPoint(*p.at(i))); + } + return rt; + } +} + +FNPointList AutoFormat(FNPointList& p) +{ + FNPointList tp = ExtractAngle(p, PHASE1_ANGLE); + uint n; + do { + n = tp.count(); + tp = SumupPoints(tp); + tp = ExtractAngle(tp, PHASE1_ANGLE); + tp = ArrangePoints(tp); + } while (n > tp.count()); + tp = SnapPoints(tp); + tp = ReducePoints(tp); + FNPointList rt; + if (2 == tp.count()) { + if (*tp.first() == *tp.last()) { + return rt; + } + } + for (uint i = 0; i < tp.count(); ++i) { + rt.append(new QPoint(*tp.at(i))); + } + return rt; +} + +FNPointList ToEllipse(int x, int y, int w, int h) { + FNPointList rt; + QPointArray pa; + pa.makeEllipse(x, y, w, h); + for (uint i = 0; i < pa.count(); ++i) { + rt.append(new QPoint(pa.point(i))); + } + return rt; +} + +FNPointList AutoCurve(FNPointList& p) +{ + FNPointList tp2; + tp2.setAutoDelete(true); + FNPointList tp4; + tp4.setAutoDelete(true); + QPoint sp = SnapPoint(*p.at(0)); + QPoint ep = SnapPoint(*p.at(p.count()-1)); + if (sp == ep) { + //楕円 + int sx = p.at(0)->x(); + int sy = p.at(0)->y(); + int ex = sx; + int ey = sy; + for (uint i = 1; i < p.count(); ++i) { + QPoint tp = *p.at(i); + if (sx > tp.x()) { + sx = tp.x(); + } else if (ex < tp.x()) { + ex = tp.x(); + } + if (sy > tp.y()) { + sy = tp.y(); + } else if (ey < tp.y()) { + ey = tp.y(); + } + } + sp = SnapPoint(QPoint(sx, sy)); + ep = SnapPoint(QPoint(ex, ey)); + tp2.append(new QPoint(sp.x(), sp.y())); + tp2.append(new QPoint(ep.x(), ep.y())); + } else { + FNPointList tp = ExtractAngle2(p, PHASE2_ANGLE); + uint n; + do { + n = tp.count(); + tp = SumupPoints(tp); + tp = ExtractAngle2(tp, PHASE2_ANGLE); + tp = SnapPoints(tp); + } while (n > tp.count()); + tp = SumupPoints(tp); + tp = ReducePoints(tp); + tp4 = TuningPoints(tp); + tp2 = ToCurves(tp4); + } + FNPointList rt; + if (2 == tp2.count()) { + if (*tp2.first() == *tp2.last()) { + return rt; + } + } + for (uint i = 0; i < tp2.count(); ++i) { + rt.append(new QPoint(*tp2.at(i))); + } + return rt; +} + +FNPointList Smoothing(FNPointList& p) +{ + int tsnap = SNAP_SIZE; + SNAP_SIZE=8; + FNPointList tp = ExtractAngle2(p, PHASE2_ANGLE); + tp = SumupPoints(tp); + tp = ReducePoints(tp); + FNPointList tp4 = TuningPoints(tp); + tp4.setAutoDelete(true); + FNPointList tp2 = ToCurves(tp4); + tp2.setAutoDelete(true); + FNPointList rt; + for (uint i = 0; i < tp2.count(); ++i) { + rt.append(new QPoint(*tp2.at(i))); + } + SNAP_SIZE = tsnap; + return rt; +} + +FNPointList Reduce(FNPointList& p) +{ + FNPointList tp = ReducePoints(p); + FNPointList rt; + for (uint i = 0; i < tp.count(); ++i) { + rt.append(new QPoint(*tp.at(i))); + } + return rt; +} --- FreeNote_1.6.1_arm/FNCanvas.cpp~compile 2003-12-24 15:20:16.000000000 +0100 +++ FreeNote_1.6.1_arm/FNCanvas.cpp 2004-02-01 18:43:35.000000000 +0100 @@ -1,1227 +1,1228 @@ -/* FreeNote for Sharp SLA300, B500, C7x0 Linux PDA - Copyright (C) 2003 Joe Kanemori. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/* -2003/12/23 ver 1.6.1 -・保存情報のサイズ縮小 - -2003/12/16-19 ver 1.5.5pre -・ペンサイズの追加(1-8) -・アンドゥ・リドゥの実装 - -2003/12/14 ver 1.5.4pre -・ペンサイズを選択可能に。 - -2003/12/05 ver 1.5.3Apre -・グリッドの色を修正 - -2003/12/04 ver 1.5.3pre -・グリッドの描画を一部修正 - -2003/11/10 ver 1.5.1pre -・曲線整形モード追加 - -2003/11/09 ver 1.5.0pre -・自動整形モード追加 - -2003/09/03 ver 1.3.4pre -・Use all quadrant OFF時に表示位置がリセットされる場合があるバグ対応。 - -2003/09/01-03 ver 1.3.3pre -・スクロールの改良 -・Use all quadrant(全象限を使用する)メニューを追加 - -2003/08/31 FreeNote 1.3.2pre -・全方向スクロール - -2003/08/23 FreeNote 1.3.0pre -・CR動作の修正 - -2003/08/15 FreeNote 1.2.1を公開 -・保存時のバグ修正 -・完了ダイアログの自動消去 -・PNGファイルへの出力 - -2003/08/15 FreeNote 1.2を公開 -・オプション追加 -・スクロールガイド -・Freeファイル関連付け -・アイコンの変更 - -2003/08/05 FreeNote 1.1.1preを公開 -・高速起動時に閉じた状態を保持 -・描画モード切替え時に消しゴム表示 -・保存時間短縮 -・Viewモードの挙動を変更 -・メニューの見た目を変更 -*/ -#include "fncanvas.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fnmessagebox.h" -#include "fmtengine.h" - -int snap(int v) { - int tv = abs(v); - tv = ((int)(tv + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; - if (0 > v) { - return -tv; - } else { - return tv; - } -} - -FNCanvas::FNCanvas(QWidget* parent = 0, const char* name = 0, WFlags f = 0) - :QWidget(parent, name, f), - _pen(black, 1, SolidLine, RoundCap, RoundJoin), - _asMode(AS_NONE), - _drawMode(MODE_DRAW), - _disp_offset(0), - _eraser_l(50), - _eraser_s(10), - _h_step(100), - _v_step(100), - _margin(5), - _scrollTiming(800), - _viewMode(false), - _isWaiting(false), - _isDragging(false), - _isHeadingEnables(false), - _isShowGuide(false), - _isUseAllQuadrant(false), - _scale_x(1.0), - _scale_y(1.0) -{ - _tracks.setAutoDelete(true); - this->setBackgroundMode(NoBackground); - _timer = new QTimer(this); - connect(_timer, SIGNAL(timeout()), this, SLOT(autoScroll())); -} - -FNCanvas::~FNCanvas() -{ - _timer->stop(); - delete _timer; - - _tracks.clear(); - clearList(_draws); -} - -void FNCanvas::setScrollTiming(int v) -{ - _scrollTiming = v; -} - - -void FNCanvas::setVStep(int v) -{ - _v_step = v; -} - -void FNCanvas::setHStep(int v) -{ - _h_step = v; -} - -void FNCanvas::setSEraser(int v) -{ - _eraser_s = v; -} - -void FNCanvas::setLEraser(int v) -{ - _eraser_l = v; -} - - -void FNCanvas::setMargin(int v) -{ - if (v < 3) { - v = 3; - } - _margin = v; -} - -void FNCanvas::setScrollMode(int as) -{ - _asMode = as; - redraw(); -} - -void FNCanvas::autoScroll() -{ - if (AS_NONE == _asMode) { - if (MODE_FORMAT == _drawMode || MODE_CURVE == _drawMode || MODE_SMOOTH == _drawMode) { - setOrigin(_origin.x(), _origin.y()); - } - return; - } - bool tmp = _isHeadingEnables; - int dx = 0; - int dy = 0; - if (AS_BOTH == _asMode || AS_HORIZONTAL == _asMode) { - if (_last.x() > width() * (_margin - 1) / _margin) { - dx = _h_step; - } else if (_last.x() < width() / _margin) { - dx = -_h_step; - } - } - if (AS_BOTH == _asMode || AS_VERTICAL == _asMode) { - if (_last.y() > height() * (_margin - 1) / _margin) { - dy = _v_step; - } else if (_last.y() < height() / _margin) { - dy = -_v_step; - } - } - setOrigin(_origin.x() + dx, _origin.y() + dy); - _isHeadingEnables = tmp; -} - -void FNCanvas::mousePressEvent(QMouseEvent* evt) -{ - setFocus(); - _timer->stop(); - _tracks.clear(); - if (_viewMode) { - _isWaiting = true; - _viewMode = false; - setOrigin((int)((evt->x()) / _scale_x) - width() / 2, (int)((evt->y()) / _scale_y) - height() / 2); - redraw(); - emit resetViewMode(); - } else if (MODE_ERASE != _drawMode) { - _last = evt->pos(); - _tracks.append(new QPoint(_last)); - } else { - redraw(); - _last = evt->pos(); - _tracks.append(new QPoint(_last)); - - QPainter pbuf; - QPainter pwin; - pbuf.begin(&_buffer); - pwin.begin(this); - - int w = _eraser_s; - if (PENWIDTH_MAX / 2 < _pen.width()) { - w = _eraser_l; - } - pbuf.setRasterOp(XorROP); - pbuf.setPen(QPen(white, 1)); - pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - - pwin.setRasterOp(XorROP); - pwin.setPen(QPen(white, 1)); - pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - - pbuf.end(); - pwin.end(); - } - _isDragging = true; -} - -void FNCanvas::mouseMoveEvent(QMouseEvent* evt) -{ - if (_isWaiting) { - return; - } - if (MODE_ERASE != _drawMode) { - QPainter pwin; - QPainter pbuf; - - pwin.begin(this); - pbuf.begin(&_buffer); - - pwin.setPen(_pen); - pbuf.setPen(_pen); - - pwin.drawLine(_last, evt->pos()); - pbuf.drawLine(_last, evt->pos()); - - pwin.end(); - pbuf.end(); - _last = evt->pos(); - _tracks.append(new QPoint(_last)); - } else { - //redraw(); - if (_last.x() == -1) { - return; - } - QPainter pbuf; - QPainter pwin; - - pbuf.begin(&_buffer); - pwin.begin(this); - - int w = _eraser_s; - if (PENWIDTH_MAX / 2 < _pen.width()) { - w = _eraser_l; - } - pbuf.setRasterOp(XorROP); - pwin.setRasterOp(XorROP); - pbuf.setPen(QPen(white, 1)); - pwin.setPen(QPen(white, 1)); - pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - - _tracks.append(new QPoint(evt->pos())); - _last = evt->pos(); - - pbuf.setRasterOp(CopyROP); - pwin.setRasterOp(CopyROP); - QRect r = QRect(0, 0, width(), height()); - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - if (r.intersects(p->boundingRect())) { - bool f = false; - QRect selected(_last.x() - w / 2, _last.y() - w / 2, w, w); - for (uint j = 0; j < p->points().count(); ++j) { - QPoint& pts = p->points().at(j); - if (selected.contains(pts)) { - f = true; - break; - } - } - if (f) { - p->drawShape(pbuf, f); - p->drawShape(pwin, f); - } - } - } - pbuf.setRasterOp(XorROP); - pwin.setRasterOp(XorROP); - pbuf.setPen(QPen(white, 1)); - pwin.setPen(QPen(white, 1)); - pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - pbuf.end(); - pwin.end(); - } -} - -void FNCanvas::mouseReleaseEvent(QMouseEvent* evt) -{ - _isDragging = false; - if (_isWaiting) { - _isWaiting = false; - return; - } - _last = evt->pos(); - if (MODE_ERASE != _drawMode) { - if (1 < _tracks.count()) { - FNPolygon* p = NULL; - if (MODE_FORMAT == _drawMode) { - p = new FNPolygon(_pen); - _tracks = AutoFormat(_tracks); - } else if (MODE_CURVE == _drawMode) { - QPoint sp = SnapPoint(*_tracks.at(0)); - QPoint ep = SnapPoint(*_tracks.at(_tracks.count()-1)); - _tracks = AutoCurve(_tracks); - if (sp == ep) { - p = new FNEllipse(_pen); - } else if (2 < _tracks.count()) { - p = new FNBezier(_pen); - } else { - p = new FNPolygon(_pen); - } - } else if (MODE_SMOOTH == _drawMode) { - _tracks = Smoothing(_tracks); - if (2 < _tracks.count()) { - p = new FNBezier(_pen); - } else { - p = new FNPolygon(_pen); - } - } else { - _tracks = Reduce(_tracks); - p = new FNPolygon(_pen); - } - if (1 < _tracks.count()) { - p->setPoints(_tracks); - redobuf_flush(); - _draws.append(p); - } - } - _tracks.clear(); - _isHeadingEnables = true; - _timer->start(_scrollTiming, true); - } else { - _last = QPoint(-1, -1); - _tracks.append(new QPoint(evt->pos())); - redraw(); - } -} - -void FNCanvas::paintEvent(QPaintEvent* evt) -{ - bitBlt(this, 0, 0, &_buffer); -} - -void FNCanvas::resizeEvent(QResizeEvent* evt) -{ - QPixmap save(_buffer); - _buffer.resize(evt->size()); - _buffer.fill(white); - bitBlt(&_buffer, 0, 0, &save); - redraw(); -} - -void FNCanvas::setOrigin(QPoint& o) -{ - this->setOrigin(o.x(), o.y()); -} - -QPoint FNCanvas::getTopLeft() -{ - if (0 == _draws.count() || !_isUseAllQuadrant) { - return _origin; - } - - int dx = ((FNPolygon*)_draws.at(0))->boundingRect().x(); - int dy = ((FNPolygon*)_draws.at(0))->boundingRect().y(); - for (uint i = 1; i < _draws.count(); ++i) { - FNPolygon* p = _draws.at(i); - if (dx > p->boundingRect().x()) { - dx = p->boundingRect().x(); - } - if (dy > p->boundingRect().y()) { - dy = p->boundingRect().y(); - } - } - return QPoint(snap(dx), snap(dy)); -} - - -void FNCanvas::rebuild() -{ - if (0 == _draws.count() || !_isUseAllQuadrant) { - return; - } - - QPoint d = getTopLeft(); - for (uint i = 0; i < _draws.count(); ++i) { - FNPolygon* p = _draws.at(i); - p->translate(-d.x(), -d.y()); - } - - _origin = QPoint(0, 0); -} - - -void FNCanvas::setOrigin(int ox, int oy) -{ - ox = snap(ox); - oy = snap(oy); - _isHeadingEnables = false; - _timer->stop(); - - - int dx = 0; - int dy = 0; - if (!_isUseAllQuadrant) { - if (0 > ox) { - ox = 0; - } - if (0 > oy) { - oy = 0; - } - dx = _origin.x() - ox; - dy = _origin.y() - oy; - } else { - dx = _origin.x() - ox; - dy = _origin.y() - oy; - if (0 > ox) { - ox = 0; - } - if (0 > oy) { - oy = 0; - } - } - for (uint i = 0; i < _tracks.count(); ++i) { - QPoint* p = _tracks.at(i); - p->setX(p->x() + dx); - p->setY(p->y() + dy); - } - - for (uint i = 0; i < _draws.count(); ++i) { - FNPolygon* p = _draws.at(i); - p->translate(dx, dy); - } - _origin = QPoint(ox, oy); - emit originChanged(ox, oy); - redraw(); -} - -void FNCanvas::redraw() -{ - if (!this->isVisible()) { - return; - } - _buffer.fill(white); - QPainter pbuf; - QRect r = QRect(0, 0, width(), height()); - pbuf.begin(&_buffer); - if (_viewMode) { - float wx = 0; - float wy = 0; - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - QRect r = p->boundingRect(); - if (wx < r.right()) { - wx = r.right(); - } - if (wy < r.bottom()) { - wy = r.bottom(); - } - } - wx += SNAP_SIZE; - wy += SNAP_SIZE; - wx = snap((int)wx); - wy = snap((int)wy); - wx = wx + _origin.x(); - wy = wy + _origin.y(); - _scale_x = (float)width() / wx; - _scale_y = (float)height() / wy; - if (1.0f < _scale_x) { - _scale_x = 1.0f; - } - if (1.0f < _scale_y) { - _scale_y = 1.0f; - } - if (_scale_x > _scale_y) { - _scale_x = _scale_y; - } else if (_scale_x < _scale_y) { - _scale_y = _scale_x; - } - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - FNPolygon* t = NULL; - if (p->type() == FN_BEZIER) { - t = new FNBezier(*(FNBezier*)p); - } else if (p->type() == FN_ELLIPSE) { - t = new FNEllipse(*(FNEllipse*)p); - } else { - t = new FNPolygon(*p); - } - t->translate(-_origin.x(), -_origin.y()); - for (uint j = 0; j < t->points().count(); ++j) { - QPoint& pts = t->points().at(j); - int x = (int)(pts.x() * _scale_x); - int y = (int)(pts.y() * _scale_y); - pts.setX(x); - pts.setY(y); - } - double pensize = t->pen().width(); - if (_scale_x > _scale_y) { - pensize = pensize * _scale_y; - } else { - pensize = pensize * _scale_x; - } - if (0 >= pensize) { - pensize = 1; - } - t->pen().setWidth(pensize); - t->drawShape(pbuf); - delete t; - } - } else if (MODE_ERASE != _drawMode) { - if (MODE_FORMAT == _drawMode || MODE_CURVE == _drawMode) { - QPen pen1(QColor(0, 240, 240), 1); - QPen pen2(QColor(0, 0, 0), 1); - pbuf.setPen(QPen(QColor(0, 240, 240), 1)); - pbuf.setPen(pen1); - for (int x = 0; x < width() + SNAP_SIZE; x += SNAP_SIZE) { - pbuf.drawLine(x - SNAP_SIZE / 2, 0, x - SNAP_SIZE / 2, height()); - for (int y = 0; y < height() + SNAP_SIZE; y += SNAP_SIZE) { - pbuf.drawLine(0, y - SNAP_SIZE / 2, width(), y - SNAP_SIZE / 2); - pbuf.drawRect(x-1,y-1,2,2); - } - } - } - if (_isShowGuide) { - pbuf.setPen(QPen(cyan, 1, DashLine)); - if (AS_HORIZONTAL == _asMode || AS_BOTH == _asMode) { - if (0 != _origin.x() || _isUseAllQuadrant) { - pbuf.drawLine(width() / _margin, 0, width() / _margin, height()); - } - pbuf.drawLine(width() * (_margin - 1) / _margin, 0, width() * (_margin - 1) / _margin, height()); - } - - if (AS_VERTICAL == _asMode || AS_BOTH == _asMode) { - if (0 != _origin.y() || _isUseAllQuadrant) { - pbuf.drawLine(0, height() / _margin, width(), height() / _margin); - } - pbuf.drawLine(0, height() * (_margin - 1) / _margin, width(), height() * (_margin - 1) / _margin); - } - } - - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - if (r.intersects(p->boundingRect())) { - p->drawShape(pbuf); - } - } - } else { - int w = _eraser_s; - if (PENWIDTH_MAX / 2 < _pen.width()) { - w = _eraser_l; - } - FNPointList removes; - for (uint i = 0; i < _tracks.count(); ++i) { - removes.append(_tracks.at(i)); - } - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - if (r.intersects(p->boundingRect())) { - bool f = false; - for (uint j = 0; j < _tracks.count(); ++j) { - QPoint* pts = _tracks.at(j); - QRect selected(pts->x() - w / 2, pts->y() - w / 2, w, w); - for (uint k = 0; k < p->points().count(); ++k) { - QPoint& pts2 = p->points().at(k); - if (selected.contains(pts2)) { - f = true; - removes.remove(pts); - break; - } - } - if (f) { - break; - } - } - p->drawShape(pbuf, f); - } - } - for (uint i = 0; i < removes.count(); ++i) { - _tracks.remove(removes.at(i)); - } - /* - if (_isDragging) { - pbuf.setPen(QPen(black, 1)); - pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); - } - */ - } - pbuf.end(); - repaint(); -} - -void FNCanvas::changeColor(QRgb c) -{ - _pen.setColor(QColor(c)); -} - -void FNCanvas::undo() -{ - if (MODE_ERASE != _drawMode) { - ++_disp_offset; - if (_disp_offset > _draws.count()) { - _disp_offset = _draws.count(); - } - } else { - _draws = _undobuf; - _marks.clear(); - } - redraw(); -} - -void FNCanvas::redo() -{ - if (MODE_ERASE != _drawMode) { - if (0 < _disp_offset) { - --_disp_offset; - } - } - redraw(); -} - -void FNCanvas::clearList(FNPolygonList& list) -{ - list.setAutoDelete(true); - list.clear(); - list.setAutoDelete(false); -} - -void FNCanvas::clear() -{ - _disp_offset = 0; - clearList(_draws); - _undobuf.clear(); - setOrigin(0, 0); - redraw(); -} - -void FNCanvas::viewChanged(bool flg) -{ - _tracks.clear(); - _viewMode = flg; - if (_viewMode) { - if (_isUseAllQuadrant) { - rebuild(); - } - setOrigin(0, 0); - } - redraw(); -} - -void FNCanvas::redobuf_flush() -{ - for (uint i = 0; i < _disp_offset; ++i) { - FNPolygon* p = _draws.last(); - _draws.remove(p); - delete p; - } - _disp_offset = 0; -} - -void FNCanvas::modeChanged(int mode) -{ - _tracks.clear(); - _drawMode = mode; - redobuf_flush(); - if (MODE_ERASE == _drawMode) { - _marks.clear(); - _undobuf = _draws; - } else { - if (_draws.count() != _undobuf.count()) { - for (uint i = 0; i < _marks.count(); ++i) { - FNPolygon* p = _marks.at(i); - _draws.remove(p); - } - clearList(_marks); - } - } - redraw(); -} - -QRect FNCanvas::getMatrix(const QRect& r) const -{ - int ox = _origin.x(); - int oy = _origin.y(); - const int wide = 100; - - int left = r.left() + ox; - int top = r.top() + oy; - int right = r.right() + ox; - int bottom = r.bottom() + oy; - - left = (int)(left / wide) * wide; - top = (int)(top / wide) * wide; - right = (right % wide == 0 && left != right) ? right : (int)((right + wide) / wide) * wide; - bottom = (bottom % wide == 0 && top != bottom) ? bottom : (int)((bottom + wide) / wide) * wide; - - return QRect(left - ox, top - oy, right - left, bottom - top); -} - -void FNCanvas::CR() -{ - if (MODE_ERASE == _drawMode) { - return; - } - if (_isHeadingEnables) { - //lastから、左方向に向けて探索する。 - QRect r = getMatrix(_draws.last()->boundingRect()); - bool isSearching = true; - r.moveBy(-100, 0); - while (isSearching) { - isSearching = false; - for (uint i = 0; i < _draws.count(); ++i) { - FNPolygon* p = _draws.at(i); - const QRect& r2 = p->boundingRect(); - if (r.intersects(r2)) { - if (r.left() + 100 > r2.left()) { - r = getMatrix(r2); - r.moveBy(-100, 0); - isSearching = true; - break; - } - } - } - } - r.moveBy(100, 0); - //lastが画面の4/5以下ならば、スクロールアップする。 - //そうでなければ、ヘッディングのみ。 - if (_last.y() > height() * 4 / 5) { - setOrigin(_origin.x() + r.x(), _origin.y() + 50); - } else { - setOrigin(_origin.x() + r.x(), _origin.y()); - } - _isHeadingEnables = false; - } else { - //lastの周囲に何も無い場合は、縦にスクロールする。 - setOrigin(_origin.x(), _origin.y() + 50); - } -} - -void FNCanvas::erase() -{ - if (MODE_ERASE != _drawMode) { - return; - } - FNPolygonList temp; - int w = _eraser_s; - if (PENWIDTH_MAX / 2 < _pen.width()) { - w = _eraser_l; - } - QRect r = QRect(0, 0, width(), height()); - for (uint i = 0; i < _draws.count(); ++i) { - FNPolygon* p = _draws.at(i); - bool f = false; - if (r.intersects(p->boundingRect())) { - for (uint j = 0; j < _tracks.count(); ++j) { - QPoint* pts = _tracks.at(j); - QRect selected(pts->x() - w / 2, pts->y() - w / 2, w, w); - for (uint k = 0; k < p->points().count(); ++k) { - QPoint& pts2 = p->points().at(k); - if (selected.contains(pts2)) { - temp.append(p); - f = true; - break; - } - } - if (f) { - break; - } - } - } - } - for (uint i = 0; i < temp.count(); ++i) { - _draws.remove(temp.at(i)); - _marks.append(temp.at(i)); - } - _tracks.clear(); - redraw(); -} - -void FNCanvas::setPensize(int sz) -{ - _pen.setWidth(sz); -} - -bool FNCanvas::exportPNG(const QFileInfo& info, QPixmap& buf) -{ - if (0 == info.fileName().length()) { - QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); - return false; - } - if (info.extension(false) != "png") { - QMessageBox::warning(0,"FreeNoteQt", "extension '.png' expected."); - return false; - } - - bool ret = buf.save(info.absFilePath(), "PNG"); - if (ret) { - FNMessageBox::information(0,"FreeNoteQt", "export PNG complete."); - } else { - QMessageBox::warning(0,"FreeNoteQt", "could not export file."); - } - return ret; -} - -QString FNCanvas::mkPDFscript(FNPolygon* elm) -{ - QString s =""; - char buf[1024]; - - float r = (float)elm->pen().color().red() / 255.0f; - float g = (float)elm->pen().color().green() / 255.0f; - float b = (float)elm->pen().color().blue() / 255.0f; - s += "q\n"; - sprintf(buf, "%f %f %f RG\n", r, g, b); - s += buf; - QPointArray points = elm->points().copy(); - points.translate(_origin.x(), _origin.y()); - if (elm->type() == FN_BEZIER) { - sprintf(buf, "%d %d m\n", points[0].x(), points[0].y()); - s += buf; - for (uint j = 1; j < points.count(); j += 3) { - sprintf(buf, "%d %d %d %d %d %d c\n", - points[j].x(), points[j].y(), - points[j + 1].x(), points[j + 1].y(), - points[j + 2].x(), points[j + 2].y() - ); - s += buf; - } - } else if (elm->type() == FN_ELLIPSE) { - int x = points[0].x(); - int y = points[0].y(); - int ex = points[1].x(); - int ey = points[1].y(); - int w = ex - x; - int h = ey - y; - int cx = x + w/2; - int cy = y; - int x1 = x + 3*w/4; - int y1 = y; - int x2 = x + w; - int y2 = y + h/4; - int x3 = x + w; - int y3 = y + h/2; - - sprintf(buf, "%d %d m\n%d %d %d %d %d %d c\n", cx, cy, x1, y1, x2, y2, x3, y3); - s += buf; - x1 = x + w; - y1 = y + 3 * h / 4; - x2 = x + 3 * w / 4; - y2 = y + h; - x3 = x + w/2; - y3 = y + h; - sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); - s += buf; - - x1 = x + w / 4; - y1 = y + h; - x2 = x; - y2 = y + 3 * h / 4; - x3 = x; - y3 = y + h / 2; - sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); - s += buf; - x1 = x; - y1 = y + h / 4; - x2 = x + w / 4; - y2 = y; - x3 = x + w / 2; - y3 = y; - sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); - s += buf; - } else { - sprintf(buf, "%d %d m\n", points[0].x(), points[0].y()); - s += buf; - for (uint j = 1; j < points.count(); ++j) { - sprintf(buf, "%d %d l\n", points[j].x(), points[j].y()); - s += buf; - } - } - sprintf(buf, "%d w\n", elm->pen().width()); - s += buf; - s += "S\n"; - s += "Q\n"; - return s; -} - -bool FNCanvas::exportPDF(const QFileInfo& info) -{ - if (0 == info.fileName().length()) { - QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); - return false; - } - if (info.extension(false) != "pdf") { - QMessageBox::warning(0,"FreeNoteQt", "extension '.pdf' expected."); - return false; - } - - FILE* fp = NULL; - if (!(fp = fopen(info.absFilePath().utf8(), "wt"))) { - QMessageBox::warning(0,"FreeNoteQt", "could not export file."); - return false; - } - - QPoint o = getTopLeft(); - rebuild(); - int wx = 595; - int wy = 842; - char buf[1024]; - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon* p = _draws.at(i); - QRect r = p->boundingRect(); - r.moveBy(_origin.x(), _origin.y()); - if (wx < r.right()) { - wx =r.right(); - } - if (wy < r.bottom()) { - wy = r.bottom(); - } - } - - int len = 0; - - sprintf(buf, "1 0 0 -1 0 %d cm\n", wy); - QString cm = buf; - len += cm.length(); - - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - QString s = mkPDFscript(_draws.at(i)); - len += s.length(); - } - - QString header = ""; - header += "%PDF-1.3\n"; - header += "1 0 obj\n"; - header += "<<\n"; - header += "/Type /Page\n"; - header += "/Parent 3 0 R\n"; - header += "/Resources\n"; - header += "<<\n"; - header += "/ProcSet [ /PDF ]\n"; - header += ">>\n"; - sprintf(buf, "/MediaBox [ 0 0 %010d %010d ]\n", wx, wy); - header += buf; - header += "/Contents 4 0 R\n"; - header += ">>\n"; - header += "endobj\n"; - header += "2 0 obj\n"; - header += "<<\n"; - header += "/Type /Catalog\n"; - header += "/Pages 3 0 R\n"; - header += "/PageLayout /OneColumn\n"; - header += "/OpenAction [1 0 R /XYZ null null 1 ]\n"; - header += ">>\n"; - header += "endobj\n"; - header += "3 0 obj\n"; - header += "<<\n"; - header += "/Type /Pages\n"; - header += "/Kids [ 1 0 R ]\n"; - header += "/Count 1\n"; - header += ">>\n"; - header += "endobj\n"; - header += "4 0 obj\n"; - sprintf(buf, "<< /Length %010d >>\n", len); - header += buf; - header += "stream\n"; - - QString footer = ""; - footer += "xref\n"; - footer += "0 5\n"; - footer += "0000000000 65535 f \n"; - footer += "0000000009 00000 n \n"; - footer += "0000000147 00000 n \n"; - footer += "0000000257 00000 n \n"; - footer += "0000000316 00000 n \n"; - footer += "trailer\n"; - footer += "<<\n"; - footer += "/Size 5\n"; - footer += "/Root 2 0 R\n"; - footer += ">>\n"; - footer += "startxref\n"; - - len = cm.length(); - len += header.length(); - fputs(header, fp); - fputs(cm, fp); - - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - QString s = mkPDFscript(_draws.at(i)); - len += s.length(); - fputs(s, fp); - } - QString streamfooter = "endstream\nendobj\n"; - len += streamfooter.length(); - fputs(streamfooter, fp); - - fputs(footer, fp); - sprintf(buf, "%d\n", len); - fputs(buf, fp); - fputs("%%EOF\n", fp); - fclose(fp); - if (_isUseAllQuadrant) { - setOrigin(-o.x(), -o.y()); - } - FNMessageBox::information(0,"FreeNoteQt", "export PDF complete."); - return true; -} - -bool FNCanvas::save(const QFileInfo& info) -{ - if (0 == info.fileName().length()) { - QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); - return false; - } - if (info.extension(false) != "free") { - QMessageBox::warning(0,"FreeNoteQt", "extension '.free' expected."); - return false; - } - FILE* fp = NULL; - if (!(fp = fopen(info.absFilePath().utf8(), "wt"))) { - QMessageBox::warning(0,"FreeNoteQt", "could not save file."); - return false; - } - QPoint o = getTopLeft(); - rebuild(); - fputs("\n", fp); - fputs("\n", fp); - char buf[1024]; - for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { - FNPolygon p(*_draws.at(i)); - p.translate(_origin.x(), _origin.y()); - if (p.type() == FN_BEZIER) { - sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); - } else if (p.type() == FN_ELLIPSE) { - sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); - } else { - sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); - } - fputs(buf, fp); - QPointArray& points = p.points(); - for (uint j = 0; j < points.count(); ++j) { - QPoint point = points.point(j); - sprintf(buf, "\t\t

\n", point.x(), point.y()); - fputs(buf, fp); - } - if (p.type() == FN_BEZIER) { - fputs("\t\n", fp); - } else if (p.type() == FN_ELLIPSE) { - fputs("\t\n", fp); - } else { - fputs("\t\n", fp); - } - } - fputs("\n", fp); - fclose(fp); - if (_isUseAllQuadrant) { - setOrigin(-o.x(), -o.y()); - } - FNMessageBox::information(0, "FreeNoteQt", "save complete."); - return true; -} - -bool FNCanvas::load(const QFileInfo& info) -{ - if (0 == info.fileName().length()) { - QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); - return false; - } - if (!info.exists()) { - QMessageBox::warning(0,"FreeNoteQt", "file not exists."); - return false; - } - FILE* fp = NULL; - if (!(fp = fopen(info.absFilePath().utf8(), "rt"))) { - QMessageBox::warning(0,"FreeNoteQt", "could not open file."); - return false; - } - clear(); - - QString line; - FNPointList points; - points.setAutoDelete(true); - int c; - int w; - QPen pen(Qt::black, 1); - FNPolygon* polygon; - - char rdbuf[1024]; - char buf[1024]; - QString type = ""; - while (!feof(fp)) { - fgets(rdbuf, sizeof(rdbuf), fp); - line = rdbuf; - if (-1 != line.find("setPoints(points); - points.clear(); - } - } - fclose(fp); - int x = 0; - int y = 0; - for (uint i = 0; i < _draws.count(); ++i) { - if (y > _draws.at(i)->boundingRect().top()) { - y = _draws.at(i)->boundingRect().top(); - } - if (x > _draws.at(i)->boundingRect().left()) { - x = _draws.at(i)->boundingRect().left(); - } - } - for (uint i = 0; i < _draws.count(); ++i) { - _draws.at(i)->translate(-x, -y); - } - redraw(); - FNMessageBox::information(0,"FreeNoteQt", "load complete."); - - return true; -} - -FNPolygon* FNCanvas::createPolygon(QPen& pen) -{ - return new FNPolygon(pen); -} - -FNPolygon* FNCanvas::createBezier(QPen& pen) -{ - return new FNBezier(pen); -} - - -FNPolygon* FNCanvas::createEllipse(QPen& pen) -{ - return new FNEllipse(pen); -} - -QPoint* FNCanvas::createPts(int x, int y) -{ - return new QPoint(x, y); -} - -void FNCanvas::setGuide(bool f) -{ - _isShowGuide = f; - redraw(); -} +/* FreeNote for Sharp SLA300, B500, C7x0 Linux PDA + Copyright (C) 2003 Joe Kanemori. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/* +2003/12/23 ver 1.6.1 +・保存情報のサイズ縮小 + +2003/12/16-19 ver 1.5.5pre +・ペンサイズの追加(1-8) +・アンドゥ・リドゥの実装 + +2003/12/14 ver 1.5.4pre +・ペンサイズを選択可能に。 + +2003/12/05 ver 1.5.3Apre +・グリッドの色を修正 + +2003/12/04 ver 1.5.3pre +・グリッドの描画を一部修正 + +2003/11/10 ver 1.5.1pre +・曲線整形モード追加 + +2003/11/09 ver 1.5.0pre +・自動整形モード追加 + +2003/09/03 ver 1.3.4pre +・Use all quadrant OFF時に表示位置がリセットされる場合があるバグ対応。 + +2003/09/01-03 ver 1.3.3pre +・スクロールの改良 +・Use all quadrant(全象限を使用する)メニューを追加 + +2003/08/31 FreeNote 1.3.2pre +・全方向スクロール + +2003/08/23 FreeNote 1.3.0pre +・CR動作の修正 + +2003/08/15 FreeNote 1.2.1を公開 +・保存時のバグ修正 +・完了ダイアログの自動消去 +・PNGファイルへの出力 + +2003/08/15 FreeNote 1.2を公開 +・オプション追加 +・スクロールガイド +・Freeファイル関連付け +・アイコンの変更 + +2003/08/05 FreeNote 1.1.1preを公開 +・高速起動時に閉じた状態を保持 +・描画モード切替え時に消しゴム表示 +・保存時間短縮 +・Viewモードの挙動を変更 +・メニューの見た目を変更 +*/ +#include "fncanvas.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // abs +#include "fnmessagebox.h" +#include "fmtengine.h" + +int snap(int v) { + int tv = abs(v); + tv = ((int)(tv + SNAP_SIZE / 2) / SNAP_SIZE) * SNAP_SIZE; + if (0 > v) { + return -tv; + } else { + return tv; + } +} + +FNCanvas::FNCanvas(QWidget* parent, const char* name, WFlags f ) + :QWidget(parent, name, f), + _pen(black, 1, SolidLine, RoundCap, RoundJoin), + _asMode(AS_NONE), + _drawMode(MODE_DRAW), + _disp_offset(0), + _eraser_l(50), + _eraser_s(10), + _h_step(100), + _v_step(100), + _margin(5), + _scrollTiming(800), + _viewMode(false), + _isWaiting(false), + _isDragging(false), + _isHeadingEnables(false), + _isShowGuide(false), + _isUseAllQuadrant(false), + _scale_x(1.0), + _scale_y(1.0) +{ + _tracks.setAutoDelete(true); + this->setBackgroundMode(NoBackground); + _timer = new QTimer(this); + connect(_timer, SIGNAL(timeout()), this, SLOT(autoScroll())); +} + +FNCanvas::~FNCanvas() +{ + _timer->stop(); + delete _timer; + + _tracks.clear(); + clearList(_draws); +} + +void FNCanvas::setScrollTiming(int v) +{ + _scrollTiming = v; +} + + +void FNCanvas::setVStep(int v) +{ + _v_step = v; +} + +void FNCanvas::setHStep(int v) +{ + _h_step = v; +} + +void FNCanvas::setSEraser(int v) +{ + _eraser_s = v; +} + +void FNCanvas::setLEraser(int v) +{ + _eraser_l = v; +} + + +void FNCanvas::setMargin(int v) +{ + if (v < 3) { + v = 3; + } + _margin = v; +} + +void FNCanvas::setScrollMode(int as) +{ + _asMode = as; + redraw(); +} + +void FNCanvas::autoScroll() +{ + if (AS_NONE == _asMode) { + if (MODE_FORMAT == _drawMode || MODE_CURVE == _drawMode || MODE_SMOOTH == _drawMode) { + setOrigin(_origin.x(), _origin.y()); + } + return; + } + bool tmp = _isHeadingEnables; + int dx = 0; + int dy = 0; + if (AS_BOTH == _asMode || AS_HORIZONTAL == _asMode) { + if (_last.x() > width() * (_margin - 1) / _margin) { + dx = _h_step; + } else if (_last.x() < width() / _margin) { + dx = -_h_step; + } + } + if (AS_BOTH == _asMode || AS_VERTICAL == _asMode) { + if (_last.y() > height() * (_margin - 1) / _margin) { + dy = _v_step; + } else if (_last.y() < height() / _margin) { + dy = -_v_step; + } + } + setOrigin(_origin.x() + dx, _origin.y() + dy); + _isHeadingEnables = tmp; +} + +void FNCanvas::mousePressEvent(QMouseEvent* evt) +{ + setFocus(); + _timer->stop(); + _tracks.clear(); + if (_viewMode) { + _isWaiting = true; + _viewMode = false; + setOrigin((int)((evt->x()) / _scale_x) - width() / 2, (int)((evt->y()) / _scale_y) - height() / 2); + redraw(); + emit resetViewMode(); + } else if (MODE_ERASE != _drawMode) { + _last = evt->pos(); + _tracks.append(new QPoint(_last)); + } else { + redraw(); + _last = evt->pos(); + _tracks.append(new QPoint(_last)); + + QPainter pbuf; + QPainter pwin; + pbuf.begin(&_buffer); + pwin.begin(this); + + int w = _eraser_s; + if (PENWIDTH_MAX / 2 < _pen.width()) { + w = _eraser_l; + } + pbuf.setRasterOp(XorROP); + pbuf.setPen(QPen(white, 1)); + pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + + pwin.setRasterOp(XorROP); + pwin.setPen(QPen(white, 1)); + pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + + pbuf.end(); + pwin.end(); + } + _isDragging = true; +} + +void FNCanvas::mouseMoveEvent(QMouseEvent* evt) +{ + if (_isWaiting) { + return; + } + if (MODE_ERASE != _drawMode) { + QPainter pwin; + QPainter pbuf; + + pwin.begin(this); + pbuf.begin(&_buffer); + + pwin.setPen(_pen); + pbuf.setPen(_pen); + + pwin.drawLine(_last, evt->pos()); + pbuf.drawLine(_last, evt->pos()); + + pwin.end(); + pbuf.end(); + _last = evt->pos(); + _tracks.append(new QPoint(_last)); + } else { + //redraw(); + if (_last.x() == -1) { + return; + } + QPainter pbuf; + QPainter pwin; + + pbuf.begin(&_buffer); + pwin.begin(this); + + int w = _eraser_s; + if (PENWIDTH_MAX / 2 < _pen.width()) { + w = _eraser_l; + } + pbuf.setRasterOp(XorROP); + pwin.setRasterOp(XorROP); + pbuf.setPen(QPen(white, 1)); + pwin.setPen(QPen(white, 1)); + pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + + _tracks.append(new QPoint(evt->pos())); + _last = evt->pos(); + + pbuf.setRasterOp(CopyROP); + pwin.setRasterOp(CopyROP); + QRect r = QRect(0, 0, width(), height()); + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + if (r.intersects(p->boundingRect())) { + bool f = false; + QRect selected(_last.x() - w / 2, _last.y() - w / 2, w, w); + for (uint j = 0; j < p->points().count(); ++j) { + QPoint& pts = p->points().at(j); + if (selected.contains(pts)) { + f = true; + break; + } + } + if (f) { + p->drawShape(pbuf, f); + p->drawShape(pwin, f); + } + } + } + pbuf.setRasterOp(XorROP); + pwin.setRasterOp(XorROP); + pbuf.setPen(QPen(white, 1)); + pwin.setPen(QPen(white, 1)); + pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + pwin.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + pbuf.end(); + pwin.end(); + } +} + +void FNCanvas::mouseReleaseEvent(QMouseEvent* evt) +{ + _isDragging = false; + if (_isWaiting) { + _isWaiting = false; + return; + } + _last = evt->pos(); + if (MODE_ERASE != _drawMode) { + if (1 < _tracks.count()) { + FNPolygon* p = NULL; + if (MODE_FORMAT == _drawMode) { + p = new FNPolygon(_pen); + _tracks = AutoFormat(_tracks); + } else if (MODE_CURVE == _drawMode) { + QPoint sp = SnapPoint(*_tracks.at(0)); + QPoint ep = SnapPoint(*_tracks.at(_tracks.count()-1)); + _tracks = AutoCurve(_tracks); + if (sp == ep) { + p = new FNEllipse(_pen); + } else if (2 < _tracks.count()) { + p = new FNBezier(_pen); + } else { + p = new FNPolygon(_pen); + } + } else if (MODE_SMOOTH == _drawMode) { + _tracks = Smoothing(_tracks); + if (2 < _tracks.count()) { + p = new FNBezier(_pen); + } else { + p = new FNPolygon(_pen); + } + } else { + _tracks = Reduce(_tracks); + p = new FNPolygon(_pen); + } + if (1 < _tracks.count()) { + p->setPoints(_tracks); + redobuf_flush(); + _draws.append(p); + } + } + _tracks.clear(); + _isHeadingEnables = true; + _timer->start(_scrollTiming, true); + } else { + _last = QPoint(-1, -1); + _tracks.append(new QPoint(evt->pos())); + redraw(); + } +} + +void FNCanvas::paintEvent(QPaintEvent* evt) +{ + bitBlt(this, 0, 0, &_buffer); +} + +void FNCanvas::resizeEvent(QResizeEvent* evt) +{ + QPixmap save(_buffer); + _buffer.resize(evt->size()); + _buffer.fill(white); + bitBlt(&_buffer, 0, 0, &save); + redraw(); +} + +void FNCanvas::setOrigin(QPoint& o) +{ + this->setOrigin(o.x(), o.y()); +} + +QPoint FNCanvas::getTopLeft() +{ + if (0 == _draws.count() || !_isUseAllQuadrant) { + return _origin; + } + + int dx = ((FNPolygon*)_draws.at(0))->boundingRect().x(); + int dy = ((FNPolygon*)_draws.at(0))->boundingRect().y(); + for (uint i = 1; i < _draws.count(); ++i) { + FNPolygon* p = _draws.at(i); + if (dx > p->boundingRect().x()) { + dx = p->boundingRect().x(); + } + if (dy > p->boundingRect().y()) { + dy = p->boundingRect().y(); + } + } + return QPoint(snap(dx), snap(dy)); +} + + +void FNCanvas::rebuild() +{ + if (0 == _draws.count() || !_isUseAllQuadrant) { + return; + } + + QPoint d = getTopLeft(); + for (uint i = 0; i < _draws.count(); ++i) { + FNPolygon* p = _draws.at(i); + p->translate(-d.x(), -d.y()); + } + + _origin = QPoint(0, 0); +} + + +void FNCanvas::setOrigin(int ox, int oy) +{ + ox = snap(ox); + oy = snap(oy); + _isHeadingEnables = false; + _timer->stop(); + + + int dx = 0; + int dy = 0; + if (!_isUseAllQuadrant) { + if (0 > ox) { + ox = 0; + } + if (0 > oy) { + oy = 0; + } + dx = _origin.x() - ox; + dy = _origin.y() - oy; + } else { + dx = _origin.x() - ox; + dy = _origin.y() - oy; + if (0 > ox) { + ox = 0; + } + if (0 > oy) { + oy = 0; + } + } + for (uint i = 0; i < _tracks.count(); ++i) { + QPoint* p = _tracks.at(i); + p->setX(p->x() + dx); + p->setY(p->y() + dy); + } + + for (uint i = 0; i < _draws.count(); ++i) { + FNPolygon* p = _draws.at(i); + p->translate(dx, dy); + } + _origin = QPoint(ox, oy); + emit originChanged(ox, oy); + redraw(); +} + +void FNCanvas::redraw() +{ + if (!this->isVisible()) { + return; + } + _buffer.fill(white); + QPainter pbuf; + QRect r = QRect(0, 0, width(), height()); + pbuf.begin(&_buffer); + if (_viewMode) { + float wx = 0; + float wy = 0; + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + QRect r = p->boundingRect(); + if (wx < r.right()) { + wx = r.right(); + } + if (wy < r.bottom()) { + wy = r.bottom(); + } + } + wx += SNAP_SIZE; + wy += SNAP_SIZE; + wx = snap((int)wx); + wy = snap((int)wy); + wx = wx + _origin.x(); + wy = wy + _origin.y(); + _scale_x = (float)width() / wx; + _scale_y = (float)height() / wy; + if (1.0f < _scale_x) { + _scale_x = 1.0f; + } + if (1.0f < _scale_y) { + _scale_y = 1.0f; + } + if (_scale_x > _scale_y) { + _scale_x = _scale_y; + } else if (_scale_x < _scale_y) { + _scale_y = _scale_x; + } + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + FNPolygon* t = NULL; + if (p->type() == FN_BEZIER) { + t = new FNBezier(*(FNBezier*)p); + } else if (p->type() == FN_ELLIPSE) { + t = new FNEllipse(*(FNEllipse*)p); + } else { + t = new FNPolygon(*p); + } + t->translate(-_origin.x(), -_origin.y()); + for (uint j = 0; j < t->points().count(); ++j) { + QPoint& pts = t->points().at(j); + int x = (int)(pts.x() * _scale_x); + int y = (int)(pts.y() * _scale_y); + pts.setX(x); + pts.setY(y); + } + double pensize = t->pen().width(); + if (_scale_x > _scale_y) { + pensize = pensize * _scale_y; + } else { + pensize = pensize * _scale_x; + } + if (0 >= pensize) { + pensize = 1; + } + t->pen().setWidth(pensize); + t->drawShape(pbuf); + delete t; + } + } else if (MODE_ERASE != _drawMode) { + if (MODE_FORMAT == _drawMode || MODE_CURVE == _drawMode) { + QPen pen1(QColor(0, 240, 240), 1); + QPen pen2(QColor(0, 0, 0), 1); + pbuf.setPen(QPen(QColor(0, 240, 240), 1)); + pbuf.setPen(pen1); + for (int x = 0; x < width() + SNAP_SIZE; x += SNAP_SIZE) { + pbuf.drawLine(x - SNAP_SIZE / 2, 0, x - SNAP_SIZE / 2, height()); + for (int y = 0; y < height() + SNAP_SIZE; y += SNAP_SIZE) { + pbuf.drawLine(0, y - SNAP_SIZE / 2, width(), y - SNAP_SIZE / 2); + pbuf.drawRect(x-1,y-1,2,2); + } + } + } + if (_isShowGuide) { + pbuf.setPen(QPen(cyan, 1, DashLine)); + if (AS_HORIZONTAL == _asMode || AS_BOTH == _asMode) { + if (0 != _origin.x() || _isUseAllQuadrant) { + pbuf.drawLine(width() / _margin, 0, width() / _margin, height()); + } + pbuf.drawLine(width() * (_margin - 1) / _margin, 0, width() * (_margin - 1) / _margin, height()); + } + + if (AS_VERTICAL == _asMode || AS_BOTH == _asMode) { + if (0 != _origin.y() || _isUseAllQuadrant) { + pbuf.drawLine(0, height() / _margin, width(), height() / _margin); + } + pbuf.drawLine(0, height() * (_margin - 1) / _margin, width(), height() * (_margin - 1) / _margin); + } + } + + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + if (r.intersects(p->boundingRect())) { + p->drawShape(pbuf); + } + } + } else { + int w = _eraser_s; + if (PENWIDTH_MAX / 2 < _pen.width()) { + w = _eraser_l; + } + FNPointList removes; + for (uint i = 0; i < _tracks.count(); ++i) { + removes.append(_tracks.at(i)); + } + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + if (r.intersects(p->boundingRect())) { + bool f = false; + for (uint j = 0; j < _tracks.count(); ++j) { + QPoint* pts = _tracks.at(j); + QRect selected(pts->x() - w / 2, pts->y() - w / 2, w, w); + for (uint k = 0; k < p->points().count(); ++k) { + QPoint& pts2 = p->points().at(k); + if (selected.contains(pts2)) { + f = true; + removes.remove(pts); + break; + } + } + if (f) { + break; + } + } + p->drawShape(pbuf, f); + } + } + for (uint i = 0; i < removes.count(); ++i) { + _tracks.remove(removes.at(i)); + } + /* + if (_isDragging) { + pbuf.setPen(QPen(black, 1)); + pbuf.drawRect(_last.x() - w / 2, _last.y() - w / 2, w, w); + } + */ + } + pbuf.end(); + repaint(); +} + +void FNCanvas::changeColor(QRgb c) +{ + _pen.setColor(QColor(c)); +} + +void FNCanvas::undo() +{ + if (MODE_ERASE != _drawMode) { + ++_disp_offset; + if (_disp_offset > _draws.count()) { + _disp_offset = _draws.count(); + } + } else { + _draws = _undobuf; + _marks.clear(); + } + redraw(); +} + +void FNCanvas::redo() +{ + if (MODE_ERASE != _drawMode) { + if (0 < _disp_offset) { + --_disp_offset; + } + } + redraw(); +} + +void FNCanvas::clearList(FNPolygonList& list) +{ + list.setAutoDelete(true); + list.clear(); + list.setAutoDelete(false); +} + +void FNCanvas::clear() +{ + _disp_offset = 0; + clearList(_draws); + _undobuf.clear(); + setOrigin(0, 0); + redraw(); +} + +void FNCanvas::viewChanged(bool flg) +{ + _tracks.clear(); + _viewMode = flg; + if (_viewMode) { + if (_isUseAllQuadrant) { + rebuild(); + } + setOrigin(0, 0); + } + redraw(); +} + +void FNCanvas::redobuf_flush() +{ + for (uint i = 0; i < _disp_offset; ++i) { + FNPolygon* p = _draws.last(); + _draws.remove(p); + delete p; + } + _disp_offset = 0; +} + +void FNCanvas::modeChanged(int mode) +{ + _tracks.clear(); + _drawMode = mode; + redobuf_flush(); + if (MODE_ERASE == _drawMode) { + _marks.clear(); + _undobuf = _draws; + } else { + if (_draws.count() != _undobuf.count()) { + for (uint i = 0; i < _marks.count(); ++i) { + FNPolygon* p = _marks.at(i); + _draws.remove(p); + } + clearList(_marks); + } + } + redraw(); +} + +QRect FNCanvas::getMatrix(const QRect& r) const +{ + int ox = _origin.x(); + int oy = _origin.y(); + const int wide = 100; + + int left = r.left() + ox; + int top = r.top() + oy; + int right = r.right() + ox; + int bottom = r.bottom() + oy; + + left = (int)(left / wide) * wide; + top = (int)(top / wide) * wide; + right = (right % wide == 0 && left != right) ? right : (int)((right + wide) / wide) * wide; + bottom = (bottom % wide == 0 && top != bottom) ? bottom : (int)((bottom + wide) / wide) * wide; + + return QRect(left - ox, top - oy, right - left, bottom - top); +} + +void FNCanvas::CR() +{ + if (MODE_ERASE == _drawMode) { + return; + } + if (_isHeadingEnables) { + //lastから、左方向に向けて探索する。 + QRect r = getMatrix(_draws.last()->boundingRect()); + bool isSearching = true; + r.moveBy(-100, 0); + while (isSearching) { + isSearching = false; + for (uint i = 0; i < _draws.count(); ++i) { + FNPolygon* p = _draws.at(i); + const QRect& r2 = p->boundingRect(); + if (r.intersects(r2)) { + if (r.left() + 100 > r2.left()) { + r = getMatrix(r2); + r.moveBy(-100, 0); + isSearching = true; + break; + } + } + } + } + r.moveBy(100, 0); + //lastが画面の4/5以下ならば、スクロールアップする。 + //そうでなければ、ヘッディングのみ。 + if (_last.y() > height() * 4 / 5) { + setOrigin(_origin.x() + r.x(), _origin.y() + 50); + } else { + setOrigin(_origin.x() + r.x(), _origin.y()); + } + _isHeadingEnables = false; + } else { + //lastの周囲に何も無い場合は、縦にスクロールする。 + setOrigin(_origin.x(), _origin.y() + 50); + } +} + +void FNCanvas::erase() +{ + if (MODE_ERASE != _drawMode) { + return; + } + FNPolygonList temp; + int w = _eraser_s; + if (PENWIDTH_MAX / 2 < _pen.width()) { + w = _eraser_l; + } + QRect r = QRect(0, 0, width(), height()); + for (uint i = 0; i < _draws.count(); ++i) { + FNPolygon* p = _draws.at(i); + bool f = false; + if (r.intersects(p->boundingRect())) { + for (uint j = 0; j < _tracks.count(); ++j) { + QPoint* pts = _tracks.at(j); + QRect selected(pts->x() - w / 2, pts->y() - w / 2, w, w); + for (uint k = 0; k < p->points().count(); ++k) { + QPoint& pts2 = p->points().at(k); + if (selected.contains(pts2)) { + temp.append(p); + f = true; + break; + } + } + if (f) { + break; + } + } + } + } + for (uint i = 0; i < temp.count(); ++i) { + _draws.remove(temp.at(i)); + _marks.append(temp.at(i)); + } + _tracks.clear(); + redraw(); +} + +void FNCanvas::setPensize(int sz) +{ + _pen.setWidth(sz); +} + +bool FNCanvas::exportPNG(const QFileInfo& info, QPixmap& buf) +{ + if (0 == info.fileName().length()) { + QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); + return false; + } + if (info.extension(false) != "png") { + QMessageBox::warning(0,"FreeNoteQt", "extension '.png' expected."); + return false; + } + + bool ret = buf.save(info.absFilePath(), "PNG"); + if (ret) { + FNMessageBox::information(0,"FreeNoteQt", "export PNG complete."); + } else { + QMessageBox::warning(0,"FreeNoteQt", "could not export file."); + } + return ret; +} + +QString FNCanvas::mkPDFscript(FNPolygon* elm) +{ + QString s =""; + char buf[1024]; + + float r = (float)elm->pen().color().red() / 255.0f; + float g = (float)elm->pen().color().green() / 255.0f; + float b = (float)elm->pen().color().blue() / 255.0f; + s += "q\n"; + sprintf(buf, "%f %f %f RG\n", r, g, b); + s += buf; + QPointArray points = elm->points().copy(); + points.translate(_origin.x(), _origin.y()); + if (elm->type() == FN_BEZIER) { + sprintf(buf, "%d %d m\n", points[0].x(), points[0].y()); + s += buf; + for (uint j = 1; j < points.count(); j += 3) { + sprintf(buf, "%d %d %d %d %d %d c\n", + points[j].x(), points[j].y(), + points[j + 1].x(), points[j + 1].y(), + points[j + 2].x(), points[j + 2].y() + ); + s += buf; + } + } else if (elm->type() == FN_ELLIPSE) { + int x = points[0].x(); + int y = points[0].y(); + int ex = points[1].x(); + int ey = points[1].y(); + int w = ex - x; + int h = ey - y; + int cx = x + w/2; + int cy = y; + int x1 = x + 3*w/4; + int y1 = y; + int x2 = x + w; + int y2 = y + h/4; + int x3 = x + w; + int y3 = y + h/2; + + sprintf(buf, "%d %d m\n%d %d %d %d %d %d c\n", cx, cy, x1, y1, x2, y2, x3, y3); + s += buf; + x1 = x + w; + y1 = y + 3 * h / 4; + x2 = x + 3 * w / 4; + y2 = y + h; + x3 = x + w/2; + y3 = y + h; + sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); + s += buf; + + x1 = x + w / 4; + y1 = y + h; + x2 = x; + y2 = y + 3 * h / 4; + x3 = x; + y3 = y + h / 2; + sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); + s += buf; + x1 = x; + y1 = y + h / 4; + x2 = x + w / 4; + y2 = y; + x3 = x + w / 2; + y3 = y; + sprintf(buf, "%d %d %d %d %d %d c\n", x1, y1, x2, y2, x3, y3); + s += buf; + } else { + sprintf(buf, "%d %d m\n", points[0].x(), points[0].y()); + s += buf; + for (uint j = 1; j < points.count(); ++j) { + sprintf(buf, "%d %d l\n", points[j].x(), points[j].y()); + s += buf; + } + } + sprintf(buf, "%d w\n", elm->pen().width()); + s += buf; + s += "S\n"; + s += "Q\n"; + return s; +} + +bool FNCanvas::exportPDF(const QFileInfo& info) +{ + if (0 == info.fileName().length()) { + QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); + return false; + } + if (info.extension(false) != "pdf") { + QMessageBox::warning(0,"FreeNoteQt", "extension '.pdf' expected."); + return false; + } + + FILE* fp = NULL; + if (!(fp = fopen(info.absFilePath().utf8(), "wt"))) { + QMessageBox::warning(0,"FreeNoteQt", "could not export file."); + return false; + } + + QPoint o = getTopLeft(); + rebuild(); + int wx = 595; + int wy = 842; + char buf[1024]; + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon* p = _draws.at(i); + QRect r = p->boundingRect(); + r.moveBy(_origin.x(), _origin.y()); + if (wx < r.right()) { + wx =r.right(); + } + if (wy < r.bottom()) { + wy = r.bottom(); + } + } + + int len = 0; + + sprintf(buf, "1 0 0 -1 0 %d cm\n", wy); + QString cm = buf; + len += cm.length(); + + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + QString s = mkPDFscript(_draws.at(i)); + len += s.length(); + } + + QString header = ""; + header += "%PDF-1.3\n"; + header += "1 0 obj\n"; + header += "<<\n"; + header += "/Type /Page\n"; + header += "/Parent 3 0 R\n"; + header += "/Resources\n"; + header += "<<\n"; + header += "/ProcSet [ /PDF ]\n"; + header += ">>\n"; + sprintf(buf, "/MediaBox [ 0 0 %010d %010d ]\n", wx, wy); + header += buf; + header += "/Contents 4 0 R\n"; + header += ">>\n"; + header += "endobj\n"; + header += "2 0 obj\n"; + header += "<<\n"; + header += "/Type /Catalog\n"; + header += "/Pages 3 0 R\n"; + header += "/PageLayout /OneColumn\n"; + header += "/OpenAction [1 0 R /XYZ null null 1 ]\n"; + header += ">>\n"; + header += "endobj\n"; + header += "3 0 obj\n"; + header += "<<\n"; + header += "/Type /Pages\n"; + header += "/Kids [ 1 0 R ]\n"; + header += "/Count 1\n"; + header += ">>\n"; + header += "endobj\n"; + header += "4 0 obj\n"; + sprintf(buf, "<< /Length %010d >>\n", len); + header += buf; + header += "stream\n"; + + QString footer = ""; + footer += "xref\n"; + footer += "0 5\n"; + footer += "0000000000 65535 f \n"; + footer += "0000000009 00000 n \n"; + footer += "0000000147 00000 n \n"; + footer += "0000000257 00000 n \n"; + footer += "0000000316 00000 n \n"; + footer += "trailer\n"; + footer += "<<\n"; + footer += "/Size 5\n"; + footer += "/Root 2 0 R\n"; + footer += ">>\n"; + footer += "startxref\n"; + + len = cm.length(); + len += header.length(); + fputs(header, fp); + fputs(cm, fp); + + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + QString s = mkPDFscript(_draws.at(i)); + len += s.length(); + fputs(s, fp); + } + QString streamfooter = "endstream\nendobj\n"; + len += streamfooter.length(); + fputs(streamfooter, fp); + + fputs(footer, fp); + sprintf(buf, "%d\n", len); + fputs(buf, fp); + fputs("%%EOF\n", fp); + fclose(fp); + if (_isUseAllQuadrant) { + setOrigin(-o.x(), -o.y()); + } + FNMessageBox::information(0,"FreeNoteQt", "export PDF complete."); + return true; +} + +bool FNCanvas::save(const QFileInfo& info) +{ + if (0 == info.fileName().length()) { + QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); + return false; + } + if (info.extension(false) != "free") { + QMessageBox::warning(0,"FreeNoteQt", "extension '.free' expected."); + return false; + } + FILE* fp = NULL; + if (!(fp = fopen(info.absFilePath().utf8(), "wt"))) { + QMessageBox::warning(0,"FreeNoteQt", "could not save file."); + return false; + } + QPoint o = getTopLeft(); + rebuild(); + fputs("\n", fp); + fputs("\n", fp); + char buf[1024]; + for (uint i = 0; i < _draws.count() - _disp_offset; ++i) { + FNPolygon p(*_draws.at(i)); + p.translate(_origin.x(), _origin.y()); + if (p.type() == FN_BEZIER) { + sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); + } else if (p.type() == FN_ELLIPSE) { + sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); + } else { + sprintf(buf, "\t\n", (uint)p.pen().color().rgb(), p.pen().width()); + } + fputs(buf, fp); + QPointArray& points = p.points(); + for (uint j = 0; j < points.count(); ++j) { + QPoint point = points.point(j); + sprintf(buf, "\t\t

\n", point.x(), point.y()); + fputs(buf, fp); + } + if (p.type() == FN_BEZIER) { + fputs("\t\n", fp); + } else if (p.type() == FN_ELLIPSE) { + fputs("\t\n", fp); + } else { + fputs("\t\n", fp); + } + } + fputs("\n", fp); + fclose(fp); + if (_isUseAllQuadrant) { + setOrigin(-o.x(), -o.y()); + } + FNMessageBox::information(0, "FreeNoteQt", "save complete."); + return true; +} + +bool FNCanvas::load(const QFileInfo& info) +{ + if (0 == info.fileName().length()) { + QMessageBox::warning(0,"FreeNoteQt", "file name is empty."); + return false; + } + if (!info.exists()) { + QMessageBox::warning(0,"FreeNoteQt", "file not exists."); + return false; + } + FILE* fp = NULL; + if (!(fp = fopen(info.absFilePath().utf8(), "rt"))) { + QMessageBox::warning(0,"FreeNoteQt", "could not open file."); + return false; + } + clear(); + + QString line; + FNPointList points; + points.setAutoDelete(true); + int c; + int w; + QPen pen(Qt::black, 1); + FNPolygon* polygon; + + char rdbuf[1024]; + char buf[1024]; + QString type = ""; + while (!feof(fp)) { + fgets(rdbuf, sizeof(rdbuf), fp); + line = rdbuf; + if (-1 != line.find("setPoints(points); + points.clear(); + } + } + fclose(fp); + int x = 0; + int y = 0; + for (uint i = 0; i < _draws.count(); ++i) { + if (y > _draws.at(i)->boundingRect().top()) { + y = _draws.at(i)->boundingRect().top(); + } + if (x > _draws.at(i)->boundingRect().left()) { + x = _draws.at(i)->boundingRect().left(); + } + } + for (uint i = 0; i < _draws.count(); ++i) { + _draws.at(i)->translate(-x, -y); + } + redraw(); + FNMessageBox::information(0,"FreeNoteQt", "load complete."); + + return true; +} + +FNPolygon* FNCanvas::createPolygon(QPen& pen) +{ + return new FNPolygon(pen); +} + +FNPolygon* FNCanvas::createBezier(QPen& pen) +{ + return new FNBezier(pen); +} + + +FNPolygon* FNCanvas::createEllipse(QPen& pen) +{ + return new FNEllipse(pen); +} + +QPoint* FNCanvas::createPts(int x, int y) +{ + return new QPoint(x, y); +} + +void FNCanvas::setGuide(bool f) +{ + _isShowGuide = f; + redraw(); +}