From cf3ec188764cdf34ff3472ee9806aba3a772d2df Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Sun, 18 Nov 2012 04:22:58 +0000 Subject: [PATCH] Added rotation tool, save/load capability. --- Makefile | 48 ++-- res/cursor5.png | Bin 327 -> 259 bytes res/cursor6.png | Bin 336 -> 327 bytes res/cursor7.png | Bin 316 -> 336 bytes res/cursor8.png | Bin 322 -> 316 bytes res/cursor9.png | Bin 0 -> 322 bytes res/toolpal1.xpm | 98 ++++---- src/charwindow.cpp | 3 +- src/editwindow.cpp | 264 +++++++++++++++++----- src/editwindow.h | 7 +- src/glyphpoints.cpp | 240 +++++++++++++++++++- src/glyphpoints.h | 15 +- src/{ttemainwindow.cpp => mainwindow.cpp} | 128 ++++++++++- src/{ttemainwindow.h => mainwindow.h} | 58 ++--- src/toolwindow.cpp | 13 +- src/toolwindow.h | 1 + src/ttedit.cpp | 4 +- src/ttedit.h | 5 +- src/vector.cpp | 259 ++++++++++++++++++++- src/vector.h | 66 ++++++ ttedit.pro | 4 +- ttedit.qrc | 1 + 22 files changed, 1021 insertions(+), 193 deletions(-) create mode 100644 res/cursor9.png rename src/{ttemainwindow.cpp => mainwindow.cpp} (76%) rename src/{ttemainwindow.h => mainwindow.h} (54%) diff --git a/Makefile b/Makefile index 30e8c20..d5dcd62 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ ############################################################################# # Makefile for building: ttedit -# Generated by qmake (2.01a) (Qt 4.8.2) on: Fri Sep 14 09:37:18 2012 +# Generated by qmake (2.01a) (Qt 4.8.3) on: Sat Nov 17 12:34:10 2012 # Project: ttedit.pro # Template: app # Command: /usr/bin/qmake -o Makefile ttedit.pro @@ -16,7 +16,7 @@ CXXFLAGS = -pipe -O2 -D_REENTRANT -Wall -W $(DEFINES) INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -Iobj LINK = g++ LFLAGS = -Wl,-O1 -LIBS = $(SUBLIBS) -L/usr/lib64/qt4 -lQtGui -L/usr/lib64 -L/usr/lib64/qt4 -L/usr/X11R6/lib -lQtCore -lglib-2.0 -lgthread-2.0 -lrt -lpthread +LIBS = $(SUBLIBS) -L/usr/lib64/qt4 -lQtGui -L/usr/lib64 -L/usr/lib64/qt4 -L/usr/X11R6/lib -lQtCore -lgthread-2.0 -lrt -lglib-2.0 -lpthread AR = ar cqs RANLIB = QMAKE = /usr/bin/qmake @@ -44,20 +44,20 @@ OBJECTS_DIR = obj/ ####### Files SOURCES = src/ttedit.cpp \ - src/ttemainwindow.cpp \ + src/mainwindow.cpp \ src/editwindow.cpp \ src/glyphpoints.cpp \ src/debug.cpp \ src/toolwindow.cpp \ src/charwindow.cpp \ src/vector.cpp \ - src/graphicprimitives.cpp obj/moc_ttemainwindow.cpp \ + src/graphicprimitives.cpp obj/moc_mainwindow.cpp \ obj/moc_editwindow.cpp \ obj/moc_toolwindow.cpp \ obj/moc_charwindow.cpp \ obj/qrc_ttedit.cpp OBJECTS = obj/ttedit.o \ - obj/ttemainwindow.o \ + obj/mainwindow.o \ obj/editwindow.o \ obj/glyphpoints.o \ obj/debug.o \ @@ -65,7 +65,7 @@ OBJECTS = obj/ttedit.o \ obj/charwindow.o \ obj/vector.o \ obj/graphicprimitives.o \ - obj/moc_ttemainwindow.o \ + obj/moc_mainwindow.o \ obj/moc_editwindow.o \ obj/moc_toolwindow.o \ obj/moc_charwindow.o \ @@ -184,7 +184,7 @@ qmake: FORCE dist: @$(CHK_DIR_EXISTS) obj/ttedit1.0.0 || $(MKDIR) obj/ttedit1.0.0 - $(COPY_FILE) --parents $(SOURCES) $(DIST) obj/ttedit1.0.0/ && $(COPY_FILE) --parents src/ttedit.h src/ttemainwindow.h src/editwindow.h src/glyphpoints.h src/types.h src/debug.h src/toolwindow.h src/charwindow.h src/vector.h src/graphicprimitives.h src/list.h obj/ttedit1.0.0/ && $(COPY_FILE) --parents ttedit.qrc obj/ttedit1.0.0/ && $(COPY_FILE) --parents src/ttedit.cpp src/ttemainwindow.cpp src/editwindow.cpp src/glyphpoints.cpp src/debug.cpp src/toolwindow.cpp src/charwindow.cpp src/vector.cpp src/graphicprimitives.cpp obj/ttedit1.0.0/ && (cd `dirname obj/ttedit1.0.0` && $(TAR) ttedit1.0.0.tar ttedit1.0.0 && $(COMPRESS) ttedit1.0.0.tar) && $(MOVE) `dirname obj/ttedit1.0.0`/ttedit1.0.0.tar.gz . && $(DEL_FILE) -r obj/ttedit1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) obj/ttedit1.0.0/ && $(COPY_FILE) --parents src/ttedit.h src/mainwindow.h src/editwindow.h src/glyphpoints.h src/types.h src/debug.h src/toolwindow.h src/charwindow.h src/vector.h src/graphicprimitives.h src/list.h obj/ttedit1.0.0/ && $(COPY_FILE) --parents ttedit.qrc obj/ttedit1.0.0/ && $(COPY_FILE) --parents src/ttedit.cpp src/mainwindow.cpp src/editwindow.cpp src/glyphpoints.cpp src/debug.cpp src/toolwindow.cpp src/charwindow.cpp src/vector.cpp src/graphicprimitives.cpp obj/ttedit1.0.0/ && (cd `dirname obj/ttedit1.0.0` && $(TAR) ttedit1.0.0.tar ttedit1.0.0 && $(COMPRESS) ttedit1.0.0.tar) && $(MOVE) `dirname obj/ttedit1.0.0`/ttedit1.0.0.tar.gz . && $(DEL_FILE) -r obj/ttedit1.0.0 clean:compiler_clean @@ -205,11 +205,11 @@ mocclean: compiler_moc_header_clean compiler_moc_source_clean mocables: compiler_moc_header_make_all compiler_moc_source_make_all -compiler_moc_header_make_all: obj/moc_ttemainwindow.cpp obj/moc_editwindow.cpp obj/moc_toolwindow.cpp obj/moc_charwindow.cpp +compiler_moc_header_make_all: obj/moc_mainwindow.cpp obj/moc_editwindow.cpp obj/moc_toolwindow.cpp obj/moc_charwindow.cpp compiler_moc_header_clean: - -$(DEL_FILE) obj/moc_ttemainwindow.cpp obj/moc_editwindow.cpp obj/moc_toolwindow.cpp obj/moc_charwindow.cpp -obj/moc_ttemainwindow.cpp: src/ttemainwindow.h - /usr/bin/moc $(DEFINES) $(INCPATH) src/ttemainwindow.h -o obj/moc_ttemainwindow.cpp + -$(DEL_FILE) obj/moc_mainwindow.cpp obj/moc_editwindow.cpp obj/moc_toolwindow.cpp obj/moc_charwindow.cpp +obj/moc_mainwindow.cpp: src/mainwindow.h + /usr/bin/moc $(DEFINES) $(INCPATH) src/mainwindow.h -o obj/moc_mainwindow.cpp obj/moc_editwindow.cpp: src/types.h \ src/toolwindow.h \ @@ -242,6 +242,7 @@ obj/qrc_ttedit.cpp: ttedit.qrc \ res/act-charwin.png \ res/act-forward.png \ res/cursor2.png \ + res/cursor9.png \ res/cursor4.png /usr/bin/rcc -name ttedit ttedit.qrc -o obj/qrc_ttedit.cpp @@ -263,15 +264,15 @@ compiler_clean: compiler_moc_header_clean compiler_rcc_clean ####### Compile obj/ttedit.o: src/ttedit.cpp src/ttedit.h \ - src/ttemainwindow.h + src/mainwindow.h $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/ttedit.o src/ttedit.cpp -obj/ttemainwindow.o: src/ttemainwindow.cpp src/ttemainwindow.h \ - src/editwindow.h \ +obj/mainwindow.o: src/mainwindow.cpp src/mainwindow.h \ + src/charwindow.h \ + src/glyphpoints.h \ src/types.h \ + src/editwindow.h \ src/toolwindow.h \ - src/glyphpoints.h \ - src/charwindow.h \ src/ttedit.h \ src/debug.h \ res/cur1.xpm \ @@ -286,17 +287,18 @@ obj/ttemainwindow.o: src/ttemainwindow.cpp src/ttemainwindow.h \ res/tool1.xpm \ res/tool2.xpm \ res/tool3.xpm - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/ttemainwindow.o src/ttemainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/mainwindow.o src/mainwindow.cpp obj/editwindow.o: src/editwindow.cpp src/editwindow.h \ src/types.h \ src/toolwindow.h \ src/glyphpoints.h \ - src/graphicprimitives.h \ - src/debug.h \ - src/vector.h \ src/charwindow.h \ - src/ttedit.h + src/debug.h \ + src/graphicprimitives.h \ + src/mainwindow.h \ + src/ttedit.h \ + src/vector.h $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/editwindow.o src/editwindow.cpp obj/glyphpoints.o: src/glyphpoints.cpp src/glyphpoints.h \ @@ -324,8 +326,8 @@ obj/graphicprimitives.o: src/graphicprimitives.cpp src/graphicprimitives.h \ src/types.h $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/graphicprimitives.o src/graphicprimitives.cpp -obj/moc_ttemainwindow.o: obj/moc_ttemainwindow.cpp - $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_ttemainwindow.o obj/moc_ttemainwindow.cpp +obj/moc_mainwindow.o: obj/moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_mainwindow.o obj/moc_mainwindow.cpp obj/moc_editwindow.o: obj/moc_editwindow.cpp $(CXX) -c $(CXXFLAGS) $(INCPATH) -o obj/moc_editwindow.o obj/moc_editwindow.cpp diff --git a/res/cursor5.png b/res/cursor5.png index 234c1f3a53d75b9a1837097d05cbf404555501e7..f6e85fe49a9e0a3369e0f7ca0a8df9f8f4a24b46 100644 GIT binary patch delta 184 zcmV;p07w7F0)qmOHwobYPykTtASzUmKp=k$77ifP0>}~o004tYL_t(o!|j&A4!|G? zL!sIK|8jSkiF0#$q3l2t69p0;8dNhgBT38Bm7G}+XcKo&*$MQE3y0000=W7Hwpg${{a7>y{D6rKp=k%0tz<5LW@!W0075HL_t(o!|j&a4#Xe` zL}9Z3|I6%4ZQKcKtrvKaq=`i$#}O|gB4TDHS#~A2EC`f_s-`G``X>Vd?1+Yd=Zu8F zzm6yfv^pao@D#8c0zE+<#40HC2G$T}W~-F>Je-mYp`H?|s#^d`QcCut$}9wU#`S0f zS>{WDJEpW}6hNK4XCRK5NiHIyo`ftl!*Lx<*T996&!H6nxn0000=W7Vt)!Y!a|Eu0002TNkl+YZDa2t;AB|NqPEOKscaz`u?t2(&sQAn+8h8v;E+ z9>gjr^aj=tW@f9D`8=GG456M9s;XN6N>WPpqslAX*2+3^4zy0j)Hmdc n^}n~_AVla=9XodH*f#qD@aeDht~DZr00000NkvXXu0mjf#2RV6 delta 246 zcmVd&u3i!b zWw1L>(};*jM1*$P4KBM#ur2^>QG)Z$4ia2CR+HeGvqvJ5Ah!-$Bt%3aRpPJ15~u`? zAOVf2b5$QgwKMd7FsneWgn}s+6;!DwAr2G>a1;Jvbc%!gygjvZTS7u>?m(d&u3i!b zWw1L>(};*jM1*$P4KBM#ur2^>QG)Z$4ia2CR+HeGvqvJ5Ah!-$Bt%3aRpPJ15~u`? zAOVf2b5$QgwKMd7FsneWgn}s+6;!DwAr2G>a1;Jvbc%!gygjvZTS7u>?m((GG?n2!%PU_kZQ{-(+*ducd)E zvb7aD_&O*mA|fOytL#k9RS;TU04z~L>yH%>Y8}}S>NztZ^xr@hgti7VAhb6j8bY5; ziiFUo6QdxGPM5S0@E`yn1i%I-NiWywAA&#~wESEhi{uR=L|cK9s8{EiWNti9LMwGo zg=q!e1n}0u%o=!gPbfa`8Qr3-vjA3lyG6ff3!1s$hWbFOGcLVDeo_Bx8xBIGmTKF! cZQH`^2Z)@U16CTe8vpb%7 diff --git a/res/cursor8.png b/res/cursor8.png index 1a7ffdc7834a833c72a3f129a0670c6cff2c039b..b34c46dfa35371361cdaffb6ad3e25d3fbb23e61 100644 GIT binary patch delta 226 zcmV<803H9r0=xo{Vt))2L3nL20002INkl(GG?n2!%PU_kZQ{-(+*ducd)E zvb7aD_&O*mA|fOytL#k9RS;TU04z~L>yH%>Y8}}S>NztZ^xr@hgti7VAhb6j8bY5; ziiFUo6QdxGPM5S0@E`yn1i%I-NiWywAA&#~wESEhi{uR=L|cK9s8{EiWNti9LMwGo zg=q!e1n}0u%o=!gPbfa`8Qr3-vjA3lyG6ff3!1s$hWbFOGcLVDeo_Bx8xBIGmTKF! cZQH`^2Z)@U16CTe8vpT22Vt)+*HNLo-0002ONklZP?00007x;8=X*cf4f19OuD@+?#smn;KqBycFc1qNF4!`07x9%r2J=_ZTt?o8CINb9`gp z?fT(G!E%m1rrjSA~<#aN4CGJ$?wlkama|Uh`6~9-; zSoVe0sBgwbZu_vCZTsw2&dcE1RQs{tCfY2-z3f|&m4$`HjXvpnleT`!InW0RB?eDd KKbLh*2~7Z44tP`m literal 0 HcmV?d00001 diff --git a/res/toolpal1.xpm b/res/toolpal1.xpm index f6f329f..c340812 100755 --- a/res/toolpal1.xpm +++ b/res/toolpal1.xpm @@ -1,53 +1,53 @@ /* XPM */ static const char * toolpal1_xpm[] = { -"96 48 2 1", +"120 48 2 1", " c #000000", ". c #FFFFFF", -" ", -" .................. .................. .................. .................. ", -" ", -" . .................. . . .................. . . .................. . . .................. . ", -" . .... ............. . . .................. . . ........ ........ . . .................. . ", -" . .... ............ . . .................. . . ........ ........ . . ...... .......... . ", -" . .... ........... . . .. ............... . . ....... ....... . . .... .. ........ . ", -" . .... .......... . . .. .............. . . ....... ....... . . ... ...... ....... . ", -" . .... ......... . . .. ............. . . ...... . . ...... . . ... ...... ....... . ", -" . .... ........ . . .. ............ . . ..... .. .. ..... . . .. ........ ...... . ", -" . .... ....... . . .. ... .. . . ... ... ... ... . . .. ........ ...... . ", -" . .... ...... . . .. .. . . . . . . . ... ...... ....... . ", -" . .... ..... . . .. . ... . . . . . . . ... ...... ....... . ", -" . .... ........ . . .. ... ... . . . ... ... ... ... . . .... .. ...... . ", -" . .... ........ . . .. ... . . . ..... .. .. ..... . . ...... .. ..... . ", -" . .... .. ....... . . .. .. .. .. . . ...... . . ...... . . ........... .... . ", -" . .... ... ....... . . ...... .. ...... . . ....... ....... . . ............ ... . ", -" . ......... ...... . . .......... ...... . . ....... ....... . . ............. .. . ", -" . ......... ...... . . .......... ...... . . ........ ........ . . .............. .. . ", -" . .......... ....... . . .................. . . ........ ........ . . .................. . ", -" . .................. . . .................. . . .................. . . .................. . ", -" ", -" .................. .................. .................. .................. ", -" ", -" ", -" .................. .................. .................. .................. ", -" ", -" . .................. . . .................. . . .................. . . .................. . ", -" . .................. . . .................. . . .................. . . .................. . ", -" . .................. . . ........ ........ . . .. .......... .. . . .. ........... .. . ", -" . .................. . . ....... ....... . . .. ........ .. . . ... . .. .. . ", -" . .................. . . ....... ....... . . ... ...... ... . . .... ... . ", -" . ....... ....... . . ...... .. ...... . . .... .... . . ..... ... .... . ", -" . ...... ...... . . ...... .. ...... . . ..... ..... . . ...... ... ..... . ", -" . ..... ..... . . ..... .... ..... . . ..... ..... . . ...... . ..... . ", -" . ..... .. ..... . . ..... .... ..... . . ..... ..... . . ...... ..... . ", -" . ..... .. ..... . . .... ...... .... . . ..... ..... . . ...... ..... . ", -" . ..... ..... . . .... ...... .... . . ..... ..... . . ...... ...... . ", -" . ...... ...... . . ... ........ ... . . ..... ..... . . ...... ... ..... . ", -" . ....... ....... . . ... ........ ... . . .... .... . . ..... .... .... . ", -" . .................. . . .. .......... .. . . ... ...... ... . . .... ..... ... . ", -" . .................. . . .. .. . . .. ........ .. . . ... . ...... .. . ", -" . .................. . . ... ... . . .. .......... .. . . .. ........... .. . ", -" . .................. . . .................. . . .................. . . .................. . ", -" . .................. . . .................. . . .................. . . .................. . ", -" ", -" .................. .................. .................. .................. ", -" "}; +" ", +" .................. .................. .................. .................. .................. ", +" ", +" . .................. . . .................. . . .................. . . .................. . . ....... ....... . ", +" . .... ............. . . .................. . . ........ ........ . . .................. . . ...... ...... . ", +" . .... ............ . . .................. . . ........ ........ . . ...... .......... . . .... . . .... . ", +" . .... ........... . . .. ............... . . ....... ....... . . .... .. ........ . . ... .. .... .. ... . ", +" . .... .......... . . .. .............. . . ....... ....... . . ... ...... ....... . . .. .. ...... .. .. . ", +" . .... ......... . . .. ............. . . ...... . . ...... . . ... ...... ....... . . .. ............ .. . ", +" . .... ........ . . .. ............ . . ..... .. .. ..... . . .. ........ ...... . . . ...... ...... . . ", +" . .... ....... . . .. ... .. . . ... ... ... ... . . .. ........ ...... . . . ...... ...... . . ", +" . .... ...... . . .. .. . . . . . . . ... ...... ....... . . . .... .... . . ", +" . .... ..... . . .. . ... . . . . . . . ... ...... ....... . . . .... .... . . ", +" . .... ........ . . .. ... ... . . . ... ... ... ... . . .... .. ...... . . . ...... ...... . . ", +" . .... ........ . . .. ... . . . ..... .. .. ..... . . ...... .. ..... . . . ...... ...... . . ", +" . .... .. ....... . . .. .. .. .. . . ...... . . ...... . . ........... .... . . .. ............ .. . ", +" . .... ... ....... . . ...... .. ...... . . ....... ....... . . ............ ... . . .. ............ .. . ", +" . ......... ...... . . .......... ...... . . ....... ....... . . ............. .. . . ... .......... ... . ", +" . ......... ...... . . .......... ...... . . ........ ........ . . .............. .. . . .... ...... .... . ", +" . .......... ....... . . .................. . . ........ ........ . . .................. . . ...... ...... . ", +" . .................. . . .................. . . .................. . . .................. . . .................. . ", +" ", +" .................. .................. .................. .................. .................. ", +" ", +" ", +" .................. .................. .................. .................. .................. ", +" ", +" . .................. . . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . ........ ........ . . .. .......... .. . . .. ........... .. . . .................. . ", +" . .................. . . ....... ....... . . .. ........ .. . . ... . .. .. . . .................. . ", +" . .................. . . ....... ....... . . ... ...... ... . . .... ... . . .................. . ", +" . ....... ....... . . ...... .. ...... . . .... .... . . ..... ... .... . . .................. . ", +" . ...... ...... . . ...... .. ...... . . ..... ..... . . ...... ... ..... . . .................. . ", +" . ..... ..... . . ..... .... ..... . . ..... ..... . . ...... . ..... . . .................. . ", +" . ..... .. ..... . . ..... .... ..... . . ..... ..... . . ...... ..... . . .................. . ", +" . ..... .. ..... . . .... ...... .... . . ..... ..... . . ...... ..... . . .................. . ", +" . ..... ..... . . .... ...... .... . . ..... ..... . . ...... ...... . . .................. . ", +" . ...... ...... . . ... ........ ... . . ..... ..... . . ...... ... ..... . . .................. . ", +" . ....... ....... . . ... ........ ... . . .... .... . . ..... .... .... . . .................. . ", +" . .................. . . .. .......... .. . . ... ...... ... . . .... ..... ... . . .................. . ", +" . .................. . . .. .. . . .. ........ .. . . ... . ...... .. . . .................. . ", +" . .................. . . ... ... . . .. .......... .. . . .. ........... .. . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . . .................. . ", +" . .................. . . .................. . . .................. . . .................. . . .................. . ", +" ", +" .................. .................. .................. .................. .................. ", +" "}; diff --git a/src/charwindow.cpp b/src/charwindow.cpp index cea3baa..0309b78 100755 --- a/src/charwindow.cpp +++ b/src/charwindow.cpp @@ -24,7 +24,8 @@ #include "charwindow.h" #include "debug.h" -CharWindow::CharWindow(QWidget * parent/*= NULL*/): QWidget(parent, Qt::Tool), path(NULL) +//CharWindow::CharWindow(QWidget * parent/*= NULL*/): QWidget(parent, Qt::Tool), path(NULL) +CharWindow::CharWindow(QWidget * parent/*= NULL*/): QWidget(parent, Qt::Window), path(NULL) { setWindowTitle("Character: Unknown"); } diff --git a/src/editwindow.cpp b/src/editwindow.cpp index f3cc70f..85a8ca8 100755 --- a/src/editwindow.cpp +++ b/src/editwindow.cpp @@ -34,17 +34,18 @@ #define DEBUGTP // Toolpalette debugging... #include "editwindow.h" -//#include -#include "graphicprimitives.h" -#include "debug.h" -#include "vector.h" #include "charwindow.h" +#include "debug.h" +#include "graphicprimitives.h" +#include "mainwindow.h" #include "ttedit.h" +#include "vector.h" + EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect), ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1), - polyFirstPoint(true) + polyFirstPoint(true), showRotationCenter(false), haveZeroPoint(false) { setBackgroundRole(QPalette::Base); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -55,22 +56,25 @@ EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent), setMouseTracking(true); } + QSize EditWindow::minimumSizeHint() const { return QSize(50, 50); } + QSize EditWindow::sizeHint() const { return QSize(400, 400); } + void EditWindow::CreateCursors(void) { - int hotx[8] = { 1, 1, 11, 15, 1, 1, 1, 1 }; - int hoty[8] = { 1, 1, 11, 13, 1, 1, 1, 1 }; + int hotx[9] = { 1, 1, 11, 15, 1, 1, 1, 1, 1 }; + int hoty[9] = { 1, 1, 11, 13, 1, 1, 1, 1, 1 }; - for(int i=0; i<8; i++) + for(int i=0; i<9; i++) { QString s; s.sprintf(":/res/cursor%u.png", i+1); @@ -79,6 +83,7 @@ void EditWindow::CreateCursors(void) } } + QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event) { QSize winSize = size(); @@ -88,6 +93,7 @@ QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event) return QPoint(offsetX + event->x(), offsetY + (winSize.height() - event->y())); } + QPoint EditWindow::GetAdjustedClientPosition(int x, int y) { QSize winSize = size(); @@ -96,6 +102,7 @@ QPoint EditWindow::GetAdjustedClientPosition(int x, int y) return QPoint(-offsetX + x, (winSize.height() - (-offsetY + y)) * +1.0); } + /* TODO: o Different colors for polys on selected points @@ -133,13 +140,22 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/) //// dc.DrawLine(0, 0, 10, 10); p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine)); - // Draw coordinate axes + // Draw coordinate axes // dc.CrossHair(0, 0); p.drawLine(0, -16384, 0, 16384); p.drawLine(-16384, 0, 16384, 0); - // Draw points + // Draw rotation center (if active) + + if (showRotationCenter) + { + p.setPen(QPen(Qt::red, 2.0, Qt::SolidLine)); + p.drawLine(rotationCenter.x() + 7, rotationCenter.y(), rotationCenter.x() - 7, rotationCenter.y()); + p.drawLine(rotationCenter.x(), rotationCenter.y() + 7, rotationCenter.x(), rotationCenter.y() - 7); + } + + // Draw points for(int i=0; i 2) + { + // Initial move... + // If it's not on curve, then move to it, otherwise move to last point... + + int x, y; + + if (rotated.GetOnCurve(poly, rotated.GetNumPoints(poly) - 1)) + x = (int)rotated.GetX(poly, rotated.GetNumPoints(poly) - 1), y = (int)rotated.GetY(poly, rotated.GetNumPoints(poly) - 1); + else + x = (int)rotated.GetX(poly, 0), y = (int)rotated.GetY(poly, 0); + + for(int i=0; i 2) + { + // Initial move... + // If it's not on curve, then move to it, otherwise move to last point... + + int x, y; + + if (glyph.GetOnCurve(poly, glyph.GetNumPoints(poly) - 1)) + x = (int)glyph.GetX(poly, glyph.GetNumPoints(poly) - 1), y = (int)glyph.GetY(poly, glyph.GetNumPoints(poly) - 1); + else + x = (int)glyph.GetX(poly, 0), y = (int)glyph.GetY(poly, 0); + + for(int i=0; ibutton() == Qt::RightButton) @@ -336,11 +459,24 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP update(); } } + else if (tool == TOOLRotate) + { + // I think what's needed here is to keep the initial mouse click, + // paint the rotation center, then use the 1st mouse move event to establish + // the rotation "zero line", which becomes the line of reference to all + // subsequent mouse moves. + rotationCenter = GetAdjustedMousePosition(event); + showRotationCenter = true; + haveZeroPoint = false; + rotationAngle = 0; + update(); + } } event->accept(); } + void EditWindow::mouseMoveEvent(QMouseEvent * event) { if (event->buttons() == Qt::RightButton) @@ -368,57 +504,58 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event) } else if (event->buttons() == Qt::LeftButton) { -#if 0 - if (tool == TOOLScroll) - { - // Extract current point from lParam/calc offset from previous point - - pt = e.GetPosition(); - ptOffset.x = pt.x - ptPrevious.x, - ptOffset.y = pt.y - ptPrevious.y; - - // NOTE: OffsetViewportOrg operates in DEVICE UNITS... - -//Seems there's no equivalent for this in wxWidgets...! -//!!! FIX !!! -// hdc = GetDC(hWnd); -// OffsetViewportOrgEx(hdc, ptOffset.x, ptOffset.y, NULL); -// ReleaseDC(hWnd, hdc); - -// this shows that it works, so the logic above must be faulty... -// And it is. It should convert the coords first, then do the subtraction to figure the offset... -// Above: DONE -// Then multiply it by the scaling factor. Whee! - // This looks wacky because we're using screen coords for the offset... - // Otherwise, we would subtract both offsets! - offsetX -= ptOffset.x, offsetY += ptOffset.y; - Refresh(); - } - else -#endif - if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect) + if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect) + { + if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. { - if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. - { //temporary, for testing. BTW, Select drag bug is here...! #if 1 - QPoint pt2 = GetAdjustedMousePosition(event); - pts.SetXY(ptHighlight, pt2.x(), pt2.y()); - update(); + QPoint pt2 = GetAdjustedMousePosition(event); + pts.SetXY(ptHighlight, pt2.x(), pt2.y()); + update(); #endif - } } - else if (tool == TOOLPolySelect) + } + else if (tool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) { - if (pts.GetNumPoints() > 0) - { - QPoint pt2 = GetAdjustedMousePosition(event); - // Should also set onCurve here as well, depending on keystate + QPoint pt2 = GetAdjustedMousePosition(event); + // Should also set onCurve here as well, depending on keystate //Or should we? - pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight)); - update(); + pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight)); + update(); + } + } + else if (tool == TOOLRotate) + { + if (pts.GetNumPoints() > 0) + { + if (!haveZeroPoint) + { + rotationZeroPoint = GetAdjustedMousePosition(event); + haveZeroPoint = true; + } + else + { + // Figure out the angle between the "zero" vector and the current one, + // then rotate all points relative to the "zero" vector (done by paint()) + QPoint currentPoint = GetAdjustedMousePosition(event); + Vector v1(rotationZeroPoint.x(), rotationZeroPoint.y(), 0, + rotationCenter.x(), rotationCenter.y(), 0); + Vector v2(currentPoint.x(), currentPoint.y(), 0, + rotationCenter.x(), rotationCenter.y(), 0); +// rotationAngle = v1.Angle(v2); + rotationAngle = v2.Angle(v1); + + QString s; + s.sprintf("%.3f degrees", rotationAngle * 180.0 / 3.14159265358979323); + ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage(s); } + + update(); } + } } else if (event->buttons() == Qt::NoButton) { @@ -463,20 +600,20 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event) int32 p1x = pts.GetX(i), p1y = pts.GetY(i), p2x = pts.GetX(pts.GetNext(i)), p2y = pts.GetY(pts.GetNext(i)); - vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0), + Vector ls(p2x, p2y, 0, p1x, p1y, 0), v1(pt2.x(), pt2.y(), 0, p1x, p1y, 0), v2(pt2.x(), pt2.y(), 0, p2x, p2y, 0); - double pp = ls.dot(v1) / ls.length(), dist; + double pp = ls.Dot(v1) / ls.Magnitude(), dist; // Geometric interpretation: // pp is the paremeterized point on the vector ls where the perpendicular intersects ls. // If pp < 0, then the perpendicular lies beyond the 1st endpoint. If pp > length of ls, // then the perpendicular lies beyond the 2nd endpoint. if (pp < 0.0) - dist = v1.length(); - else if (pp > ls.length()) - dist = v2.length(); + dist = v1.Magnitude(); + else if (pp > ls.Magnitude()) + dist = v2.Magnitude(); else // distance = ?Det?(ls, v1) / |ls| - dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length()); + dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.Magnitude()); //The answer to the above looks like it might be found here: // @@ -520,6 +657,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event) event->accept(); } + void EditWindow::mouseReleaseEvent(QMouseEvent * event) { if (event->button() == Qt::RightButton) @@ -550,11 +688,21 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event) } else if (event->button() == Qt::LeftButton) { + if (showRotationCenter) + { + showRotationCenter = false; + haveZeroPoint = false; + pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y())); + update(); + ((TTEdit *)qApp)->mainWindow->statusBar()->showMessage(""); + } + // if (tool == TOOLScroll || tool == TOOLZoom) // ReleaseMouse(); //this is prolly too much ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&pts); ((TTEdit *)qApp)->charWnd->update(); + } event->accept(); diff --git a/src/editwindow.h b/src/editwindow.h index 1b24dde..9ca997b 100755 --- a/src/editwindow.h +++ b/src/editwindow.h @@ -32,7 +32,9 @@ class EditWindow: public QWidget void CreateCursors(void); QPoint GetAdjustedMousePosition(QMouseEvent * event); QPoint GetAdjustedClientPosition(int x, int y); + void DrawGlyph(QPainter & p, GlyphPoints & glyph); + public: QImage image; QPoint pt, ptOffset, ptPrevious; double scale; // Window scaling factor @@ -41,9 +43,12 @@ class EditWindow: public QWidget GlyphPoints pts; // Glyph point structure int32 ptHighlight, oldPtHighlight, ptNextHighlight, oldPtNextHighlight; bool polyFirstPoint; + bool showRotationCenter, haveZeroPoint; + QPoint rotationCenter, rotationZeroPoint, rotationCurrentPoint; + double rotationAngle; ToolWindow * toolPalette; - QCursor cur[8]; + QCursor cur[9]; }; #endif // __EDITWINDOW_H__ diff --git a/src/glyphpoints.cpp b/src/glyphpoints.cpp index 0fc62f3..e6dc52c 100755 --- a/src/glyphpoints.cpp +++ b/src/glyphpoints.cpp @@ -22,6 +22,8 @@ #ifdef DEBUG #include "debug.h" #endif +#include + /*GlyphPoints::GlyphPoints(void) { @@ -46,6 +48,7 @@ WriteLogMsg("GlyphPoints: Default constructor. %u points, %u polys.\n", numPoint #endif } + GlyphPoints::GlyphPoints(int xx, int yy, bool oc) { //Hmm. What to do with this...? @@ -55,6 +58,7 @@ WriteLogMsg("GlyphPoints: Single point constructor. %u points, %u polys.\n", num #endif } + // Copy constructor (needed for deep copying) //GlyphPoints::GlyphPoints(GlyphPoints &c): x(NULL), y(NULL), onCurve(NULL), polyEnd(NULL) @@ -66,8 +70,11 @@ WriteLogMsg("GlyphPoints: Copy constructor. %u points, %u polys.\n", numPoints, #endif } + GlyphPoints::~GlyphPoints() { + FreeAllocatedMemory(); +#if 0 if (x) delete[] x; @@ -79,8 +86,10 @@ GlyphPoints::~GlyphPoints() if (polyEnd) delete[] polyEnd; +#endif } + void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool * oca, uint16 * pa) { numPoints = nPts, numPolys = nPlys; @@ -114,11 +123,29 @@ void GlyphPoints::AllocateAndCopy(int nPts, int nPlys, int * xa, int * ya, bool } } + +void GlyphPoints::FreeAllocatedMemory(void) +{ + if (x) + delete[] x; + + if (y) + delete[] y; + + if (onCurve) + delete[] onCurve; + + if (polyEnd) + delete[] polyEnd; +} + + GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c) { if (this == &c) return *this; // Take care of self-assignment +#if 0 if (x) delete[] x; @@ -130,12 +157,14 @@ GlyphPoints& GlyphPoints::operator=(const GlyphPoints &c) if (polyEnd) delete[] polyEnd; - +#endif + FreeAllocatedMemory(); AllocateAndCopy(c.numPoints, c.numPolys, c.x, c.y, c.onCurve, c.polyEnd); return *this; } + // Add another GlyphPoints' points to this one... GlyphPoints GlyphPoints::operator+(const GlyphPoints &c) @@ -177,6 +206,7 @@ GlyphPoints GlyphPoints::operator+(const GlyphPoints &c) return retVal; } + // Add a point to this GlyphPoints... GlyphPoints GlyphPoints::operator+(const IPoint &c) @@ -205,6 +235,7 @@ GlyphPoints GlyphPoints::operator+(const IPoint &c) return retVal; } + GlyphPoints& GlyphPoints::operator+=(const IPoint &p) { InsertPoint(numPoints, p.x, p.y, p.onCurve); @@ -212,6 +243,17 @@ GlyphPoints& GlyphPoints::operator+=(const IPoint &p) return *this; } + +void GlyphPoints::Clear(void) +{ + FreeAllocatedMemory(); + x = y = NULL; + onCurve = NULL; + polyEnd = NULL; + numPoints = numPolys = pointsAllocated = polysAllocated = 0; +} + + void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc) { if (pt > numPoints) // > because we can insert at end...! @@ -246,11 +288,13 @@ void GlyphPoints::InsertPoint(uint16 pt, int xx, int yy, bool oc) x = totX, y = totY, onCurve = totOnCurve; } + void GlyphPoints::InsertPoint(uint16 pt, const IPoint &p) { InsertPoint(pt, p.x, p.y, p.onCurve); } + // // Delete a point from the glyph // Note that we don't bother to reallocate anything here, just bump the @@ -283,11 +327,13 @@ void GlyphPoints::DeletePoint(uint16 pt) x[i] = x[i + 1], y[i] = y[i + 1], onCurve[i] = onCurve[i + 1]; } + uint16 GlyphPoints::GetNumPoints(void) { return numPoints; } + uint16 GlyphPoints::GetNumPoints(uint16 poly) { if (poly >= numPolys) @@ -303,11 +349,13 @@ WriteLogMsg("Exception: GetNumPoints(uint16). poly=%u, numPolys=%u\xD\xA", poly, return polyEnd[poly] - (poly == 0 ? -1 : polyEnd[poly - 1]); } + uint16 GlyphPoints::GetNumPolys(void) { return numPolys; } + int GlyphPoints::GetX(uint16 pt) { if (pt >= numPoints) @@ -323,6 +371,7 @@ WriteLogMsg("Exception: GetX(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints) return x[pt]; } + int GlyphPoints::GetY(uint16 pt) { if (pt >= numPoints) @@ -338,6 +387,7 @@ WriteLogMsg("Exception: GetY(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoints) return y[pt]; } + bool GlyphPoints::GetOnCurve(uint16 pt) { if (pt >= numPoints) @@ -353,6 +403,7 @@ WriteLogMsg("Exception: GetOnCurve(uint16). pt=%u, numPoints=%u\xD\xA", pt, numP return onCurve[pt]; } + int GlyphPoints::GetX(uint16 poly, uint16 pt) { if (pt >= GetNumPoints(poly)) @@ -368,11 +419,13 @@ WriteLogMsg("Exception: GetX(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\x return x[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)]; } + int GlyphPoints::GetNextX(uint16 poly, uint16 pt) { return GetX(poly, GetNext(poly, pt)); } + int GlyphPoints::GetY(uint16 poly, uint16 pt) { if (pt >= GetNumPoints(poly)) @@ -388,16 +441,19 @@ WriteLogMsg("Exception: GetY(uint16, uint16). poly= %u, pt=%u, numPoints=%u\xD\x return y[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)]; } + int GlyphPoints::GetNextY(uint16 poly, uint16 pt) { return GetY(poly, GetNext(poly, pt)); } + IPoint GlyphPoints::GetPoint(uint16 poly, uint16 pt) { return IPoint(GetX(poly, pt), GetY(poly, pt)); } + bool GlyphPoints::GetOnCurve(uint16 poly, uint16 pt) { if (pt >= GetNumPoints(poly)) @@ -413,16 +469,36 @@ WriteLogMsg("Exception: GetOnCurve(uint16, uint16). poly= %u, pt=%u, numPoints=% return onCurve[pt + (poly == 0 ? 0 : polyEnd[poly - 1] + 1)]; } + bool GlyphPoints::GetPrevOnCurve(uint16 poly, uint16 pt) { return GetOnCurve(poly, GetPrev(poly, pt)); } + bool GlyphPoints::GetNextOnCurve(uint16 poly, uint16 pt) { return GetOnCurve(poly, GetNext(poly, pt)); } + +uint16 GlyphPoints::GetPolyStart(uint16 poly) +{ + if (poly >= numPolys) +#ifdef DEBUG +{ +WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys); +#endif + throw GP_OUT_OF_RANGE; +#ifdef DEBUG +} +#endif + + // If it's poly 0, return 0. Otherwise, get the previous poly's end & add one to it + return (poly == 0 ? 0 : polyEnd[poly - 1] + 1); +} + + uint16 GlyphPoints::GetPolyEnd(uint16 poly) { if (poly >= numPolys) @@ -438,12 +514,14 @@ WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, n return polyEnd[poly]; } + void GlyphPoints::OffsetPoints(int xOff, int yOff) { for(int i=0; i= numPoints) @@ -487,6 +567,7 @@ WriteLogMsg("Exception: SetXY(uint16, int, int). pt=%u, numPoints=%u\xD\xA", pt, x[pt] = xx, y[pt] = yy; } + void GlyphPoints::SetOnCurve(uint16 pt, bool oc) { if (pt >= numPoints) @@ -502,6 +583,7 @@ WriteLogMsg("Exception: SetOnCurve(uint16, bool). pt=%u, numPoints=%u\xD\xA", pt onCurve[pt] = oc; } + uint16 GlyphPoints::GetPrev(uint16 pt) { // pt = 7, polyEnd = 4, 9, 15 @@ -527,6 +609,7 @@ uint16 GlyphPoints::GetPrev(uint16 pt) return retVal; } + uint16 GlyphPoints::GetNext(uint16 pt) { uint16 min = 0, max = numPoints - 1; @@ -551,6 +634,7 @@ uint16 GlyphPoints::GetNext(uint16 pt) return retVal; } + // // Get previous point for this polygon using wraparound. // Note that pt is a zero-based index! @@ -560,6 +644,7 @@ uint16 GlyphPoints::GetPrev(uint16 poly, uint16 pt) return (pt == 0 ? GetNumPoints(poly) - 1 : pt - 1); } + // // Get next point for this polygon using wraparound. // Note that pt is a zero-based index! @@ -569,6 +654,7 @@ uint16 GlyphPoints::GetNext(uint16 poly, uint16 pt) return (pt == GetNumPoints(poly) - 1 ? 0 : pt + 1); } + uint16 GlyphPoints::GetPoly(uint16 pt) { if (pt >= numPoints) @@ -588,6 +674,7 @@ WriteLogMsg("Exception: GetPoly(uint16). pt=%u, numPoints=%u\xD\xA", pt, numPoin return (uint16)-1; } + void GlyphPoints::AddNewPolyAtEnd(void) { if (numPoints == 0) // By default, we already *have* a poly @@ -604,6 +691,7 @@ void GlyphPoints::AddNewPolyAtEnd(void) polyEnd = newPolyEnd; } + IPoint GlyphPoints::GetMidpointToPrev(uint16 poly, uint16 pt) { uint16 prev = GetPrev(poly, pt); @@ -614,6 +702,7 @@ IPoint GlyphPoints::GetMidpointToPrev(uint16 poly, uint16 pt) return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f); } + IPoint GlyphPoints::GetMidpointToNext(uint16 poly, uint16 pt) { uint16 next = GetNext(poly, pt); @@ -624,6 +713,7 @@ IPoint GlyphPoints::GetMidpointToNext(uint16 poly, uint16 pt) return IPoint((x1 + x2) / 2.0f, (y1 + y2) / 2.0f); } + IPoint GlyphPoints::GetPrevPoint(uint16 poly, uint16 pt) { uint16 prevPt = GetPrev(poly, pt); @@ -631,9 +721,157 @@ IPoint GlyphPoints::GetPrevPoint(uint16 poly, uint16 pt) return IPoint(GetX(poly, prevPt), GetY(poly, prevPt)); } + IPoint GlyphPoints::GetNextPoint(uint16 poly, uint16 pt) { uint16 nextPt = GetNext(poly, pt); return IPoint(GetX(poly, nextPt), GetY(poly, nextPt)); } + + +// +// Rotate a point by "angle" around point "center" +// +IPoint GlyphPoints::RotatePoint(const double angle, const IPoint point, const IPoint center) +{ + // Translate the point to the origin + double xt = (double)(point.x - center.x); + double yt = (double)(point.y - center.y); + + // Rotate the point by angle + double xr = (xt * cos(angle)) - (yt * sin(angle)); + double yr = (xt * sin(angle)) + (yt * cos(angle)); + + // Translate it back... + IPoint rotated; + rotated.x = (int)(xr + 0.5) + center.x; + rotated.y = (int)(yr + 0.5) + center.y; + return rotated; +} + + +// +// Rotate all points in the glyph by "angle" around point "pt" +// +void GlyphPoints::RotatePoints(const double angle, const IPoint pt) +{ + for(int i=0; i= numPolys) + return IPoint(0, 0); + +// if (poly >= numPolys) +//#ifdef DEBUG +//{ +//WriteLogMsg("Exception: GetPolyEnd(uint16). poly=%u, numPolys=%u\xD\xA", poly, numPolys); +//#endif +// throw GP_OUT_OF_RANGE; +//#ifdef DEBUG +//} +//#endif + + IPoint centroid; // Initializes to (0, 0) + uint16 numPointsInPoly = GetNumPoints(poly); + + for(uint16 i=GetPolyStart(poly); i<=GetPolyEnd(poly); i++) + { + centroid.x += x[i]; + centroid.y += y[i]; + } + + centroid.x /= numPointsInPoly; + centroid.y /= numPointsInPoly; + + return centroid; +} + + +void GlyphPoints::RotatePolyAroundCentroid(const int16 poly, const double angle) +{ + if (poly >= numPolys) + return; + + IPoint centroid = GetPolyCentroid(poly); + + for(uint16 i=GetPolyStart(poly); i<=GetPolyEnd(poly); i++) + { + IPoint rotated = RotatePoint(angle, IPoint(x[i], y[i]), centroid); + x[i] = rotated.x; + y[i] = rotated.y; + } +} + + +// really need to do checking on the results from fscanf... +bool GlyphPoints::LoadGlyphFromFile(FILE * file) +{ + char line[512]; + float version; + + FreeAllocatedMemory(); + + fscanf(file, "%s V%f", line, &version); + fscanf(file, "%s %u", line, &numPoints); + x = new int[numPoints]; + y = new int[numPoints]; + onCurve = new bool[numPoints]; + + for(int i=0; ipts; + fprintf(file, "TTEGLYPH V1.0\n"); + fprintf(file, "POINTS %u\n", numPoints); + + for(int i=0; i +// "IPoint" is an Integer based Point struct IPoint { int32 x, y; @@ -46,11 +48,12 @@ class GlyphPoints GlyphPoints operator+(const GlyphPoints &); GlyphPoints operator+(const IPoint &); GlyphPoints& operator+=(const IPoint &); + void Clear(void); void InsertPoint(uint16, int, int, bool); void InsertPoint(uint16, const IPoint &); void DeletePoint(uint16); uint16 GetNumPoints(void); - uint16 GetNumPoints(uint16); + uint16 GetNumPoints(uint16 poly); uint16 GetNumPolys(void); int GetX(uint16); int GetY(uint16); @@ -63,6 +66,7 @@ class GlyphPoints bool GetOnCurve(uint16, uint16); bool GetPrevOnCurve(uint16, uint16); bool GetNextOnCurve(uint16, uint16); + uint16 GetPolyStart(uint16); uint16 GetPolyEnd(uint16); void OffsetPoints(int, int); void OffsetPoly(uint16, int32, int32); @@ -80,8 +84,17 @@ class GlyphPoints IPoint GetPrevPoint(uint16, uint16); IPoint GetNextPoint(uint16, uint16); + IPoint RotatePoint(const double angle, const IPoint point, const IPoint center); + void RotatePoints(const double angle, const IPoint point); + IPoint GetPolyCentroid(const int16 poly); + void RotatePolyAroundCentroid(const int16 poly, const double angle); + + bool LoadGlyphFromFile(FILE *); + bool SaveGlyphToFile(FILE *); + private: void AllocateAndCopy(int, int, int *, int *, bool *, uint16 *); + void FreeAllocatedMemory(void); private: int numPoints, numPolys; diff --git a/src/ttemainwindow.cpp b/src/mainwindow.cpp similarity index 76% rename from src/ttemainwindow.cpp rename to src/mainwindow.cpp index 2e155d3..8c7524f 100644 --- a/src/ttemainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,5 +1,5 @@ // -// TTEMAINWINDOW.CPP - The TrueType Editor +// MAINWINDOW.CPP - The TrueType Editor // by James L. Hammons // (C) 2004 Underground Software // @@ -34,13 +34,13 @@ #define DEBUGFOO // Various tool debugging... //#define DEBUGTP // Toolpalette debugging... -//#include -#include "ttemainwindow.h" -#include "editwindow.h" +#include "mainwindow.h" #include "charwindow.h" +#include "editwindow.h" #include "ttedit.h" -TTEMainWindow::TTEMainWindow() + +MainWindow::MainWindow() { ((TTEdit *)qApp)->charWnd = new CharWindow(this); editWnd = new EditWindow(this); @@ -94,6 +94,10 @@ TTEMainWindow::TTEMainWindow() editToolBar->addAction(cutAct); editToolBar->addAction(copyAct); editToolBar->addAction(pasteAct); +#else + CreateActions(); + CreateMenus(); + CreateToolbars(); #endif // Create status bar @@ -110,17 +114,122 @@ TTEMainWindow::TTEMainWindow() ((TTEdit *)qApp)->charWnd->show();//eh? } -void TTEMainWindow::closeEvent(QCloseEvent * event) + +// +// Consolidates action creation from a multi-step process to a single-step one. +// +QAction * MainWindow::CreateAction(QString name, QString tooltip, QString statustip, + QIcon icon, QKeySequence key, bool checkable/*= false*/) +{ + QAction * action = new QAction(icon, name, this); + action->setToolTip(tooltip); + action->setStatusTip(statustip); + action->setShortcut(key); + action->setCheckable(checkable); + + return action; +} + + +// +// This is essentially the same as the previous function, but this allows more +// than one key sequence to be added as key shortcuts. +// +QAction * MainWindow::CreateAction(QString name, QString tooltip, QString statustip, + QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable/*= false*/) +{ + QAction * action = new QAction(icon, name, this); + action->setToolTip(tooltip); + action->setStatusTip(statustip); + QList keyList; + keyList.append(key1); + keyList.append(key2); + action->setShortcuts(keyList); + action->setCheckable(checkable); + + return action; +} + + +void MainWindow::CreateActions(void) +{ + newGlyphAct = CreateAction("&New Glyph", "New Glyph", "Create a new glyph", QIcon(), QKeySequence()); + openFileAct = CreateAction("&Open File", "Open File", "Open a glyph file", QIcon(), QKeySequence()); + saveFileAct = CreateAction("&Save File", "Save File", "Save a glyph file", QIcon(), QKeySequence()); + + connect(newGlyphAct, SIGNAL(triggered()), this, SLOT(NewGlyph())); + connect(openFileAct, SIGNAL(triggered()), this, SLOT(OpenFile())); + connect(saveFileAct, SIGNAL(triggered()), this, SLOT(SaveFile())); +} + + +void MainWindow::CreateMenus(void) +{ + QMenu * menu = menuBar()->addMenu(tr("&File")); + menu->addAction(newGlyphAct); + menu->addAction(openFileAct); + menu->addAction(saveFileAct); +// menu->addAction(fileSaveAsAct); +// menu->addAction(fileCloseAct); +} + + +void MainWindow::CreateToolbars(void) +{ +} + + +void MainWindow::closeEvent(QCloseEvent * event) { WriteSettings(); event->accept(); // ignore() if can't close for some reason } -void TTEMainWindow::Open(void) + +void MainWindow::NewGlyph(void) { + editWnd->pts.Clear(); + ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&(editWnd->pts)); + ((TTEdit *)qApp)->charWnd->update(); + editWnd->update(); } -void TTEMainWindow::ReadSettings(void) + +void MainWindow::OpenFile(void) +{ + QString filename = QFileDialog::getOpenFileName(this, tr("Open Glyph File"), + "./", tr("Glyph files (*.glyph)")); + FILE * file = fopen(filename.toAscii().data(), "r"); + + //need to pop an error box here... + if (file == 0) + return; + + editWnd->pts.LoadGlyphFromFile(file); + fclose(file); + + ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&(editWnd->pts)); + ((TTEdit *)qApp)->charWnd->update(); + editWnd->update(); +} + + +void MainWindow::SaveFile(void) +{ + QString filename = QFileDialog::getSaveFileName(this, tr("Save Glyph File"), + "./", tr("Glyph files (*.glyph)")); + FILE * file = fopen(filename.toAscii().data(), "w"); + + //need to pop an error box here... + if (file == 0) + return; + + editWnd->pts.SaveGlyphToFile(file); + fclose(file); +} + + +void MainWindow::ReadSettings(void) { QSettings settings("Underground Software", "TTEdit"); QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); @@ -133,7 +242,8 @@ void TTEMainWindow::ReadSettings(void) ((TTEdit *)qApp)->charWnd->move(pos); } -void TTEMainWindow::WriteSettings(void) + +void MainWindow::WriteSettings(void) { QSettings settings("Underground Software", "TTEdit"); settings.setValue("pos", pos()); diff --git a/src/ttemainwindow.h b/src/mainwindow.h similarity index 54% rename from src/ttemainwindow.h rename to src/mainwindow.h index 8de8ec1..166a87e 100644 --- a/src/ttemainwindow.h +++ b/src/mainwindow.h @@ -1,67 +1,46 @@ // -// TTEMAINWINDOW.H: Header file +// MAINWINDOW.H: Header file // // by James L. Hammons // (C) 2009 Underground Software // -#ifndef __TTEMAINWINDOW_H__ -#define __TTEMAINWINDOW_H__ +#ifndef __MAINWINDOW_H__ +#define __MAINWINDOW_H__ -//Hrm. uh??? I thought this wasn't the way to do this stuff...??? #include -#if 0 -//#include // So that whoever uses this can without having - // to pull in a bunch of references manually -//#include "ttf.h" // Forward declarations -//class TTEditWin; -//class TTEditWindow; -//class CharWindow; -//class ToolWindow; - -// -// Class representing the entire Application -// -class TTEditApp: public QMainWindow -{ - public: - TTEditFrame * mainFrame; - CharWindow * charWin; - ToolWindow * toolPalette; - TTF font; - wxCursor * cur[8]; - - bool OnInit(); - int OnExit(); - void CreateResources(void); -}; - -DECLARE_APP(TTEditApp) -#endif -// Forward declarations - class EditWindow; //class CharWindow; -class TTEMainWindow: public QMainWindow + +class MainWindow: public QMainWindow { // All Qt apps require this macro Q_OBJECT public: - TTEMainWindow(); + MainWindow(); protected: void closeEvent(QCloseEvent * event); private slots: - void Open(); + void NewGlyph(void); + void OpenFile(void); + void SaveFile(void); private: + QAction * CreateAction(QString name, QString tooltip, QString statustip, + QIcon icon, QKeySequence key, bool checkable = false); + QAction * CreateAction(QString name, QString tooltip, QString statustip, + QIcon icon, QKeySequence key1, QKeySequence key2, bool checkable = false); + void CreateActions(void); + void CreateMenus(void); + void CreateToolbars(void); void ReadSettings(void); void WriteSettings(void); @@ -88,6 +67,9 @@ class TTEMainWindow: public QMainWindow DECLARE_EVENT_TABLE() #endif + QAction * newGlyphAct; + QAction * openFileAct; + QAction * saveFileAct; }; -#endif // __TTEMAINWINDOW_H__ +#endif // __MAINWINDOW_H__ diff --git a/src/toolwindow.cpp b/src/toolwindow.cpp index 75eaa0e..0bee1fa 100755 --- a/src/toolwindow.cpp +++ b/src/toolwindow.cpp @@ -34,7 +34,7 @@ ToolWindow::ToolWindow(void): QWidget(NULL, Qt::Window | Qt::FramelessWindowHint // Set up sizes sizeTPBM.rx() = img.width(), sizeTPBM.ry() = img.height(); - sizeStamp.rx() = sizeTPBM.x() / 4, sizeStamp.ry() = sizeTPBM.y() / 2; + sizeStamp.rx() = sizeTPBM.x() / 5, sizeStamp.ry() = sizeTPBM.y() / 2; setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setVisible(false); @@ -54,7 +54,8 @@ void ToolWindow::paintEvent(QPaintEvent * event) { //need ul corner of bitmap, ul corner of dest, width/height p.setCompositionMode(QPainter::RasterOp_NotSource); - QPoint pt(sizeStamp.x() * (prevTool & 0x03), sizeStamp.y() * (prevTool >> 2)); +// QPoint pt(sizeStamp.x() * (prevTool & 0x03), sizeStamp.y() * (prevTool >> 2)); + QPoint pt(sizeStamp.x() * (prevTool % 5), sizeStamp.y() * (prevTool / 5)); p.drawImage(pt.x(), pt.y(), img, pt.x(), pt.y(), sizeStamp.x(), sizeStamp.y()); } } @@ -76,8 +77,12 @@ ToolType ToolWindow::FindSelectedTool(void) ToolType newTool = TOOLNone; // NOTE: This works because x and y are UNSIGNED - if (x < 4 && y < 2) - newTool = (ToolType)((y * 4) + x); + if (x < 5 && y < 2) + newTool = (ToolType)((y * 5) + x); + + // We don't have 10 yet, so fix this if the user selected the blank space + if (newTool == 9) + newTool = TOOLNone; return newTool; } diff --git a/src/toolwindow.h b/src/toolwindow.h index 1623eb4..27a0cb3 100755 --- a/src/toolwindow.h +++ b/src/toolwindow.h @@ -18,6 +18,7 @@ enum ToolType { TOOLPolySelect, // Polygon selection tool TOOLScroll, // Scroll window tool TOOLZoom, // Zoom window tool + TOOLRotate, // Rotate tool TOOLAddPt, // Add point tool TOOLAddPoly, // Polygon creation tool TOOLDelPt, // Delete point tool diff --git a/src/ttedit.cpp b/src/ttedit.cpp index 62417b5..9f34039 100755 --- a/src/ttedit.cpp +++ b/src/ttedit.cpp @@ -18,13 +18,13 @@ #include "ttedit.h" #include -#include "ttemainwindow.h" +#include "mainwindow.h" // Main app constructor--we stick globally accessible stuff here... TTEdit::TTEdit(int & argc, char * argv[]): QApplication(argc, argv), charWnd(NULL) { - mainWindow = new TTEMainWindow; + mainWindow = new MainWindow; //printf("mainWindow.show();\n"); mainWindow->show(); } diff --git a/src/ttedit.h b/src/ttedit.h index 9bc6b59..3c63025 100755 --- a/src/ttedit.h +++ b/src/ttedit.h @@ -8,12 +8,11 @@ #ifndef __TTEDIT_H__ #define __TTEDIT_H__ -//Hrm. uh??? I thought this wasn't the way to do this stuff...??? #include // Forward declarations class CharWindow; -class TTEMainWindow; +class MainWindow; class TTEdit: public QApplication { @@ -22,7 +21,7 @@ class TTEdit: public QApplication public: CharWindow * charWnd; - TTEMainWindow * mainWindow; + MainWindow * mainWindow; }; #endif // __TTEDIT_H__ diff --git a/src/vector.cpp b/src/vector.cpp index 32fe4e1..1f4c29c 100755 --- a/src/vector.cpp +++ b/src/vector.cpp @@ -1,3 +1,5 @@ +#if 0 + // // VECTOR.H - vector class definition // @@ -14,8 +16,8 @@ // JLH 05/15/2004 Added operator+ function // -#include #include "vector.h" +#include vector::vector(double a1/*= 0.0*/, double b1/*= 0.0*/, double c1/*= 0.0*/, double a2/*= 0.0*/, double b2/*= 0.0*/, double c2/*= 0.0*/): @@ -139,3 +141,258 @@ void vector::zero(const double epsilon/*= 1.0e-6*/) if (fabs(z) < epsilon) z = 0.0; } + +#else + +// +// vector.cpp: Various structures used for 3 dimensional imaging +// +// by James Hammons +// (C) 2006 Underground Software +// +// JLH = James L. Hammons +// +// WHO WHEN WHAT +// --- ---------- ------------------------------------------------------------ +// JLH 09/19/2006 Created this file +// JLH 03/22/2011 Moved implementation of constructor from header to here +// JLH 04/02/2011 Fixed divide-by-zero bug in Unit(), added Angle() function +// + +#include "vector.h" + +#include // For sqrt() +//#include "mathconstants.h" + +#define PI 3.14159265358979323846264338327 +#define RADIANS_TO_DEGREES (180.0 / PI) +#define DEGREES_TO_RADIANS (PI / 180.0) + + +// Vector implementation + +Vector::Vector(double x1/*= 0*/, double y1/*= 0*/, double z1/*= 0*/, + double x2/*= 0*/, double y2/*= 0*/, double z2/*= 0*/): + x(x1 - x2), y(y1 - y2), z(z1 - z2) +{ +} + + +Vector::Vector(Vector head, Vector tail): x(head.x - tail.x), y(head.y - tail.y), z(head.z - tail.z) +{ +} + + +Vector Vector::operator=(Vector const v) +{ + x = v.x, y = v.y, z = v.z; + + return *this; +} + + +Vector Vector::operator+(Vector const v) +{ + return Vector(x + v.x, y + v.y, z + v.z); +} + + +Vector Vector::operator-(Vector const v) +{ + return Vector(x - v.x, y - v.y, z - v.z); +} + + +// Unary negation + +Vector Vector::operator-(void) +{ + return Vector(-x, -y, -z); +} + + +// Vector x constant + +Vector Vector::operator*(double const v) +{ + return Vector(x * v, y * v, z * v); +} + + +// Vector x constant + +Vector Vector::operator*(float const v) +{ + return Vector(x * v, y * v, z * v); +} + + +// Vector / constant + +Vector Vector::operator/(double const v) +{ + return Vector(x / v, y / v, z / v); +} + + +// Vector / constant + +Vector Vector::operator/(float const v) +{ + return Vector(x / v, y / v, z / v); +} + + +// Vector (cross) product + +Vector Vector::operator*(Vector const v) +{ + // a x b = [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] + return Vector((y * v.z) - (z * v.y), (z * v.x) - (x * v.z), (x * v.y) - (y * v.x)); +} + + +// Dot product + +double Vector::Dot(Vector const v) +{ + return (x * v.x) + (y * v.y) + (z * v.z); +} + + +// Vector x constant, self assigned + +Vector& Vector::operator*=(double const v) +{ + x *= v, y *= v, z *= v; + + return *this; +} + + +// Vector / constant, self assigned + +Vector& Vector::operator/=(double const v) +{ + x /= v, y /= v, z /= v; + + return *this; +} + + +// Vector + vector, self assigned + +Vector& Vector::operator+=(Vector const v) +{ + x += v.x, y += v.y, z += v.z; + + return *this; +} + + +// Vector + constant, self assigned + +Vector& Vector::operator+=(double const v) +{ + x += v, y += v, z += v; + + return *this; +} + + +// Vector - vector, self assigned + +Vector& Vector::operator-=(Vector const v) +{ + x -= v.x, y -= v.y, z -= v.z; + + return *this; +} + + +// Vector - constant, self assigned + +Vector& Vector::operator-=(double const v) +{ + x -= v, y -= v, z -= v; + + return *this; +} + + +// Check for equality +bool Vector::operator==(Vector const v) +{ + return (x == v.x && y == v.y && z == v.z ? true : false); +} + + +// Check for inequality +bool Vector::operator!=(Vector const v) +{ + return (x != v.x || y != v.y || z != v.z ? true : false); +} + + +Vector Vector::Unit(void) +{ + double mag = Magnitude(); + + // If the magnitude of the vector is zero, then the Unit vector is undefined... + if (mag == 0) + return Vector(0, 0, 0); + + return Vector(x / mag, y / mag, z / mag); +} + + +double Vector::Magnitude(void) +{ + return sqrt(x * x + y * y + z * z); +} + + +double Vector::Angle(void) +{ + // acos returns a value between zero and PI, which means we don't know which + // quadrant the angle is in... Though, if the y-coordinate of the vector is + // negative, that means that the angle is in quadrants III - IV. + double rawAngle = acos(Unit().x); + double correctedAngle = (y < 0 ? (2.0 * PI) - rawAngle : rawAngle); + + return correctedAngle; +} + + +// +// Angle between these two vectors +// +double Vector::Angle(Vector v) +{ + return Angle() - v.Angle(); +} + + +bool Vector::isZero(double epsilon/*= 1e-6*/) +{ + return (fabs(x) < epsilon && fabs(y) < epsilon && fabs(z) < epsilon ? true : false); +} + + +// Class methods + +double Vector::Dot(Vector v1, Vector v2) +{ + return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z); +} + + +double Vector::Magnitude(Vector v1, Vector v2) +{ + double xx = v1.x - v2.x; + double yy = v1.y - v2.y; + double zz = v1.z - v2.z; + return sqrt(xx * xx + yy * yy + zz * zz); +} + +#endif diff --git a/src/vector.h b/src/vector.h index 36025b9..6c46dff 100755 --- a/src/vector.h +++ b/src/vector.h @@ -1,3 +1,5 @@ +#if 0 + // // VECTOR.H - vector class definition // @@ -33,3 +35,67 @@ struct vector }; #endif // __VECTOR_H__ + +#else + +// +// vector.h (Last modified: 6/28/2001) +// +// Various structures used for 3 dimensional imaging +// +// by James L. Hammons +// (C) 2001 Underground Software +// + +#ifndef __VECTOR_H__ +#define __VECTOR_H__ + +// What we'll do here is create the vector type and use typedef to alias Point to it. Yeah, that's it. + +class Vector +{ + public: +// Vector(double xx = 0, double yy = 0, double zz = 0); + Vector(double x1 = 0, double y1 = 0, double z1 = 0, double x2 = 0, double y2 = 0, double z2 = 0); + Vector(Vector head, Vector tail); // Create vector from two points + Vector operator=(Vector const v); + Vector operator+(Vector const v); + Vector operator-(Vector const v); + Vector operator-(void); // Unary negation + Vector operator*(double const v); // Vector times constant (double) + Vector operator*(float const v); // Vector times constant (float) + Vector operator/(double const v); // Vector divided by constant (double) + Vector operator/(float const v); // Vector divided by constant (float) + Vector operator*(Vector const v); // Vector product + double Dot(Vector const v); // Dot product + + Vector& operator*=(double const v); // Vector times constant self-assignment + Vector& operator/=(double const v); // Vector divided by constant self-assignment + Vector& operator+=(Vector const v); // Vector plus Vector self-assignment + Vector& operator+=(double const v); // Vector plus constant self-assignment + Vector& operator-=(Vector const v); // Vector minus Vector self-assignment + Vector& operator-=(double const v); // Vector minus constant self-assignment + + bool operator==(Vector const v); // Check for equality + bool operator!=(Vector const v); // Check for inequality + + Vector Unit(void); + double Magnitude(void); + double Angle(void); // Angle of this vector WRT positive X-axis + double Angle(Vector v); // Angle between these two vectors + bool isZero(double epsilon = 1e-6); + + // Class methods + + static double Dot(Vector v1, Vector v2); + static double Magnitude(Vector v1, Vector v2); + + public: + double x, y, z; +}; + +typedef Vector Point; + +#endif // __VECTOR_H__ + +#endif \ No newline at end of file diff --git a/ttedit.pro b/ttedit.pro index dd20f26..78798a3 100644 --- a/ttedit.pro +++ b/ttedit.pro @@ -5,7 +5,7 @@ CONFIG += qt #CONFIG += qt debug HEADERS += src/ttedit.h -HEADERS += src/ttemainwindow.h +HEADERS += src/mainwindow.h HEADERS += src/editwindow.h HEADERS += src/glyphpoints.h HEADERS += src/types.h @@ -17,7 +17,7 @@ HEADERS += src/graphicprimitives.h HEADERS += src/list.h SOURCES += src/ttedit.cpp -SOURCES += src/ttemainwindow.cpp +SOURCES += src/mainwindow.cpp SOURCES += src/editwindow.cpp SOURCES += src/glyphpoints.cpp SOURCES += src/debug.cpp diff --git a/ttedit.qrc b/ttedit.qrc index ca2b69b..27c4f83 100644 --- a/ttedit.qrc +++ b/ttedit.qrc @@ -8,6 +8,7 @@ res/cursor6.png res/cursor7.png res/cursor8.png + res/cursor9.png res/act-back.png res/act-forward.png res/act-charwin.png -- 2.37.2