]> Shamusworld >> Repos - ttedit/commitdiff
Added rectangle point selection, canvas zooming.
authorShamus Hammons <jlhamm@acm.org>
Fri, 4 Mar 2016 19:57:48 +0000 (13:57 -0600)
committerShamus Hammons <jlhamm@acm.org>
Fri, 4 Mar 2016 19:57:48 +0000 (13:57 -0600)
Note that the scrolling & single point selection are still a bit wonky.

26 files changed:
res/cursor-select-multi.png [new file with mode: 0644]
res/toolpal1.png
src/charnames.cpp
src/charwindow.cpp
src/debug.cpp
src/editwindow.cpp
src/editwindow.h
src/global.cpp [new file with mode: 0644]
src/global.h [new file with mode: 0644]
src/glyphpoints.cpp
src/glyphpoints.h
src/graphicprimitives.cpp [deleted file]
src/graphicprimitives.h [deleted file]
src/list.h
src/mainwindow.cpp
src/mainwindow.h
src/mathconstants.h [new file with mode: 0644]
src/painter.cpp [new file with mode: 0644]
src/painter.h [new file with mode: 0644]
src/toolwindow.cpp
src/toolwindow.h
src/ttedit.cpp
src/ttf.cpp
src/vector.cpp
ttedit.pro
ttedit.qrc

diff --git a/res/cursor-select-multi.png b/res/cursor-select-multi.png
new file mode 100644 (file)
index 0000000..521627c
Binary files /dev/null and b/res/cursor-select-multi.png differ
index 54ca026c5d06a84e4e830609af43cd8c3a894778..2d29d452c26950a1634481a7f0ea86e3140d97c1 100644 (file)
Binary files a/res/toolpal1.png and b/res/toolpal1.png differ
index 56047bd8c811d151e75aa1883f8ab0f4b0c60ee4..d50cfa3f889f1485b2286965894eef21335d0347 100755 (executable)
@@ -2,13 +2,13 @@
 // CHARNAMES.CPP
 //
 // A header file that links Unicode character names to character numbers.
-// by James L. Hammons
+// by James Hammons
 // (C) 2004 Underground Software
 //
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  ??/??/200?  Created this file
 //
 
index 0309b78e82630cbbb00e31540b192c791257fae6..76112e4f8e92c96d59fc15ba45fd0bc84b9fd9b3 100755 (executable)
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  08/28/2008  Created this file
 // JLH  03/19/2009  Converted from wxWidgets to Qt
 // JLH  03/21/2009  Fixed main screen points rendering
index fb77b4277a07ddec150f50f2cd050a7e951c948d..bfe1b0b38bb85dc87ec694ef622f04dff9110b25 100755 (executable)
@@ -6,7 +6,7 @@
 //   JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  ------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  07/31/2002  Created this file
 // JLH  07/31/2002  Added debug log functions & system error logging functions
 // JLH  08/16/2002  Added debug log function for SQL error reporting, made
index 9d0f5d8d803b725ca27ab5a2f051e3f39bf3ea4a..85b4d9c716360349edefda5b7128dcfe14d06fbe 100755 (executable)
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  08/28/2008  Created this file
 // JLH  09/02/2008  Separated scrolling from dedicated tool to MMB drag
 // JLH  03/13/2009  Converted from wxWidgets to Qt
@@ -36,7 +36,7 @@
 #include "editwindow.h"
 #include "charwindow.h"
 #include "debug.h"
-#include "graphicprimitives.h"
+#include "global.h"
 #include "mainwindow.h"
 #include "ttedit.h"
 #include "vector.h"
@@ -45,7 +45,8 @@
 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), showRotationCenter(false), haveZeroPoint(false)
+       polyFirstPoint(true), showRotationCenter(false), haveZeroPoint(false),
+       selectionInProgress(false)
 {
        setBackgroundRole(QPalette::Base);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -54,6 +55,7 @@ EditWindow::EditWindow(QWidget * parent/*= NULL*/): QWidget(parent),
        CreateCursors();
        setCursor(cur[TOOLSelect]);
        setMouseTracking(true);
+       ClearSelection();
 }
 
 
@@ -71,12 +73,13 @@ QSize EditWindow::sizeHint() const
 
 void EditWindow::CreateCursors(void)
 {
-       int hotx[11] = {  1,  1, 11, 15,  1,  1,  1,  1,  1,  1,  1 };
-       int hoty[11] = {  1,  1, 11, 13,  1,  1,  1,  1,  1,  1,  1 };
-       char cursorName[11][48] = { "select", "select-poly", "scroll", "zoom", "add-point",
-               "add-poly", "del-point", "del-poly", "rotate", "rotate", "select" };
+       int hotx[12] = {  1,  1, 1, 15,  1,  1,  1,  1,  1,  1,  1, 11 };
+       int hoty[12] = {  1,  1, 1, 13,  1,  1,  1,  1,  1,  1,  1, 11 };
+       char cursorName[12][48] = { "select", "select-poly", "select-multi", "zoom",
+               "add-point", "add-poly", "del-point", "del-poly", "rotate", "rotate",
+               "select", "scroll" };
 
-       for(int i=0; i<11; i++)
+       for(int i=0; i<12; i++)
        {
                QString s;
                s.sprintf(":/res/cursor-%s.png", cursorName[i]);
@@ -88,20 +91,17 @@ void EditWindow::CreateCursors(void)
 
 QPoint EditWindow::GetAdjustedMousePosition(QMouseEvent * event)
 {
-       QSize winSize = size();
-       // This is undoing the transform, e.g. going from client coords to local coords.
-       // In essence, the height - y is height + (y * -1), the (y * -1) term doing the
-       // conversion of the y-axis from increasing bottom to top.
-       return QPoint(offsetX + event->x(), offsetY + (winSize.height() - event->y()));
+       // This is undoing the transform, e.g. going from client coords to local
+       // coords. In essence, the height - y is height + (y * -1), the (y * -1)
+       // term doing the conversion of the y-axis from increasing bottom to top.
+       return QPoint(offsetX + event->x(), offsetY + (size().height() - event->y()));
 }
 
 
 QPoint EditWindow::GetAdjustedClientPosition(int x, int y)
 {
-       QSize winSize = size();
-
        // VOODOO ALERT (ON Y COMPONENT!!!!)
-       return QPoint(-offsetX + x, (winSize.height() - (-offsetY + y)) * +1.0);
+       return QPoint(-offsetX + x, (size().height() - (-offsetY + y)) * +1.0);
 }
 
 
@@ -114,14 +114,21 @@ TODO:
 */
 void EditWindow::paintEvent(QPaintEvent * /*event*/)
 {
-       QPainter p(this);
+       QPainter qtp(this);
+       Painter painter(&qtp);
 //hm, causes lockup (or does it???)
-       p.setRenderHint(QPainter::Antialiasing);
-
-       QSize winSize = size();
-
-       p.translate(QPoint(-offsetX, winSize.height() - (-offsetY)));
-       p.scale(1.0, -1.0);
+//& it doesn't help with our Bezier rendering code :-P
+       painter.SetRenderHint(QPainter::Antialiasing);
+
+       Global::zoom = scale;
+       Global::origin = Vector(offsetX, offsetY);
+       Global::viewportHeight = size().height();
+       Global::screenSize = Vector(size().width(), size().height());
+//     p.translate(QPoint(-offsetX, size().height() - (-offsetY)));
+//     p.scale(1.0, -1.0);
+//Nope, a big load of shit. So we'll have to bite the bullet and do it the
+//hard way™.
+//     p.scale(scale, -scale);
 
 // Scrolling can be done by using OffsetViewportOrgEx
 // Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform)
@@ -130,78 +137,95 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
 // Instead, we have to scale EVERYTHING by hand. Crap!
 // It's not *that* bad, but not as convenient either...
 
-       p.setPen(QPen(Qt::blue, 1.0, Qt::DotLine));
+       painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
 
        // Draw coordinate axes
 
-       p.drawLine(0, -16384, 0, 16384);
-       p.drawLine(-16384, 0, 16384, 0);
+       painter.DrawLine(0, -16384, 0, 16384);
+       painter.DrawLine(-16384, 0, 16384, 0);
 
        // 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);
+               painter.SetPen(QPen(Qt::red, 2.0, Qt::SolidLine));
+               painter.DrawLine(rotationCenter.x + 7, rotationCenter.y, rotationCenter.x - 7, rotationCenter.y);
+               painter.DrawLine(rotationCenter.x, rotationCenter.y + 7, rotationCenter.x, rotationCenter.y - 7);
        }
 
        // Draw points
 
        for(int i=0; i<pts.GetNumPoints(); i++)
        {
-               if (i == ptHighlight)
+               /*if (tool == TOOLMultiSelect)
                {
-                       p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       if (selectedPoints[i])
+                       {
+                               qtp.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       }
+                       else
+                       {
+                               qtp.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+                       }
+               }
+               else*/
+               if (((i == ptHighlight) && (tool != TOOLMultiSelect)) || ((tool == TOOLMultiSelect) && selectedPoints[i]))
+               {
+                       painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
                        {
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawSquareDotN(pts.GetXY(i), 7);
+                               painter.DrawSquareDotN(pts.GetXY(i), 9);
                        }
                        else
                        {
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawRoundDotN(pts.GetXY(i), 7);
+                               painter.DrawRoundDotN(pts.GetXY(i), 9);
                        }
                }
                else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt)
                {
-                       p.setPen(QPen(Qt::green, 1.0, Qt::SolidLine));
+                       painter.SetPen(QPen(Qt::green, 1.0, Qt::SolidLine));
 
                        if (pts.GetOnCurve(i))
                        {
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawSquareDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawSquareDotN(pts.GetXY(i), 7);
+                               painter.DrawSquareDotN(pts.GetXY(i), 9);
                        }
                        else
                        {
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 7);
-                               DrawRoundDotN(p, pts.GetX(i), pts.GetY(i), 9);
+                               painter.DrawRoundDotN(pts.GetXY(i), 7);
+                               painter.DrawRoundDotN(pts.GetXY(i), 9);
                        }
                }
                else
                {
-                       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+                       painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
 
+#if 1
                        if (pts.GetOnCurve(i))
-                               DrawSquareDot(p, pts.GetX(i), pts.GetY(i));
+                               painter.DrawSquareDot(pts.GetXY(i));
                        else
-                               DrawRoundDot(p, pts.GetX(i), pts.GetY(i));
+                               painter.DrawRoundDot(pts.GetXY(i));
+#else
+                       (pts.GetOnCurve(i) ? DrawSquareDot(p, pts.GetX(i), pts.GetY(i))
+                               : DrawRoundDot(p, pts.GetX(i), pts.GetY(i)));
+#endif
                }
 
                if (tool == TOOLDelPt && i == ptHighlight)
                {
-                       p.setPen(QPen(Qt::red, 1.0, Qt::SolidLine));
-                       p.drawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
-                       p.drawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
+                       painter.SetPen(QPen(Qt::red, 1.0, Qt::SolidLine));
+                       painter.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5);
+                       painter.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5);
                }
        }
 
        // Draw curve formed by points
 
-       p.setPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-       DrawGlyph(p, pts);
+       painter.SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
+       DrawGlyph(painter, pts);
 
        if (haveZeroPoint)
        {
@@ -209,20 +233,27 @@ void EditWindow::paintEvent(QPaintEvent * /*event*/)
                GlyphPoints rotated = pts;
 
                if (tool == TOOLRotate)
-                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                       rotated.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
                else if (tool == TOOLRotatePoly)
                {
                        uint16_t poly = rotated.GetPolyForPointNumber(ptHighlight);
                        rotated.RotatePolyAroundCentroid(poly, rotationAngle);
                }
 
-               p.setPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
-               DrawGlyph(p, rotated);
+               painter.SetPen(QPen(QColor(255, 0, 255), 1.0, Qt::SolidLine));
+               DrawGlyph(painter, rotated);
+       }
+
+       if (selectionInProgress)
+       {
+               painter.SetPen(QPen(QColor(255, 127, 0, 255)));
+               painter.SetBrush(QBrush(QColor(255, 127, 0, 100)));
+               painter.DrawRect(selection);
        }
 }
 
 
-void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
+void EditWindow::DrawGlyph(Painter & p, GlyphPoints & glyph)
 {
        for(int poly=0; poly<glyph.GetNumPolys(); poly++)
        {
@@ -274,7 +305,7 @@ void EditWindow::DrawGlyph(QPainter & p, GlyphPoints & glyph)
 }
 
 
-void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16_t poly)
+void EditWindow::DrawGlyphPoly(Painter & p, GlyphPoints & glyph, uint16_t poly)
 {
        // Sanity check
        if (glyph.GetNumPoints(poly) < 3)
@@ -294,7 +325,7 @@ void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16_t poly)
                if (glyph.GetOnCurve(poly, i) && glyph.GetNextOnCurve(poly, i))
                {
                        IPoint pt2 = glyph.GetNextPoint(poly, i);
-                       p.drawLine(pt.x, pt.y, pt2.x, pt2.y);
+                       p.DrawLine(pt.x, pt.y, pt2.x, pt2.y);
                        pt = pt2;
                }
                else
@@ -304,20 +335,27 @@ void EditWindow::DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16_t poly)
                        if (glyph.GetOnCurve(poly, i))
                                continue;
 
-                       // We are now guaranteed that we are sitting on a curve control point
-                       // (off curve). Figure the extent of the curve: If the following is a
-                       // curve control point, then use the midpoint to it otherwise go to
-                       // the next point since it's on curve.
+                       // We are now guaranteed that we are sitting on a curve control
+                       // point (off curve). Figure the extent of the curve: If the
+                       // following is a curve control point, then use the midpoint to it
+                       // otherwise go to the next point since it's on curve.
                        IPoint pt2 = (glyph.GetNextOnCurve(poly, i)
                                ? glyph.GetNextPoint(poly, i) : glyph.GetMidpointToNext(poly, i));
 
-                       Bezier(p, pt, glyph.GetPoint(poly, i), pt2);
+                       p.DrawBezier(pt, glyph.GetPoint(poly, i), pt2);
                        pt = pt2;
                }
        }
 }
 
 
+void EditWindow::ClearSelection(void)
+{
+       for(int i=0; i<65536; i++)
+               selectedPoints[i] = false;
+}
+
+
 void EditWindow::mousePressEvent(QMouseEvent * event)
 {
        if (event->button() == Qt::RightButton)
@@ -329,16 +367,28 @@ void EditWindow::mousePressEvent(QMouseEvent * event)
        }
        else if (event->button() == Qt::MidButton)
        {
-               setCursor(cur[2]);                                                      // Scrolling cursor
+               // Scrolling cursor
+               setCursor(cur[11]);
+               ptPrevious = Vector(event->x(), event->y());
+               ptPrevious /= Global::zoom;
        }
        else if (event->button() == Qt::LeftButton)
        {
                if (tool == TOOLScroll || tool == TOOLZoom)
 ;//meh                 CaptureMouse();                                         // Make sure we capture the mouse when in scroll/zoom mode
+               else if (tool == TOOLMultiSelect)
+               {
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       selectionInProgress = true;
+                       selection.setTopLeft(QPoint(pt.x, pt.y));
+                       selection.setBottomRight(QPoint(pt.x, pt.y));
+               }
                else if (tool == TOOLAddPt)             // "Add Point" tool
                {
-                       QPoint pt = GetAdjustedMousePosition(event);
-                       IPoint pointToAdd(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       IPoint pointToAdd(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
 
                        if (pts.GetNumPoints() < 2)
                        {
@@ -368,10 +418,11 @@ WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.
                                pts.AddNewPolyAtEnd();
                        }
 
-                       QPoint pt = GetAdjustedMousePosition(event);
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
 //printf("GetAdjustedMousePosition = %i, %i\n", pt.x(), pt.y());
                        // Append a point to the end of the structure
-                       pts += IPoint(pt.x(), pt.y(), ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
+                       pts += IPoint(pt.x, pt.y, ((event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier) ? false : true));
                        ptHighlight = pts.GetNumPoints() - 1;
                        update();
 #ifdef DEBUGFOO
@@ -382,10 +433,12 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                {
                        if (pts.GetNumPoints() > 0)
                        {
-                               pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+//                             pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                               Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
 //printf("GetAdjustedClientPosition = %i, %i\n", pt.x(), pt.y());
 //                             WarpPointer(pt.x, pt.y);
-                               QCursor::setPos(mapToGlobal(pt));
+                               QPoint warp(pt.x, pt.y);
+                               QCursor::setPos(mapToGlobal(warp));
 
                                if (event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::ControlModifier)
                                {
@@ -412,7 +465,8 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                        // 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);
+//                     rotationCenter = GetAdjustedMousePosition(event);
+                       rotationCenter = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                        showRotationCenter = true;
                        haveZeroPoint = false;
                        rotationAngle = 0;
@@ -421,11 +475,12 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                else if (tool == TOOLRotatePoly)
                {
                        IPoint centroid = pts.GetPolyCentroid(pts.GetPolyForPointNumber(ptHighlight));
-                       rotationCenter = QPoint(centroid.x, centroid.y);
+                       rotationCenter = Vector(centroid.x, centroid.y);
                        showRotationCenter = true;
-                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
-                       QCursor::setPos(mapToGlobal(pt));
-                       rotationZeroPoint = QPoint(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+//                     pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       Vector pt = Painter::QtToCartesianCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
+                       QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
+                       rotationZeroPoint = Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
                        haveZeroPoint = true;
                        rotationAngle = 0;
                        update();
@@ -433,8 +488,9 @@ WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumP
                else if (tool == TOOLFlipWinding)
                {
                        pts.InvertPolyDrawSequence(pts.GetPolyForPointNumber(ptHighlight));
-                       pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
-                       QCursor::setPos(mapToGlobal(pt));
+//                     pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight));
+                       Vector pt = Painter::QtToCartesianCoords(Vector(pts.GetX(ptHighlight), pts.GetY(ptHighlight)));
+                       QCursor::setPos(mapToGlobal(QPoint(pt.x, pt.y)));
                        update();
                }
        }
@@ -458,13 +514,14 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
        else if (event->buttons() == Qt::MidButton)
        {
                // Calc offset from previous point
-               pt = event->pos();
-               ptOffset = QPoint(pt.x() - ptPrevious.x(), pt.y() - ptPrevious.y());
+               Vector pt(event->x(), event->y());
+               pt /= Global::zoom;
+               ptOffset = Vector(pt.x - ptPrevious.x, pt.y - ptPrevious.y);
 
 // 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();
+               offsetX -= ptOffset.x, offsetY += ptOffset.y;
                update();
                ptPrevious = pt;
        }
@@ -476,20 +533,22 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                        if (tool == TOOLSelect && pts.GetNumPoints() == 0)
                                return;
 
-                       QPoint pt2 = GetAdjustedMousePosition(event);
-                       pts.SetXY(ptHighlight, pt2.x(), pt2.y());
+//                     QPoint pt2 = GetAdjustedMousePosition(event);
+                       Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       pts.SetXY(ptHighlight, pt2.x, pt2.y);
                        update();
                }
                else if (tool == TOOLPolySelect)
                {
                        if (pts.GetNumPoints() > 0)
                        {
-                               QPoint pt2 = GetAdjustedMousePosition(event);
+//                             QPoint pt2 = GetAdjustedMousePosition(event);
+                               Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                                // Should also set onCurve here as well, depending on keystate
 //Or should we?
 //Would be nice, but we'd need to trap the keyPressEvent() as well, otherwise pressing/releasing
 //the hotkey would show no change until the user moved their mouse.
-                               pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x() - pts.GetX(ptHighlight), pt2.y() - pts.GetY(ptHighlight));
+                               pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight));
                                update();
                        }
                }
@@ -499,18 +558,20 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                        {
                                if (!haveZeroPoint)
                                {
-                                       rotationZeroPoint = GetAdjustedMousePosition(event);
+//                                     rotationZeroPoint = GetAdjustedMousePosition(event);
+                                       rotationZeroPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                                        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);
+//                                     QPoint currentPoint = GetAdjustedMousePosition(event);
+                                       Vector currentPoint = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                                       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);
 
@@ -522,6 +583,22 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                update();
                        }
                }
+               else if (tool == TOOLMultiSelect)
+               {
+//                     QPoint pt = GetAdjustedMousePosition(event);
+                       Vector pt = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
+                       selection.setBottomRight(QPoint(pt.x, pt.y));
+
+                       for(int i=0; i<pts.GetNumPoints(); i++)
+                       {
+                               if (selection.contains(QPoint(pts.GetX(i), pts.GetY(i))))
+                                       selectedPoints[i] = true;
+                               else
+                                       selectedPoints[i] = false;
+                       }
+
+                       update();
+               }
        }
        else if (event->buttons() == Qt::NoButton)
        {
@@ -529,13 +606,14 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt
                        || tool == TOOLPolySelect || tool == TOOLRotatePoly || tool == TOOLFlipWinding)
                {
-                       QPoint pt2 = GetAdjustedMousePosition(event);
+//                     QPoint pt2 = GetAdjustedMousePosition(event);
+                       Vector pt2 = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
                        double closest = 1.0e+99;
 
                        for(int i=0; i<pts.GetNumPoints(); i++)
                        {
-                               double dist = ((pt2.x() - pts.GetX(i)) * (pt2.x() - pts.GetX(i)))
-                                       + ((pt2.y() - pts.GetY(i)) * (pt2.y() - pts.GetY(i)));
+                               double dist = ((pt2.x - pts.GetX(i)) * (pt2.x - pts.GetX(i)))
+                                       + ((pt2.y - pts.GetY(i)) * (pt2.y - pts.GetY(i)));
 
                                if (dist < closest)
                                        closest = dist, ptHighlight = i;
@@ -547,15 +625,17 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                update();
                        }
 
-                       // What follows here looks like voodoo, but is really simple. What we do is
-                       // check to see if the mouse point has a perpendicular intersection with any of
-                       // the line segments. If it does, calculate the length of the perpendicular
-                       // and choose the smallest length. If there is no perpendicular, then choose the
-                       // length of line connecting the closer of either the first endpoint or the
-                       // second and choose the smallest of those.
+                       // What follows here looks like voodoo, but is really simple. What
+                       // we do is check to see if the mouse point has a perpendicular
+                       // intersection with any of the line segments. If it does,
+                       // calculate the length of the perpendicular and choose the
+                       // smallest length. If there is no perpendicular, then choose the
+                       // length of line connecting the closer of either the first
+                       // endpoint or the second and choose the smallest of those.
 
-                       // There is one bit of math that looks like voodoo to me ATM--will explain once
-                       // I understand it better (the calculation of the length of the perpendicular).
+                       // There is one bit of math that looks like voodoo to me ATM--will
+                       // explain once I understand it better (the calculation of the
+                       // length of the perpendicular).
 
                        if (pts.GetNumPoints() > 1 && tool == TOOLAddPt)
                        {
@@ -566,13 +646,15 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                                        int32_t 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),
-                                               v2(pt2.x(), pt2.y(), 0, p2x, p2y, 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.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.
+// 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.Magnitude();
@@ -583,12 +665,14 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 
 //The answer to the above looks like it might be found here:
 //
-//If the segment endpoints are s and e, and the point is p, then the test for the perpendicular
-//intercepting the segment is equivalent to insisting that the two dot products {s-e}.{s-p} and
-//{e-s}.{e-p} are both non-negative.  Perpendicular distance from the point to the segment is
-//computed by first computing the area of the triangle the three points form, then dividing by the
-//length of the segment.  Distances are done just by the Pythagorean theorem.  Twice the area of the
-//triangle formed by three points is the determinant of the following matrix:
+//If the segment endpoints are s and e, and the point is p, then the test for
+//the perpendicular intercepting the segment is equivalent to insisting that
+//the two dot products {s-e}.{s-p} and {e-s}.{e-p} are both non-negative.
+//Perpendicular distance from the point to the segment is computed by first
+//computing the area of the triangle the three points form, then dividing by
+//the length of the segment.  Distances are done just by the Pythagorean
+//theorem. Twice the area of the triangle formed by three points is the
+//determinant of the following matrix:
 //
 //sx sy 1
 //ex ey 1
@@ -596,8 +680,9 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
 //
 //By translating the start point to the origin, this can be rewritten as:
 //By subtracting row 1 from all rows, you get the following:
-//[because sx = sy = 0. you could leave out the -sx/y terms below. because we subtracted
-// row 1 from all rows (including row 1) row 1 turns out to be zero. duh!]
+//[because sx = sy = 0. you could leave out the -sx/y terms below. because we
+//subtracted row 1 from all rows (including row 1) row 1 turns out to be zero.
+//duh!]
 //
 //0         0         0
 //(ex - sx) (ey - sy) 0
@@ -617,7 +702,7 @@ void EditWindow::mouseMoveEvent(QMouseEvent * event)
                        }
                }
 
-               ptPrevious = event->pos();
+               ptPrevious = Vector(event->x(), event->y());
        }
 
        event->accept();
@@ -660,7 +745,7 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
                        haveZeroPoint = false;
 
                        if (tool == TOOLRotate)
-                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x(), rotationCenter.y()));
+                               pts.RotatePoints(rotationAngle, IPoint(rotationCenter.x, rotationCenter.y));
                        else
                        {
                                uint16_t poly = pts.GetPolyForPointNumber(ptHighlight);
@@ -677,6 +762,11 @@ void EditWindow::mouseReleaseEvent(QMouseEvent * event)
                ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&pts);
                ((TTEdit *)qApp)->charWnd->update();
 
+               if (tool == TOOLMultiSelect)
+               {
+                       selectionInProgress = false;
+                       update();
+               }
        }
 
        event->accept();
index 652535941fd35d21e45fdd477beed0f3f14e0d4f..11a5b0720eb66feb8734ff3a3a8ffe809a0efb29 100755 (executable)
@@ -12,6 +12,8 @@
 #include <stdint.h>
 #include "toolwindow.h"                                                        // For ToolType enum
 #include "glyphpoints.h"
+#include "painter.h"
+
 
 class EditWindow: public QWidget
 {
@@ -34,25 +36,29 @@ class EditWindow: public QWidget
                void CreateCursors(void);
                QPoint GetAdjustedMousePosition(QMouseEvent *);
                QPoint GetAdjustedClientPosition(int x, int y);
-               void DrawGlyph(QPainter & p, GlyphPoints & glyph);
-               void DrawGlyphPoly(QPainter & p, GlyphPoints & glyph, uint16_t poly);
+               void DrawGlyph(Painter & p, GlyphPoints & glyph);
+               void DrawGlyphPoly(Painter & p, GlyphPoints & glyph, uint16_t poly);
+               void ClearSelection(void);
 
        public:
                QImage image;
-               QPoint pt, ptOffset, ptPrevious;
-               double scale;                                                   // Window scaling factor
-               int32_t offsetX, offsetY;                                       // Window offsets
-               ToolType tool;                                                  // Current tool
-               GlyphPoints pts;                                                // Glyph point structure
+               Vector pt, ptOffset, ptPrevious;
+               double scale;                                           // Window scaling factor
+               int32_t offsetX, offsetY;                       // Window offsets
+               ToolType tool;                                          // Current tool
+               GlyphPoints pts;                                        // Glyph point structure
                int32_t ptHighlight, oldPtHighlight, ptNextHighlight, oldPtNextHighlight;
                int16_t polyHighlight, oldPolyHighlight;
                bool polyFirstPoint;
                bool showRotationCenter, haveZeroPoint;
-               QPoint rotationCenter, rotationZeroPoint, rotationCurrentPoint;
+               Vector rotationCenter, rotationZeroPoint, rotationCurrentPoint;
                double rotationAngle;
 
                ToolWindow * toolPalette;
-               QCursor cur[11];
+               QCursor cur[12];
+               bool selectedPoints[65536];     // Potential memory leak :-O
+               QRect selection;
+               bool selectionInProgress;
 };
 
 #endif // __EDITWINDOW_H__
diff --git a/src/global.cpp b/src/global.cpp
new file mode 100644 (file)
index 0000000..ad562ee
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// This page intentionally left (mostly) blank
+//
+
+#include "global.h"
+#include <QFont>
+//#include "structs.h"
+#include "toolwindow.h"
+
+// Initialize static variables
+
+bool Global::fixedAngle = false;
+bool Global::fixedLength = false;
+QFont * Global::font = 0;
+int Global::viewportHeight = 0;
+
+bool Global::deleteActive = false;
+bool Global::dimensionActive = false;
+bool Global::snapToGrid = true;
+
+//snapToPoints all well here?
+bool Global::ignoreClicks = false;
+bool Global::dontMove = false;
+bool Global::selectionInProgress = false;
+QRectF Global::selection;
+
+int Global::tool = TOOLSelect;
+//int Global::toolState = TSNone;
+
+double Global::gridSpacing;
+int Global::currentLayer = 0;
+Point Global::snapPoint;
+bool Global::snapPointIsValid = false;
+uint32_t Global::objectID = 1;
+
+Vector Global::origin(-10.0, -10.0);
+double Global::zoom = 1.0;
+Vector Global::screenSize(200.0, 200.0);
+
+float Global::scale = 0.5;
+
+Point Global::intersectPoint[16]; // Overkill, yes
+double Global::intersectParam[16]; // Ditto
+int Global::numIntersectPoints = 0;
+int Global::numIntersectParams = 0;
+
+int Global::activeLayer = 0;
+int Global::numLayers = 1;
+std::vector<bool> Global::layerHidden;
+std::vector<bool> Global::layerLocked;
+
diff --git a/src/global.h b/src/global.h
new file mode 100644 (file)
index 0000000..64422da
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __GLOBALS_H__
+#define __GLOBALS_H__
+
+// Global variable class. Note that all vars are class vars, so we don't have
+// to do any instantiation shite--it's treated as a namespace.
+
+#include <stdint.h>
+#include <vector>
+#include <QRectF>
+#include "vector.h"
+
+class QFont;
+
+enum LineStyle { LSNone, LSSolid, LSDash, LSDot, LSDashDot, LSDashDotDot };
+
+
+class Global
+{
+       public:
+               static double gridSpacing;
+               static bool selectionInProgress;
+               static QRectF selection;
+               static int currentLayer;
+               static QFont * font;
+               static Point snapPoint;
+               static bool snapPointIsValid;
+
+               static bool fixedAngle;
+               static bool fixedLength;
+               static int viewportHeight;
+               static bool deleteActive;
+               static bool dimensionActive;
+
+               static bool snapToGrid;
+               static bool ignoreClicks;
+               static bool dontMove;
+               static uint32_t objectID;
+               static int tool;
+               static int toolState;
+
+               static Point origin;
+               static double zoom;
+               static Vector screenSize;
+
+               static float scale;
+
+               static Point intersectPoint[16]; // Overkill, yes
+               static double intersectParam[16]; // Ditto
+               static int numIntersectPoints;
+               static int numIntersectParams;
+
+               static int activeLayer;
+               static int numLayers;
+               static std::vector<bool> layerHidden;
+               static std::vector<bool> layerLocked;
+};
+
+#endif // __GLOBALS_H__
+
index 0b0575253914002506c9186279f2b0a2c37a9d1b..4ae01e5d5d8630c0d9dcec1cfd0d6cb0689db0f4 100755 (executable)
@@ -10,7 +10,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  ------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  ??/??/200?  Created this file
 // JLH  05/18/2004  Added pure point adding, inserting, better polygon handling
 //
@@ -247,6 +247,7 @@ void GlyphPoints::Clear(void)
 
 void GlyphPoints::InsertPoint(uint16_t pt, int xx, int yy, bool oc)
 {
+//wouldn't it be better to treat this case as inserting at the end?
        if (pt > numPoints)                                                     // > because we can insert at end...!
                throw GP_OUT_OF_RANGE;
 
@@ -267,7 +268,6 @@ void GlyphPoints::InsertPoint(uint16_t pt, int xx, int yy, bool oc)
 //we're adding to the end of the structure: [DONE, below]
        int polyInsert = (pt == numPoints ? numPolys - 1 : GetPoly(pt));
        for(int i=polyInsert; i<numPolys; i++)
-//     for(int i=GetPoly(pt); i<numPolys; i++)
                polyEnd[i]++;                                                   // Bump polygons' end point
 
        numPoints++;
@@ -379,6 +379,22 @@ WriteLogMsg("Exception: GetY(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoint
 }
 
 
+Vector GlyphPoints::GetXY(uint16_t pt)
+{
+       if (pt >= numPoints)
+#ifdef DEBUG
+{
+WriteLogMsg("Exception: GetXY(uint16_t). pt=%u, numPoints=%u\xD\xA", pt, numPoints);
+#endif
+               throw GP_OUT_OF_RANGE;
+#ifdef DEBUG
+}
+#endif
+
+       return Vector(x[pt], y[pt]);
+}
+
+
 bool GlyphPoints::GetOnCurve(uint16_t pt)
 {
        if (pt >= numPoints)
index 8e8011f2b4893c9232df8186e36297a305853bd7..5602cbe82a87f43b06a468bacd9fa2b8599058f8 100755 (executable)
@@ -12,6 +12,7 @@
 
 #include <stdint.h>
 #include <stdio.h>
+#include "vector.h"
 
 
 // "IPoint" is an Integer based Point
@@ -66,6 +67,7 @@ class GlyphPoints
                uint16_t GetNumPolys(void);
                int GetX(uint16_t);
                int GetY(uint16_t);
+               Vector GetXY(uint16_t);
                bool GetOnCurve(uint16_t);
                int GetX(uint16_t, uint16_t);
                int GetNextX(uint16_t, uint16_t);
diff --git a/src/graphicprimitives.cpp b/src/graphicprimitives.cpp
deleted file mode 100755 (executable)
index 9dec215..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-//
-// Graphics primitives
-//
-// Various graphic functions that are slightly more complex than those that
-// come with various widget libraries.
-//
-// by James L. Hammons
-// (C) 2005 Underground Software
-//
-// JLH = James L. Hammons <jlhamm@acm.org>
-//
-// Who  When        What
-// ---  ----------  -------------------------------------------------------------
-// JLH  03/14/1998  Created this file
-// JLH  01/20/2005  Converted to use wxWidgets
-// JLH  08/30/2008  Repurposed file to handle more than just bezier curves
-//
-
-#include "graphicprimitives.h"
-
-double abs(double n)                                                   // Helper function
-{
-       return (n < 0 ? -n : n);
-}
-
-
-//
-// This function takes three points and draws a curve using a second order
-// Bezier function.
-//
-void Bezier(QPainter &p, point p1, point p2, point p3)
-{
-       double step = abs(p1.x - p3.x), tmp = abs(p1.y - p3.y);
-       step = (tmp > step ? tmp : step);                       // Get the larger of the two...
-       step = (step > 0 ? 1/step : 1);                         // & convert to valid step value
-       step *= 2.0;                                                            // (double it to draw less...)
-
-       int prevX = (int)p1.x, prevY = (int)p1.y;
-
-       for(double u=0; u<=1; u+=step)
-       {
-               double _2u = 2*u, _uu = u*u, _2uu = 2*_uu;
-               double x = (p1.x * (1 - _2u + _uu)) + (p2.x * (_2u - _2uu)) + (p3.x * _uu);
-               double y = (p1.y * (1 - _2u + _uu)) + (p2.y * (_2u - _2uu)) + (p3.y * _uu);
-
-               p.drawLine(prevX, prevY, (int)x, (int)y);
-               prevX = (int)x, prevY = (int)y;
-       }
-
-       p.drawLine(prevX, prevY, (int)p3.x, (int)p3.y);
-}
-
-
-//
-// This is a convenience funtion, using IPoints :-)
-//
-void Bezier(QPainter &p, IPoint p1, IPoint p2, IPoint p3)
-{
-       Bezier(p, point(p1.x, p1.y), point(p2.x, p2.y), point(p3.x, p3.y));
-}
-
-
-//
-// Draw a round dot (5x5, centered on [x, y])
-//
-void DrawRoundDot(QPainter &p, int32_t x, int32_t y)
-{
-       QPoint pt[8];
-
-       pt[0] = QPoint(x - 1, y - 2);
-       pt[1] = QPoint(x + 1, y - 2);
-       pt[2] = QPoint(x + 2, y - 1);
-       pt[3] = QPoint(x + 2, y + 1);
-       pt[4] = QPoint(x + 1, y + 2);
-       pt[5] = QPoint(x - 1, y + 2);
-       pt[6] = QPoint(x - 2, y + 1);
-       pt[7] = QPoint(x - 2, y - 1);
-
-       p.drawPolygon(pt, 8);
-}
-
-
-//
-// Draw a sqaure dot (5x5, centered on [x, y])
-//
-void DrawSquareDot(QPainter &p, int32_t x, int32_t y)
-{
-       QPoint pt[4];
-
-       pt[0] = QPoint(x - 2, y - 2);
-       pt[1] = QPoint(x + 2, y - 2);
-       pt[2] = QPoint(x + 2, y + 2);
-       pt[3] = QPoint(x - 2, y + 2);
-
-       p.drawPolygon(pt, 4);
-}
-
-
-//
-// Draw a sqaure dot (nxn, centered on [x, y])
-//
-void DrawSquareDotN(QPainter &p, int32_t x, int32_t y, uint32_t n)
-{
-       QPoint pt[4];
-       uint32_t offset = (n - 1) / 2;
-
-       pt[0] = QPoint(x - offset, y - offset);
-       pt[1] = QPoint(x + offset, y - offset);
-       pt[2] = QPoint(x + offset, y + offset);
-       pt[3] = QPoint(x - offset, y + offset);
-
-       p.drawPolygon(pt, 4);
-}
-
-
-//
-// Draw a round dot (nxn, centered on [x, y])
-//
-void DrawRoundDotN(QPainter &p, int32_t x, int32_t y, uint32_t n)
-{
-       int radius = (n / 2) + 1;
-       p.drawEllipse(x - radius, y - radius, n, n);
-}
diff --git a/src/graphicprimitives.h b/src/graphicprimitives.h
deleted file mode 100755 (executable)
index 6d5b27b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Graphics primitives
-//
-// Various graphic functions that are slightly more complex than those that
-// come with various widget libraries.
-//
-
-#ifndef __GRAPHICPRIMITIVES_H__
-#define __GRAPHICPRIMITIVES_H__
-
-#include <stdint.h>
-#include <QtGui>                                                               // For QPainter
-#include "glyphpoints.h"                                               // For IPoint
-
-struct point
-{
-       float x, y;
-
-       point(float xx = 0, float yy = 0): x(xx), y(yy) {}
-};
-
-void Bezier(QPainter &, point, point, point);
-void Bezier(QPainter &, IPoint, IPoint, IPoint);
-void DrawRoundDot(QPainter &, int32_t, int32_t);
-void DrawSquareDot(QPainter &, int32_t, int32_t);
-void DrawRoundDotN(QPainter &, int32_t, int32_t, uint32_t);
-void DrawSquareDotN(QPainter &, int32_t, int32_t, uint32_t);
-
-#endif // __GRAPHICPRIMITIVES_H__
index b202fcb72277ee08f92d0d9f9a6007236d8f05ab..cc430d055b5ad56d364c8994a6faf96ed42749ad 100755 (executable)
@@ -1,15 +1,15 @@
 //
 // A generic list class using a circular singly linked list
-// by James L. Hammons
-// (C) 2004 Underground Software
+// by James Hammons
+// (C) 2016 Underground Software
 //
-// Based upon work I did for CS240 Project 5 at Cal Poly Pomona for Dr. Bruce Hillam.
-// Hello Dr. Hillam! :-)
+// Based upon work I did for CS240 Project 5 at Cal Poly Pomona for Dr. Bruce
+// Hillam. Hello Dr. Hillam! :-)
 //
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  08/30/1999  Created this file
 // JLH  05/11/2004  Cleaned up a few things in the implementation
 //
index dea9087af7bf9496ed81a93fd60475091567f55e..ef738e95102f56ae4ec784ecc84b86949b297f2d 100644 (file)
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  04/10/2002  Created this file
 // JLH  05/10/2004  Translated file from ASM to CPP
 // JLH  05/14/2004  Added rudimentary editing capability to tool palette tools
@@ -18,7 +18,8 @@
 
 // FIXED:
 //
-// - Fix problem with tool palette not getting focus 1st time it's called up [DONE]
+// - Fix problem with tool palette not getting focus 1st time it's called up
+//   [DONE]
 // - Split out windows/classes defined here into their own files [DONE]
 //
 // STILL TO BE DONE:
@@ -47,7 +48,7 @@ MainWindow::MainWindow()
        setCentralWidget(editWnd);
        editWnd->setFocus();
        setWindowIcon(QIcon(":/res/ttedit.png"));
-       setWindowTitle("TTEdit!");
+       setWindowTitle("TTEdit! - Untitled");
 
 #if 0
 //     createActions();
@@ -102,6 +103,8 @@ MainWindow::MainWindow()
 #endif
 
        //      Create status bar
+       scaleIndicator = new QLabel("Scale: 100%");
+       statusBar()->addPermanentWidget(scaleIndicator);
        statusBar()->showMessage(tr("Ready"));
 
        ReadSettings();
@@ -119,8 +122,8 @@ MainWindow::MainWindow()
 //
 // 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 * 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);
@@ -136,8 +139,9 @@ QAction * MainWindow::CreateAction(QString name, QString tooltip, QString status
 // 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 * 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);
@@ -155,12 +159,18 @@ QAction * MainWindow::CreateAction(QString name, QString tooltip, QString status
 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());
+       openFileAct = CreateAction("&Open File", "Open File", "Open a glyph file", QIcon(), QKeySequence("ctrl+o"));
+       saveFileAct = CreateAction("&Save File", "Save File", "Save a glyph file", QIcon(), QKeySequence("ctrl+s"));
+       quitAct = CreateAction("&Quit", "Quit", "Exits from the TTEdit application", QIcon(), QKeySequence("ctrl+q"));
+       zoomInAct = CreateAction("Zoom In", "Zoom In", "Zoom into the canvas", QIcon(), QKeySequence("+"), QKeySequence("="));
+       zoomOutAct = CreateAction("Zoom Out", "Zoom Out", "Zoom out of canvas", QIcon(), QKeySequence("-"));
 
        connect(newGlyphAct, SIGNAL(triggered()), this, SLOT(NewGlyph()));
        connect(openFileAct, SIGNAL(triggered()), this, SLOT(OpenFile()));
        connect(saveFileAct, SIGNAL(triggered()), this, SLOT(SaveFile()));
+       connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
+       connect(zoomInAct, SIGNAL(triggered()), this, SLOT(ZoomIn()));
+       connect(zoomOutAct, SIGNAL(triggered()), this, SLOT(ZoomOut()));
 }
 
 
@@ -170,8 +180,13 @@ void MainWindow::CreateMenus(void)
        menu->addAction(newGlyphAct);
        menu->addAction(openFileAct);
        menu->addAction(saveFileAct);
+       menu->addSeparator();
+       menu->addAction(quitAct);
 //     menu->addAction(fileSaveAsAct);
 //     menu->addAction(fileCloseAct);
+       menu = menuBar()->addMenu(tr("&View"));
+       menu->addAction(zoomInAct);
+       menu->addAction(zoomOutAct);
 }
 
 
@@ -194,6 +209,8 @@ void MainWindow::NewGlyph(void)
        ((TTEdit *)qApp)->charWnd->update();
 //     editWnd->polyFirstPoint = true;
        editWnd->update();
+       setWindowTitle("TTEdit! - Untitled");
+       editWnd->setFocus();
 }
 
 
@@ -213,6 +230,8 @@ void MainWindow::OpenFile(void)
        ((TTEdit *)qApp)->charWnd->MakePathFromPoints(&(editWnd->pts));
        ((TTEdit *)qApp)->charWnd->update();
        editWnd->update();
+       setWindowTitle(QString("TTEdit! - %1").arg(filename));
+       editWnd->setFocus();
 }
 
 
@@ -228,6 +247,30 @@ void MainWindow::SaveFile(void)
 
        editWnd->pts.SaveGlyphToFile(file);
        fclose(file);
+       setWindowTitle(QString("TTEdit! - %1").arg(filename));
+       editWnd->setFocus();
+}
+
+
+void MainWindow::ZoomIn(void)
+{
+       if (editWnd->scale == 4.0)
+               return;
+
+       editWnd->scale *= 2.0;
+       scaleIndicator->setText(QString("Scale: %1%").arg(editWnd->scale * 100.0));
+       editWnd->update();
+}
+
+
+void MainWindow::ZoomOut(void)
+{
+       if (editWnd->scale == 0.25)
+               return;
+
+       editWnd->scale *= 0.5;
+       scaleIndicator->setText(QString("Scale: %1%").arg(editWnd->scale * 100.0));
+       editWnd->update();
 }
 
 
index 7038b1ed8d52b0f639ebd24eac75b14dcd559464..bc547de6a3f395b0a22856b3d6612095c946c523 100644 (file)
@@ -32,6 +32,8 @@ class MainWindow: public QMainWindow
                void NewGlyph(void);
                void OpenFile(void);
                void SaveFile(void);
+               void ZoomIn(void);
+               void ZoomOut(void);
 
        private:
                QAction * CreateAction(QString name, QString tooltip, QString statustip,
@@ -46,6 +48,7 @@ class MainWindow: public QMainWindow
 
                EditWindow * editWnd;
 //             CharWindow * charWnd;
+               QLabel * scaleIndicator;
 #if 0
        private:
        protected:
@@ -70,6 +73,11 @@ class MainWindow: public QMainWindow
                QAction * newGlyphAct;
                QAction * openFileAct;
                QAction * saveFileAct;
+               QAction * quitAct;
+               QAction * zoomInAct;
+               QAction * zoomOutAct;
+               QAction * scaleAct;
+//             QString filename;
 };
 
 #endif // __MAINWINDOW_H__
diff --git a/src/mathconstants.h b/src/mathconstants.h
new file mode 100644 (file)
index 0000000..42f4940
--- /dev/null
@@ -0,0 +1,23 @@
+// Mathematical Constants used by Architektonas
+//
+// Part of the Architektonas Project
+// (C) 2011 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// NOTE: Since this has no code associated with it, there is no corresponding
+//       .cpp file.
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  04/01/2011  Created this file
+//
+
+#define PI                 3.14159265358979323846264338327
+#define PI_OVER_2          (PI / 2.0)
+#define PI3_OVER_2         ((3.0 * PI) / 2.0)
+#define PI_TIMES_2         (PI * 2.0)
+#define RADIANS_TO_DEGREES (180.0 / PI)
+#define DEGREES_TO_RADIANS (PI / 180.0)
+
diff --git a/src/painter.cpp b/src/painter.cpp
new file mode 100644 (file)
index 0000000..16268e7
--- /dev/null
@@ -0,0 +1,490 @@
+//
+// painter.cpp: Paint abstraction layer between Archtektonas and Qt
+//
+// Part of the Architektonas Project
+// (C) 2011 Underground Software
+// See the README and GPLv3 files for licensing and warranty information
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// WHO  WHEN        WHAT
+// ---  ----------  ------------------------------------------------------------
+// JLH  09/20/2011  Created this file
+//
+
+#include "painter.h"
+#include "global.h"
+#include "mathconstants.h"
+
+
+// Set class variable defaults
+//Vector Painter::origin(-10.0, -10.0);
+//double Painter::zoom = 1.0;
+//Vector Painter::screenSize(200.0, 200.0);
+
+
+Painter::Painter(QPainter * p/*= NULL*/): painter(p)
+{
+}
+
+
+Painter::~Painter()
+{
+}
+
+
+Vector Painter::CartesianToQtCoords(Vector v)
+{
+       // Convert regular Cartesian coordinates to the inverted Y-axis Qt
+       // coordinates at the current origin and zoom level.
+       return Vector((v.x - Global::origin.x) * Global::zoom, Global::screenSize.y - ((v.y - Global::origin.y) * Global::zoom));
+}
+
+
+Vector Painter::QtToCartesianCoords(Vector v)
+{
+       // Convert screen location, with inverted Y-axis coordinates, to regular
+       // Cartesian coordinates at the current zoom level.
+       return Vector((v.x / Global::zoom) + Global::origin.x, ((Global::screenSize.y - v.y) / Global::zoom) + Global::origin.y);
+/*
+How to do it:
+
+e.g., we have a point on the screen at Qt coords of 10, 10, screenSize is 100, 100.
+origin is -10, -10 and zoom level is 2 (200%)
+
+1st, invert the Y: 10, 10 -> 10, 90
+2nd, add origin:   10, 90 ->  0, 80 (no, not right--err, yes, it is)
+3rd, aply zoom:     0, 80 ->  0, 40
+
+or, is it:
+
+1st, invert the Y: 10, 10 -> 10, 90
+2nd, aply zoom:    10, 90 ->  5, 45
+3rd, add origin:    5, 45 -> -5, 35
+
+it depends on whether or not origin is in Qt coords or cartesian. If Qt, then the 1st
+is correct, otherwise, the 2nd is correct.
+
+The way we calculate the Cartesian to Qt shows the 2nd (origin is cartesian) to be correct.
+*/
+}
+
+
+void Painter::SetRenderHint(int hint)
+{
+       if (!painter)
+               return;
+
+       painter->setRenderHint((QPainter::RenderHint)hint);
+}
+
+
+void Painter::SetPen(QPen pen)
+{
+       if (!painter)
+               return;
+
+       painter->setPen(pen);
+}
+
+
+void Painter::SetPen(uint32_t color, float size/*= 0*/, int style/*= 0*/)
+{
+       if (!painter)
+               return;
+
+       // We can cast style as Qt:PenStyle because they line up 1-to-1
+       painter->setPen(QPen(QColor(color >> 16, (color >> 8) & 0xFF, color & 0xFF, 255),
+               size, (Qt::PenStyle)style));
+}
+
+
+void Painter::SetBrush(QBrush brush)
+{
+       if (!painter)
+               return;
+
+       painter->setBrush(brush);
+}
+
+
+void Painter::SetBrush(uint32_t color)
+{
+       if (!painter)
+               return;
+
+       painter->setBrush(QBrush(QColor(color >> 16, (color >> 8) & 0xFF, color & 0xFF, 255)));
+}
+
+
+void Painter::SetFont(QFont font)
+{
+       if (!painter)
+               return;
+
+       painter->setFont(font);
+}
+
+
+void Painter::DrawAngledText(Vector center, double angle, QString text, double size)
+{
+       if (!painter)
+               return;
+
+       // Strategy: Since Qt doesn't have any rotated text drawing functions,
+       // we instead translate the origin to the center of the text to be drawn and
+       // then rotate the frame to the desired angle.
+       center = CartesianToQtCoords(center);
+
+       // We may need this stuff... If dimension text is large enough.
+//     int textWidth = QFontMetrics(painter->font()).width(text);
+//     int textHeight = QFontMetrics(painter->font()).height();
+       QRectF textBox(-100.0 * Global::zoom * size, -100.0 * Global::zoom * size, 200.0 * Global::zoom * size, 200.0 * Global::zoom * size);   // x, y, w, h; x/y = upper left corner
+
+       // This is in pixels. Might not render correctly at all zoom levels.
+       // Need to figure out if dimensions are always rendered at one size
+       // regardless of zoom, or if they have a definite size, and are thus
+       // zoomable.
+       float yOffset = -12.0 * Global::zoom * size;
+
+       // Fix text so it isn't upside down...
+       if ((angle > PI * 0.5) && (angle < PI * 1.5))
+       {
+               angle += PI;
+               yOffset = 12.0 * Global::zoom * size;
+       }
+
+       textBox.translate(0, yOffset);
+       painter->save();
+       painter->translate(center.x, center.y);
+       // Angles are backwards in the Qt coord system, so we flip ours...
+       painter->rotate(-angle * RADIANS_TO_DEGREES);
+//Need to fix this so the text scales as well...
+       painter->drawText(textBox, Qt::AlignCenter, text);
+       painter->restore();
+}
+
+
+//
+// Draw angled text. Draws text using point p as the upper left corner.
+// Size is point size, angle is in radians (defaults to 0).
+//
+void Painter::DrawTextObject(Point p, QString text, double size, double angle/*= 0*/)
+{
+       if (!painter)
+               return;
+
+       p = CartesianToQtCoords(p);
+       painter->setFont(QFont("Arial", Global::zoom * size));
+       int textWidth = QFontMetrics(painter->font()).width(text);
+       int textHeight = QFontMetrics(painter->font()).height();
+
+       QRectF textBox(0, 0, textWidth, textHeight);
+       painter->save();
+       painter->translate(p.x, p.y);
+       // Angles are backwards in the Qt coord system, so we flip ours...
+       painter->rotate(-angle * RADIANS_TO_DEGREES);
+       painter->drawText(textBox, Qt::AlignLeft | Qt::AlignTop , text);
+       painter->restore();
+}
+
+
+void Painter::DrawArc(Vector center, double radius, double startAngle, double span)
+{
+       center = CartesianToQtCoords(center);
+       // Need to multiply scalar quantities by the zoom factor as well...
+       radius *= Global::zoom;
+       QRectF rectangle(QPointF(center.x - radius, center.y - radius),
+               QPointF(center.x + radius, center.y + radius));
+       int angle1 = (int)(startAngle * RADIANS_TO_DEGREES * 16.0);
+       int angle2 = (int)(span * RADIANS_TO_DEGREES * 16.0);
+       painter->drawArc(rectangle, angle1, angle2);
+}
+
+
+void Painter::DrawEllipse(Vector center, double axis1, double axis2)
+{
+       // Need to multiply scalar quantities by the zoom factor as well...
+       center = CartesianToQtCoords(center);
+       painter->drawEllipse(QPointF(center.x, center.y), axis1 * Global::zoom, axis2 * Global::zoom);
+}
+
+
+// This function is for drawing object handles without regard for zoom level;
+// we don't want our object handle size to depend on the zoom level!
+void Painter::DrawHandle(Vector center)
+{
+       center = CartesianToQtCoords(center);
+       painter->setPen(QPen(Qt::red, 2.0, Qt::DotLine));
+       painter->setBrush(Qt::NoBrush);
+       painter->drawEllipse(QPointF(center.x, center.y), 4.0, 4.0);
+}
+
+
+// This function is for drawing object handles without regard for zoom level;
+// we don't want our object handle size to depend on the zoom level!
+void Painter::DrawArrowHandle(Vector center, double angle)
+{
+       center = CartesianToQtCoords(center);
+       QPolygonF arrow;
+
+       // Since we're drawing directly on the screen, the Y is inverted. So we use
+       // the mirror of the angle.
+       double orthoAngle = -angle + (PI / 2.0);
+       Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
+       Vector unit = Vector(cos(-angle), sin(-angle));
+
+       Point p0 = center + (unit * 6.0);
+       Point p1 = center + (unit * 21.0);
+       Point p1b = center + (unit * 11.0);
+       Point p2 = p1b + (orthogonal * 5.0);
+       Point p3 = p1b - (orthogonal * 5.0);
+
+       painter->drawLine(p0.x, p0.y, p1.x, p1.y);
+       arrow << QPointF(p1.x, p1.y) << QPointF(p2.x, p2.y) << QPointF(p3.x, p3.y);
+
+       painter->drawPolygon(arrow);
+}
+
+
+// This function is for drawing object handles without regard for zoom level;
+// we don't want our object handle size to depend on the zoom level!
+void Painter::DrawArrowToLineHandle(Vector center, double angle)
+{
+       DrawArrowHandle(center, angle);
+       center = CartesianToQtCoords(center);
+
+       // Since we're drawing directly on the screen, the Y is inverted. So we use
+       // the mirror of the angle.
+       double orthoAngle = -angle + (PI / 2.0);
+       Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
+       Vector unit = Vector(cos(-angle), sin(-angle));
+
+       Point p1 = center + (unit * 21.0);
+       Point p2 = p1 + (orthogonal * 7.0);
+       Point p3 = p1 - (orthogonal * 7.0);
+
+       painter->drawLine(p2.x, p2.y, p3.x, p3.y);
+}
+
+
+void Painter::DrawLine(int x1, int y1, int x2, int y2)
+{
+       if (!painter)
+               return;
+
+       Vector v1 = CartesianToQtCoords(Vector(x1, y1));
+       Vector v2 = CartesianToQtCoords(Vector(x2, y2));
+       painter->drawLine(v1.x, v1.y, v2.x, v2.y);
+}
+
+
+void Painter::DrawLine(Vector v1, Vector v2)
+{
+       if (!painter)
+               return;
+
+       v1 = CartesianToQtCoords(v1);
+       v2 = CartesianToQtCoords(v2);
+       painter->drawLine(QPointF(v1.x, v1.y), QPointF(v2.x, v2.y));
+}
+
+
+void Painter::DrawPoint(int x, int y)
+{
+       if (!painter)
+               return;
+
+       Vector v = CartesianToQtCoords(Vector(x, y));
+       painter->drawPoint(v.x, v.y);
+}
+
+
+// The rect passed in is in Qt coordinates...
+void Painter::DrawRoundedRect(QRectF rect, double radiusX, double radiusY)
+{
+       if (!painter)
+               return;
+
+       painter->drawRoundedRect(rect, radiusX, radiusY);
+}
+
+
+// The rect passed in is in Cartesian but we want to pad it by a set number of
+// pixels (currently set at 8), so the pad looks the same regardless of zoom.
+void Painter::DrawPaddedRect(QRectF rect)
+{
+       if (!painter)
+               return;
+
+       Vector v1 = CartesianToQtCoords(Vector(rect.x(), rect.y()));
+       Vector v2 = CartesianToQtCoords(Vector(rect.right(), rect.bottom()));
+       QRectF screenRect(QPointF(v1.x, v1.y), QPointF(v2.x, v2.y));
+       screenRect.adjust(-8, 8, 8, -8);        // Left/top, right/bottom
+       painter->drawRect(screenRect);
+}
+
+
+void Painter::DrawRect(QRectF rect)
+{
+       if (!painter)
+               return;
+
+       Vector v1 = CartesianToQtCoords(Vector(rect.x(), rect.y()));
+       Vector v2 = CartesianToQtCoords(Vector(rect.right(), rect.bottom()));
+       QRectF screenRect(QPointF(v1.x, v1.y), QPointF(v2.x, v2.y));
+       painter->drawRect(screenRect);
+}
+
+
+void Painter::DrawText(QRectF rect, int type, QString text)
+{
+       if (!painter)
+               return;
+
+       painter->drawText(rect, (Qt::AlignmentFlag)type, text);
+}
+
+
+void Painter::DrawArrowhead(Vector head, Vector tail, double size)
+{
+       if (!painter)
+               return;
+
+       QPolygonF arrow;
+
+       // We draw the arrowhead aligned along the line from tail to head
+       double angle = Vector(head - tail).Angle();
+       double orthoAngle = angle + (PI / 2.0);
+       Vector orthogonal = Vector(cos(orthoAngle), sin(orthoAngle));
+       Vector unit = Vector(head - tail).Unit();
+
+       Point p1 = head - (unit * 9.0 * size);
+       Point p2 = p1 + (orthogonal * 3.0 * size);
+       Point p3 = p1 - (orthogonal * 3.0 * size);
+
+       Point p4 = CartesianToQtCoords(head);
+       Point p5 = CartesianToQtCoords(p2);
+       Point p6 = CartesianToQtCoords(p3);
+
+       arrow << QPointF(p4.x, p4.y) << QPointF(p5.x, p5.y) << QPointF(p6.x, p6.y);
+
+       painter->drawPolygon(arrow);
+}
+
+
+// Point is given in Cartesian coordinates
+void Painter::DrawCrosshair(Vector point)
+{
+       if (!painter)
+               return;
+
+       Vector screenPoint = CartesianToQtCoords(point);
+       painter->drawLine(0, screenPoint.y, Global::screenSize.x, screenPoint.y);
+       painter->drawLine(screenPoint.x, 0, screenPoint.x, Global::screenSize.y);
+}
+
+
+void Painter::DrawInformativeText(QString text)
+{
+       painter->setFont(*Global::font);
+       QRectF bounds = painter->boundingRect(QRectF(), Qt::AlignVCenter, text);
+       bounds.moveTo(17.0, 17.0);
+       QRectF textRect = bounds;
+       textRect.adjust(-7.0, -7.0, 7.0, 7.0);
+
+       QPen pen = QPen(QColor(0x00, 0xFF, 0x00), 1.0, Qt::SolidLine);
+       painter->setPen(pen);
+       painter->setBrush(QBrush(QColor(0x40, 0xFF, 0x40, 0x9F)));
+       painter->drawRoundedRect(textRect, 7.0, 7.0);
+
+       pen = QPen(QColor(0x00, 0x5F, 0xDF));
+       painter->setPen(pen);
+       painter->drawText(bounds, Qt::AlignVCenter, text);
+}
+
+
+void Painter::DrawBezier(Point p1, Point p2, Point p3)
+{
+       p1 = CartesianToQtCoords(p1);
+       p2 = CartesianToQtCoords(p2);
+       p3 = CartesianToQtCoords(p3);
+
+       QPainterPath path;
+       path.moveTo(p1.x, p1.y);
+       path.quadTo(p2.x, p2.y, p3.x, p3.y);
+       painter->drawPath(path);
+}
+
+
+void Painter::DrawBezier(IPoint p1, IPoint p2, IPoint p3)
+{
+       DrawBezier(Point(p1.x, p1.y), Point(p2.x, p2.y), Point(p3.x, p3.y));
+}
+
+
+//
+// Draw a sqaure dot (5x5, centered on Vector; non-scaled)
+//
+void Painter::DrawSquareDot(Vector v)
+{
+       QPoint pt[4];
+       v = CartesianToQtCoords(v);
+
+       pt[0] = QPoint(v.x - 2, v.y - 2);
+       pt[1] = QPoint(v.x + 2, v.y - 2);
+       pt[2] = QPoint(v.x + 2, v.y + 2);
+       pt[3] = QPoint(v.x - 2, v.y + 2);
+
+       painter->drawPolygon(pt, 4);
+}
+
+
+//
+// Draw a round dot (5x5, centered on Vector; non-scaled)
+//
+void Painter::DrawRoundDot(Vector v)
+{
+       QPoint pt[8];
+       v = CartesianToQtCoords(v);
+
+       pt[0] = QPoint(v.x - 1, v.y - 2);
+       pt[1] = QPoint(v.x + 1, v.y - 2);
+       pt[2] = QPoint(v.x + 2, v.y - 1);
+       pt[3] = QPoint(v.x + 2, v.y + 1);
+       pt[4] = QPoint(v.x + 1, v.y + 2);
+       pt[5] = QPoint(v.x - 1, v.y + 2);
+       pt[6] = QPoint(v.x - 2, v.y + 1);
+       pt[7] = QPoint(v.x - 2, v.y - 1);
+
+       painter->drawPolygon(pt, 8);
+}
+
+
+//
+// Draw a sqaure dot (nxn, centered on Vector; non-scaled)
+//
+void Painter::DrawSquareDotN(Vector v, uint32_t n)
+{
+       QPoint pt[4];
+       uint32_t offset = (n - 1) / 2;
+       v = CartesianToQtCoords(v);
+
+       pt[0] = QPoint(v.x - offset, v.y - offset);
+       pt[1] = QPoint(v.x + offset, v.y - offset);
+       pt[2] = QPoint(v.x + offset, v.y + offset);
+       pt[3] = QPoint(v.x - offset, v.y + offset);
+
+       painter->drawPolygon(pt, 4);
+}
+
+
+//
+// Draw a round dot (nxn, centered on Vector; non-scaled)
+//
+void Painter::DrawRoundDotN(Vector v, uint32_t n)
+{
+       int radius = (n / 2) + 1;
+       v = CartesianToQtCoords(v);
+       painter->drawEllipse(v.x - radius, v.y - radius, n, n);
+}
diff --git a/src/painter.h b/src/painter.h
new file mode 100644 (file)
index 0000000..c95b84a
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __PAINTER_H__
+#define __PAINTER_H__
+
+#include <stdint.h>
+#include <QtWidgets>
+#include "vector.h"
+#include "glyphpoints.h"
+
+//#define SCREEN_ZOOM  (1.0 / 4.0)
+
+// Forward declarations
+
+class Painter
+{
+       public:
+               Painter(QPainter * p = 0);
+               ~Painter();
+
+               void SetRenderHint(int);
+               void SetPen(QPen);
+               void SetPen(uint32_t, float size = 0, int style = 0);
+               void SetBrush(QBrush);
+               void SetBrush(uint32_t);
+               void SetFont(QFont);
+               void DrawAngledText(Vector, double, QString, double);
+               void DrawTextObject(Vector, QString, double, double angle = 0);
+               void DrawArc(Vector, double, double, double);
+               void DrawEllipse(Vector, double, double);
+               void DrawHandle(Vector);
+               void DrawArrowHandle(Vector, double);
+               void DrawArrowToLineHandle(Vector, double);
+               void DrawLine(int, int, int, int);
+               void DrawLine(Vector, Vector);
+               void DrawPoint(int, int);
+               void DrawRoundedRect(QRectF, double, double);
+               void DrawPaddedRect(QRectF);
+               void DrawRect(QRectF);
+               void DrawText(QRectF, int, QString);
+               void DrawArrowhead(Vector, Vector, double);
+               void DrawCrosshair(Vector);
+               void DrawInformativeText(QString);
+               void DrawBezier(Point, Point, Point);
+               void DrawBezier(IPoint, IPoint, IPoint);
+               void DrawSquareDot(Vector);
+               void DrawRoundDot(Vector);
+               void DrawSquareDotN(Vector, uint32_t);
+               void DrawRoundDotN(Vector, uint32_t);
+
+       public:
+               static Vector CartesianToQtCoords(Vector);
+               static Vector QtToCartesianCoords(Vector);
+
+       public:
+               // Class variables
+//             static Vector origin;           // The window origin, not location of the origin
+//             static double zoom;                     // Window zoom factor
+//             static Vector screenSize;       // Width & height of the window we're drawing on
+
+       private:
+               QPainter * painter;
+};
+
+#endif // __PAINTER_H__
index 13d3754d6429e1e7a039d5b1ec68422bd53dd11f..fda5b8e7c204a961d1a66692155f997ae462e567 100755 (executable)
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  08/28/2008  Created this file
 // JLH  03/11/2009  Converted from wxWidgets to Qt
 //
@@ -81,8 +81,10 @@ ToolType ToolWindow::FindSelectedTool(void)
                newTool = (ToolType)((y * 4) + x);
 
        // We don't have 11 yet, so fix this if the user selected the blank space
-       if (newTool > 10)
-               newTool = TOOLNone;
+//now we do!
+//     if (newTool > 10)
+//             newTool = TOOLNone;
 
        return newTool;
 }
+
index 47125c26ce397952b2f3784476d8446e90507b16..2864970fbb46c0bc4fc0768361ef6b4676008401 100755 (executable)
@@ -16,7 +16,7 @@ enum ToolType {
        TOOLNone = -1,                                                  // No tool
        TOOLSelect = 0,                                                 // The "selection" tool
        TOOLPolySelect,                                                 // Polygon selection tool
-       TOOLScroll,                                                             // Scroll window tool
+       TOOLMultiSelect,                                                // Rectangle selection tool
        TOOLZoom,                                                               // Zoom window tool
        TOOLAddPt,                                                              // Add point tool
        TOOLAddPoly,                                                    // Polygon creation tool
@@ -24,7 +24,8 @@ enum ToolType {
        TOOLDelPoly,                                                    // Delete polygon tool
        TOOLRotate,                                                             // Rotate tool
        TOOLRotatePoly,                                                 // Rotate polygon around centroid tool
-       TOOLFlipWinding                                                 // Change polygon's winding direction tool
+       TOOLFlipWinding,                                                // Change polygon's winding direction tool
+       TOOLScroll                                                              // Scroll window tool
 };
 
 class ToolWindow: public QWidget
index 9f34039982ccb8231ca5302734ff28e456e592a5..46e994362cc29a78e90164fc329df9c499dce53a 100755 (executable)
@@ -6,7 +6,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  04/10/2002  Created this file
 // JLH  05/10/2004  Translated file from ASM to CPP
 // JLH  05/14/2004  Added rudimentary editing capability to tool palette tools
index 799f0321ffc288aad01c42836e19b991d961d0c7..c8e6e7f241b8f61b6bc6373a4294689358e9b62d 100755 (executable)
@@ -11,7 +11,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  ??/??/199?  Created this file
 //
 //
index 1ba2064ee925fd510bd7bc0ed6d878664f344e98..fe627cd329adb397f28c3447512dfcad265c6f02 100755 (executable)
@@ -9,7 +9,7 @@
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  -----------------------------------------------------------
 // JLH  ??/??/2003  Created original implementation
 // JLH  05/14/2004  Separated header from implementation, added operator-
 //                  function
@@ -153,7 +153,7 @@ void vector::zero(const double epsilon/*= 1.0e-6*/)
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // 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
index 1e860184bef7fff1ed31905eb840693c0b002fa5..426123b155923112b7028507a7a4da88cc2503e5 100644 (file)
@@ -5,26 +5,29 @@ CONFIG += qt
 #CONFIG += qt debug
 QT     += widgets
 
-HEADERS += src/ttedit.h
-HEADERS += src/mainwindow.h
+HEADERS += src/charwindow.h
+HEADERS += src/debug.h
 HEADERS += src/editwindow.h
+HEADERS += src/global.h
 HEADERS += src/glyphpoints.h
-HEADERS += src/debug.h
+HEADERS += src/list.h
+HEADERS += src/mainwindow.h
+HEADERS += src/mathconstants.h
+HEADERS += src/painter.h
 HEADERS += src/toolwindow.h
-HEADERS += src/charwindow.h
+HEADERS += src/ttedit.h
 HEADERS += src/vector.h
-HEADERS += src/graphicprimitives.h
-HEADERS += src/list.h
 
-SOURCES += src/ttedit.cpp
-SOURCES += src/mainwindow.cpp
+SOURCES += src/charwindow.cpp
+SOURCES += src/debug.cpp
 SOURCES += src/editwindow.cpp
+SOURCES += src/global.cpp
 SOURCES += src/glyphpoints.cpp
-SOURCES += src/debug.cpp
+SOURCES += src/mainwindow.cpp
+SOURCES += src/painter.cpp
 SOURCES += src/toolwindow.cpp
-SOURCES += src/charwindow.cpp
+SOURCES += src/ttedit.cpp
 SOURCES += src/vector.cpp
-SOURCES += src/graphicprimitives.cpp
 
 RESOURCES += ttedit.qrc
 
index 5607bf91eade6720d711b71a8e16e872502b07ef..9fcad599cc749ac4ec8d26d8a6fbe5ebfc93d6df 100644 (file)
@@ -2,6 +2,7 @@
 <qresource>
        <file>res/cursor-select.png</file>
        <file>res/cursor-select-poly.png</file>
+       <file>res/cursor-select-multi.png</file>
        <file>res/cursor-scroll.png</file>
        <file>res/cursor-zoom.png</file>
        <file>res/cursor-add-point.png</file>