From: Shamus Hammons Date: Fri, 29 Aug 2008 19:23:01 +0000 (+0000) Subject: Forgot new files in last commit. D'oh! X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=ttedit;a=commitdiff_plain;h=4e11c12e60477f13a26c0bbad41fbd9a2b1db5d9 Forgot new files in last commit. D'oh! --- diff --git a/src/charwindow.cpp b/src/charwindow.cpp new file mode 100755 index 0000000..00adcd8 --- /dev/null +++ b/src/charwindow.cpp @@ -0,0 +1,56 @@ +// +// TTEDIT.CPP - The TrueType Editor +// by James L. Hammons +// (C) 2004 Underground Software +// +// JLH = James L. Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 08/28/2008 Created this file +// + +// FIXED: +// +// STILL TO BE DONE: +// +// - Fix problem with owned window causing main window refresh problems +// (ironically enough, it doesn't seem to be a problem anymore...) +// + +#include "charwindow.h" + + +BEGIN_EVENT_TABLE(CharWindow, wxMiniFrame) + EVT_PAINT(CharWindow::OnPaint) +// EVT_MOUSE_EVENTS(CharWindow::OnMouseEvent) +END_EVENT_TABLE() + +CharWindow::CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, + const wxSize &size, long style): wxMiniFrame(parent, -1, title, pos, size, style) +{ + Show(false); +} + +CharWindow::~CharWindow() +{ +} + +void CharWindow::OnPaint(wxPaintEvent &e) +{ + wxPaintDC dc(this); +//doesnothing dc.SetBackground(*wxWHITE_BRUSH); + +// wxMemoryDC memDC; +// memDC.SelectObject(*bmp); +// dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY); + +// if (prevTool != -1) +// { +// //need ul corner of bitmap, ul corner of dest, width/height +// wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2)); +// dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT); +// } + +// memDC.SelectObject(wxNullBitmap); +} diff --git a/src/charwindow.h b/src/charwindow.h new file mode 100755 index 0000000..19fefb2 --- /dev/null +++ b/src/charwindow.h @@ -0,0 +1,33 @@ +// +// CHARWINDOW.H: Header file +// +// by James L. Hammons +// (C) 2008 Underground Software +// + +#ifndef __CHARWINDOW_H__ +#define __CHARWINDOW_H__ + +#include // So that whoever uses this can without having + // to pull in a bunch of references manually +#include + +class CharWindow: public wxMiniFrame +{ + private: + protected: + public: + wxBitmap * bmp; + + // Constructor and destructor +// CharWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0); + CharWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style); + ~CharWindow(void); + + void OnPaint(wxPaintEvent &e); +// void OnMouseEvent(wxMouseEvent &e); + + DECLARE_EVENT_TABLE() +}; + +#endif // __CHARWINDOW_H__ diff --git a/src/editwindow.cpp b/src/editwindow.cpp new file mode 100755 index 0000000..63e8b3f --- /dev/null +++ b/src/editwindow.cpp @@ -0,0 +1,1654 @@ +// +// TTEDIT.CPP - The TrueType Editor +// by James L. Hammons +// (C) 2004 Underground Software +// +// JLH = James L. Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 08/28/2008 Created this file +// + +// FIXED: +// +// STILL TO BE DONE: +// +// - Fix bug in Glyphpoints when dragging on an empty canvas or loading a font +// - Fix scrolling, zooming, settings (ini) +// + +// Uncomment this for debugging... +#define DEBUG +#define DEBUGFOO // Various tool debugging... +#define DEBUGTP // Toolpalette debugging... + +#include "editwindow.h" +#include "bezier.h" +#include "toolwindow.h" +#include "debug.h" +#include "vector.h" + + +BEGIN_EVENT_TABLE(TTEditWindow, wxWindow) + EVT_PAINT(TTEditWindow::OnPaint) + EVT_MOUSE_EVENTS(TTEditWindow::OnMouseEvent) +END_EVENT_TABLE() + +TTEditWindow::TTEditWindow(wxFrame * parent, const wxPoint &pos, const wxSize &size, long style): + wxWindow(parent, -1, pos, size, style | wxFULL_REPAINT_ON_RESIZE), + app(wxGetApp()), scale(1.0), offsetX(-10), offsetY(-10), tool(TOOLSelect), + ptHighlight(-1), oldPtHighlight(-1), ptNextHighlight(-1), oldPtNextHighlight(-1), + polyFirstPoint(true), bmp(NULL) +{ + SetCursor(*(app.cur[tool])); + SetBackgroundColour(wxColour(0xFF, 0xFF, 0xFF)); + + wxString s; + s.Printf(_("Zoom: %.2f%%"), scale * 100.0); + parent->SetStatusText(s, 1); +} + +TTEditWindow::~TTEditWindow(void) +{ + if (bmp) + delete bmp; +} + +void TTEditWindow::OnPaint(wxPaintEvent &e) +{ + wxPaintDC dc(this); +//Doesn't do crap! +//dc.SetBackground(*wxWHITE_BRUSH); + +// Due to the screwiness of wxWidgets coord system, the origin is ALWAYS +// the upper left corner--regardless of axis orientation, etc... + wxCoord width, height; + dc.GetSize(&width, &height); + + dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); + dc.SetAxisOrientation(true, true); + +// Scrolling can be done by using OffsetViewportOrgEx +// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform) +// you'd use: % = ViewportExt / WindowExt +// But it makes the window look like crap: fuggetuboutit. +// Instead, we have to scale EVERYTHING by hand. Crap! +// It's not *that* bad, but not as convenient either... + + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0xFF), 1, wxDOT))); +// dc.DrawLine(0, 0, 10, 10); + + // Draw coordinate axes + + dc.CrossHair(0, 0); + + // Draw points + + for(int i=0; iFindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID))); +// SelectObject(hdc, hRedPen1); + + if (pts.GetOnCurve(i)) + { + DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7); + DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9); + } + else + { + DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7); + DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9); + } + } + else if ((i == ptHighlight || i == ptNextHighlight) && tool == TOOLAddPt) + { + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0xAF, 0x00), 1, wxSOLID))); +// SelectObject(hdc, hGreenPen1); + + if (pts.GetOnCurve(i)) + { + DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 7); + DrawSquareDotN(dc, pts.GetX(i), pts.GetY(i), 9); + } + else + { + DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 7); + DrawRoundDotN(dc, pts.GetX(i), pts.GetY(i), 9); + } + } + else + { + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); +// SelectObject(hdc, hBlackPen1); + + if (pts.GetOnCurve(i)) + DrawSquareDot(dc, pts.GetX(i), pts.GetY(i)); + else + DrawRoundDot(dc, pts.GetX(i), pts.GetY(i)); + } + + if (tool == TOOLDelPt && i == ptHighlight) + { + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0xFF, 0x00, 0x00), 1, wxSOLID))); +// SelectObject(hdc, hRedPen1); +// MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5, NULL); +// LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) + 5); +// LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) - 5);//Lameness! +// MoveToEx(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5, NULL); +// LineTo(hdc, pts.GetX(i) + 5, pts.GetY(i) - 5); +// LineTo(hdc, pts.GetX(i) - 5, pts.GetY(i) + 5);//More lameness!! + dc.DrawLine(pts.GetX(i) - 5, pts.GetY(i) - 5, pts.GetX(i) + 5, pts.GetY(i) + 5); + dc.DrawLine(pts.GetX(i) + 5, pts.GetY(i) - 5, pts.GetX(i) - 5, pts.GetY(i) + 5); + } + } + +// SelectObject(hdc, hBlackPen1); + dc.SetPen(*(wxThePenList->FindOrCreatePen(wxColour(0x00, 0x00, 0x00), 1, wxSOLID))); + + // Draw curve formed by points + + for(int poly=0; poly 2) + { + // Initial move... + // If it's not on curve, then move to it, otherwise move to last point... + + wxCoord x, y; + + if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1)) + x = (wxCoord)pts.GetX(poly, pts.GetNumPoints(poly) - 1), y = (wxCoord)pts.GetY(poly, pts.GetNumPoints(poly) - 1); + else + x = (wxCoord)pts.GetX(poly, 0), y = (wxCoord)pts.GetY(poly, 0); + + for(int i=0; iMove(pt); + app.toolPalette->Show(true); + SetCursor(*wxSTANDARD_CURSOR); + app.toolPalette->SetCursor(*wxSTANDARD_CURSOR); + app.toolPalette->prevTool = TOOLSelect; + app.toolPalette->Refresh(false); + CaptureMouse(); + } + else if (e.RightUp()) + { + ToolType newTool = app.toolPalette->FindSelectedTool();//, oldTool = tool; + + // We only change the tool if a new one was actually selected. Otherwise, we do nothing. + if (newTool != TOOLNone) + { + tool = newTool; + + if (tool == TOOLScroll || tool == TOOLZoom || tool == TOOLAddPoly + || tool == TOOLDelPoly) + ptHighlight = -1; + + if (tool == TOOLAddPoly) + polyFirstPoint = true; + } + + ReleaseMouse(); + app.toolPalette->Show(false); + SetCursor(*(app.cur[tool])); + } + else if (e.LeftDown()) + { + if (tool == TOOLScroll || tool == TOOLZoom) + CaptureMouse(); // Make sure we capture the mouse when in scroll/zoom mode + else if (tool == TOOLAddPt) // "Add Point" tool + { + if (pts.GetNumPoints() > 0) + { + wxPoint pt = GetAdjustedMousePosition(e); + pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true)); + ptHighlight = ptNextHighlight; + Refresh(); + } + } + else if (tool == TOOLAddPoly) // "Add Poly" tool + { +#ifdef DEBUGFOO +WriteLogMsg("Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints()); +#endif + if (polyFirstPoint) + { + polyFirstPoint = false; + pts.AddNewPolyAtEnd(); + } + + wxPoint pt = GetAdjustedMousePosition(e); + // Append a point to the end of the structure + pts += IPoint(pt.x, pt.y, (e.ShiftDown() | e.ControlDown() ? false : true)); + ptHighlight = pts.GetNumPoints() - 1; + Refresh(); +#ifdef DEBUGFOO +WriteLogMsg(" --> [# polys: %u, # points: %u]\n", pts.GetNumPolys(), pts.GetNumPoints()); +#endif + } + else if (tool == TOOLSelect || tool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) + { + pt = GetAdjustedClientPosition(pts.GetX(ptHighlight), pts.GetY(ptHighlight)); + WarpPointer(pt.x, pt.y); + + if (e.ShiftDown() | e.ControlDown()) + pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight)); + } + } + else if (tool == TOOLDelPt) + { + if (pts.GetNumPoints() > 0) +//Or could use: +// if (ptHighlight != -1) + { +//This assumes that WM_MOUSEMOVE happens before this! +//The above commented out line should take care of this contingency... !!! FIX !!! + pts.DeletePoint(ptHighlight); + Refresh(); + } + } + } + else if (e.LeftUp()) + { +// mouseDown = false; + + if (tool == TOOLScroll || tool == TOOLZoom) + ReleaseMouse(); + } + else if (e.Dragging()) + { + if (e.RightIsDown()) + { + ToolType newTool = app.toolPalette->FindSelectedTool(); + + if (newTool != app.toolPalette->prevTool) + { + app.toolPalette->prevTool = newTool; + app.toolPalette->Refresh(false); + } + + return; + } + + // 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; + +// if (e.LeftIsDown()) +// { + if (tool == TOOLScroll) + { + // 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 if (tool == TOOLAddPt || tool == TOOLAddPoly || tool == TOOLSelect) + { + if (tool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. + { +//temporary, for testing. BTW, Select drag bug is here...! +#if 0 + wxPoint pt2 = GetAdjustedMousePosition(e); + pts.SetXY(ptHighlight, pt2.x, pt2.y); + Refresh(); +#endif + } + } + else if (tool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) + { + wxPoint pt2 = GetAdjustedMousePosition(e); + // 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)); + Refresh(); + } + } +// } + + ptPrevious = pt; + } + else if (e.Moving()) + { +// else // Moving, not dragging... +// { + if (tool == TOOLSelect || tool == TOOLDelPt || tool == TOOLAddPt + || tool == TOOLPolySelect)// || tool == TOOLAddPoly) + { + wxPoint pt2 = GetAdjustedMousePosition(e); + double closest = 1.0e+99; + + for(int i=0; i 1 && tool == TOOLAddPt) + { + double smallest = 1.0e+99; + + for(int i=0; i 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(); + else // distance = ?Det?(ls, v1) / |ls| + dist = fabs((ls.x * v1.y - v1.x * ls.y) / ls.length()); + +//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: +// +//sx sy 1 +//ex ey 1 +//px py 1 +// +//(???) By translating the start point to the origin, this can be rewritten as: +//By subtracting row 1 from all rows, you get the following: +// +//0 0 0 +//(ex - sx) (ey - sy) 0 +//(px - sx) (py - sy) 0 +// +//which greatly simplifies the calculation of the determinant. + + if (dist < smallest) + smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i; + } + + if (ptNextHighlight != oldPtNextHighlight) + { + oldPtNextHighlight = ptNextHighlight; + Refresh(); + } + } + } +// } + + ptPrevious = e.GetPosition(); + } +} + +wxPoint TTEditWindow::GetAdjustedMousePosition(wxMouseEvent &e) +{ + wxCoord width, height; + wxClientDC dc(this); + + dc.GetSize(&width, &height); + dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); + dc.SetAxisOrientation(true, true); + +#if 0 +wxStatusBar * sb = ((wxFrame *)GetParent())->GetStatusBar(); +wxString s; +s.Printf("Logical mouse pos: %d, %d (%d, %d)", pt.x, pt.y, width, height); +sb->SetStatusText(s); +#endif + + return e.GetLogicalPosition(dc); +} + +wxPoint TTEditWindow::GetAdjustedClientPosition(wxCoord x, wxCoord y) +{ + wxCoord width, height; + wxClientDC dc(this); + + dc.GetSize(&width, &height); + dc.SetDeviceOrigin(-offsetX, height - (-offsetY)); + dc.SetAxisOrientation(true, true); + + return wxPoint(dc.LogicalToDeviceX(x), dc.LogicalToDeviceY(y)); +} + +// +// Draw a round dot (5x5, centered on [x, y]) +// +void TTEditWindow::DrawRoundDot(wxDC &dc, int32 x, int32 y) +{ + wxPoint pt[8]; + + pt[0].x = x - 1, pt[0].y = y - 2; + pt[1].x = x + 1, pt[1].y = y - 2; + pt[2].x = x + 2, pt[2].y = y - 1; + pt[3].x = x + 2, pt[3].y = y + 1; + pt[4].x = x + 1, pt[4].y = y + 2; + pt[5].x = x - 1, pt[5].y = y + 2; + pt[6].x = x - 2, pt[6].y = y + 1; + pt[7].x = x - 2, pt[7].y = y - 1; + + dc.DrawPolygon(8, pt); +} + +// +// Draw a sqaure dot (5x5, centered on [x, y]) +// +void TTEditWindow::DrawSquareDot(wxDC &dc, int32 x, int32 y) +{ + wxPoint pt[4]; + + pt[0].x = x - 2, pt[0].y = y - 2; + pt[1].x = x + 2, pt[1].y = y - 2; + pt[2].x = x + 2, pt[2].y = y + 2; + pt[3].x = x - 2, pt[3].y = y + 2; + + dc.DrawPolygon(4, pt); +} + +// +// Draw a sqaure dot (nxn, centered on [x, y]) +// +void TTEditWindow::DrawSquareDotN(wxDC &dc, int32 x, int32 y, uint32 n) +{ + wxPoint pt[4]; + uint32 offset = (n - 1) / 2; + + pt[0].x = x - offset, pt[0].y = y - offset; + pt[1].x = x + offset, pt[1].y = y - offset; + pt[2].x = x + offset, pt[2].y = y + offset; + pt[3].x = x - offset, pt[3].y = y + offset; + + dc.DrawPolygon(4, pt); +} + +// +// Draw a round dot (nxn, centered on [x, y]) +// +void TTEditWindow::DrawRoundDotN(wxDC &dc, int32 x, int32 y, uint32 n) +{ + dc.DrawCircle(x, y, (n / 2) + 1); +} + + +#if 0 + +!!! OLD STUFF !!! + + +LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) +{ + RECT rc1, rc2; + HDC hdc; + POINT pt, ptOffset; + SIZE sz; + PAINTSTRUCT ps; + + switch (msgID) + { + case WM_CREATE: + + MiscCenterWnd(hWnd, GetDesktopWindow()); + InitCommonControls(); + hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, statusBarTxt, hWnd, ID_STATUSBAR); + + if (!hStatusBar) + return -1; + +// clean this crap up! +// well, the only crappy thing here is using a POINT as an int array, but otherwise, this is OK + wsprintf(strBuf, zoom, 1000); + hdc = GetDC(hWnd); + GetTextExtentPoint32(hdc, strBuf, lstrlen(strBuf), &sz); + ReleaseDC(hWnd, hdc); + zoomWndWidth = sz.cx; + wsprintf(strBuf, zoom, 100); + + GetClientRect(hWnd, &rc1); + pt.x = rc1.right - zoomWndWidth, pt.y = -1; + SendMessage(hStatusBar, SB_SETPARTS, 2, (LPARAM)&pt); + SendMessage(hStatusBar, SB_SETTEXT, (0 | SBT_NOBORDERS), (LPARAM)statusBarTxt); + SendMessage(hStatusBar, SB_SETTEXT, 1, (LPARAM)strBuf); + + hToolBar = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, + IDR_TOOLBAR1, 3, hInst, IDB_TOOLBAR1, tbButtons, 4, 16, 16, 16, 16, sizeof(TBBUTTON)); + + if (!hToolBar) + return -1; + + CreateNewDoc(); + +// The following can only be done because we use a private DC (using "CS_OWNDC") +// (Is that true???) +// Set the mapping to draw the character so it fits in the viewport... + hdc = GetDC(hWnd); + GetClientRect(hWnd, &rc1); + GetClientRect(hStatusBar, &rc2); + rc1.bottom -= rc2.bottom; + SetMapMode(hdc, MM_ISOTROPIC); + SetWindowExtEx(hdc, rc1.right, rc1.bottom, NULL); + SetViewportExtEx(hdc, rc1.right, -rc1.bottom, NULL); + SetViewportOrgEx(hdc, 0, rc1.bottom, NULL); + ReleaseDC(hWnd, hdc); + break; + + case WM_CLOSE: + + if (SaveChanges()) + { + wpM.length = wpC.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hMainWnd, &wpM); + GetWindowPlacement(hCharWnd, &wpC); + + if (!IsWindowVisible(hCharWnd)) // Needed because Windows lies about visibility + wpC.showCmd = SW_HIDE; + + hdc = GetDC(hWnd); + GetViewportOrgEx(hdc, &ptVPM); + ReleaseDC(hWnd, hdc); + + DestroyWindow(hWnd); + } + + break; + + case WM_DESTROY: + + PostQuitMessage(0); + break; + + case WM_NCLBUTTONDOWN: + + if (wParam == HTCAPTION) + { + NCMouseDown = true; + GetWindowRect(hMainWnd, &rc1); + GetWindowRect(hCharWnd, &rc2); + ptWinOffset.x = rc2.left - rc1.left; + ptWinOffset.y = rc2.top - rc1.top; + } + + // Let Windows do its thing with this msg, or weird things will happen... + + DefWindowProc(hWnd, msgID, wParam, lParam); + NCMouseDown = false; + break; + + case WM_WINDOWPOSCHANGING: + + if (NCMouseDown) + { + WINDOWPOS * wp = (WINDOWPOS *)lParam; + + if (wp->hwnd == hMainWnd && !(wp->flags & SWP_NOMOVE)) + SetWindowPos(hCharWnd, 0, wp->x + ptWinOffset.x, wp->y + ptWinOffset.y, + 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); + } + + return DefWindowProc(hWnd, msgID, wParam, lParam); // Seems this is needed... Bleah! + + case WM_PAINT: + { + hdc = BeginPaint(hWnd, &ps); + +// Scrolling can be done by using OffsetViewportOrgEx +// Scaling can be done by adjusting SetWindowExtEx (it's denominator of txform) +// you'd use: % = ViewportExt / WindowExt +// But it makes the window look like crap: fuggetuboutit. +// Instead, we have to scale EVERYTHING by hand. Crap! + + // Apparently, you *must* save the individual object types (pen, brush, etc.) + + HGDIOBJ oldPen = SelectObject(hdc, hBluePen1), + oldBrush = SelectObject(hdc, hNullBrush); + + // Draw coordinate axes + + MoveToEx(hdc, 0, -32000, NULL); + LineTo(hdc, 0, 32000); + MoveToEx(hdc, -32000, 0, NULL); + LineTo(hdc, 32000, 0); + + // 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... + + if (pts.GetOnCurve(poly, pts.GetNumPoints(poly) - 1)) + MoveToEx(hdc, pts.GetX(poly, pts.GetNumPoints(poly) - 1), pts.GetY(poly, pts.GetNumPoints(poly) - 1), NULL); + else + MoveToEx(hdc, pts.GetX(poly, 0), pts.GetY(poly, 0), NULL); + + for(int i=0; i 0) + { +//Do we really need to put a cap on this??? +//Maybe... +// if (pts.GetNumPoints() < 16) +// { + pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; + hdc = GetDC(hWnd); + DPtoLP(hdc, &pt, 1); + pts.InsertPoint(pts.GetNext(ptHighlight), pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true)); + ptHighlight = ptNextHighlight; + ReleaseDC(hWnd, hdc); + InvalidateRect(hWnd, NULL, TRUE); +// } + } + } + else if (currentTool == TOOLAddPoly) // "Add Poly" tool + { +#ifdef DEBUGFOO +wsprintf(strBuf, "Adding point... # polys: %u, # points: %u", pts.GetNumPolys(), pts.GetNumPoints()); +WriteLogMsg(strBuf); +#endif + if (polyFirstPoint) + { + polyFirstPoint = false; + pts.AddNewPolyAtEnd(); + } + +//Do we really need to put a cap on this??? +//Maybe... +// if (pts.GetNumPoints() < 16) +// { + pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; + hdc = GetDC(hWnd); + DPtoLP(hdc, &pt, 1); + ReleaseDC(hWnd, hdc); + // Append a point to the end of the structure + pts += IPoint(pt.x, pt.y, (wParam & (MK_SHIFT | MK_CONTROL) ? false : true)); +ptHighlight = pts.GetNumPoints() - 1; + InvalidateRect(hWnd, NULL, TRUE); +// } +#ifdef DEBUGFOO +wsprintf(strBuf, " --> [# polys: %u, # points: %u]\xD\xA", pts.GetNumPolys(), pts.GetNumPoints()); +WriteLogMsg(strBuf); +#endif + } + else if (currentTool == TOOLSelect || currentTool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) + { + pt.x = pts.GetX(ptHighlight), pt.y = pts.GetY(ptHighlight); + hdc = GetDC(hWnd); + LPtoDP(hdc, &pt, 1); + ClientToScreen(hWnd, &pt); + SetCursorPos(pt.x, pt.y); + ReleaseDC(hWnd, hdc); + + if (wParam & (MK_SHIFT | MK_CONTROL)) + pts.SetOnCurve(ptHighlight, !pts.GetOnCurve(ptHighlight)); + } + } + else if (currentTool == TOOLDelPt) + { + if (pts.GetNumPoints() > 0) +//Or could use: +// if (ptHighlight != -1) + { +//This assumes that WM_MOUSEMOVE happens before this! +//The above commented out line should take care of this contingency... !!! FIX !!! + pts.DeletePoint(ptHighlight); + InvalidateRect(hWnd, NULL, TRUE); + } + } + + break; + + case WM_LBUTTONUP: + + mouseDown = false; + + if (currentTool == TOOLScroll || currentTool == TOOLZoom) + ReleaseCapture(); + + break; + + case WM_MOUSEMOVE: + + SetCursor(hCur[currentTool]); + + // Extract current point from lParam/calc offset from previous point + + pt.x = lParam & 0xFFFF, pt.y = lParam >> 16; + ptOffset.x = pt.x - ptPrevious.x, + ptOffset.y = pt.y - ptPrevious.y; + + if (mouseDown) + { + if (currentTool == TOOLScroll) + { + // NOTE: OffsetViewportOrg operates in DEVICE UNITS... + + 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! + + InvalidateRect(hWnd, NULL, TRUE); +// SendMessage(hWnd, WM_PAINT, NULL, NULL); + } + else if (currentTool == TOOLAddPt || currentTool == TOOLAddPoly || currentTool == TOOLSelect) + { + if (currentTool != TOOLAddPt || pts.GetNumPoints() > 0)//yecch. + { + POINT pt2; + pt2.x = pt.x, pt2.y = pt.y; + // Should also set onCurve here as well, depending on keystate +//Or should we? + hdc = GetDC(hWnd); + DPtoLP(hdc, &pt2, 1); + pts.SetXY(ptHighlight, pt2.x, pt2.y); + ReleaseDC(hWnd, hdc); + InvalidateRect(hWnd, NULL, TRUE); + } + } + else if (currentTool == TOOLPolySelect) + { + if (pts.GetNumPoints() > 0) + { + POINT pt2; + pt2.x = pt.x, pt2.y = pt.y; + // Should also set onCurve here as well, depending on keystate +//Or should we? + hdc = GetDC(hWnd); + DPtoLP(hdc, &pt2, 1); + pts.OffsetPoly(pts.GetPoly(ptHighlight), pt2.x - pts.GetX(ptHighlight), pt2.y - pts.GetY(ptHighlight)); + ReleaseDC(hWnd, hdc); + InvalidateRect(hWnd, NULL, TRUE); + } + } + } + else + { + if (currentTool == TOOLSelect || currentTool == TOOLDelPt || currentTool == TOOLAddPt + || currentTool == TOOLPolySelect)// || currentTool == TOOLAddPoly) + { + POINT pt2; + pt2.x = pt.x, pt2.y = pt.y; + hdc = GetDC(hWnd); + DPtoLP(hdc, &pt2, 1); + ReleaseDC(hWnd, hdc); + + double closest = 1.0e+99; + + for(int i=0; i 1 && currentTool == TOOLAddPt) + { + double smallest = 1.0e+99; + + for(int i=0; i 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(); + else // distance = ?Det?(ls, v1) / |ls| + dist = abs((ls.x * v1.y - v1.x * ls.y) / ls.length()); + +//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: +// +//sx sy 1 +//ex ey 1 +//px py 1 +// +//(???) By translating the start point to the origin, this can be rewritten as: +//By subtracting row 1 from all rows, you get the following: +// +//0 0 0 +//(ex - sx) (ey - sy) 0 +//(px - sx) (py - sy) 0 +// +//which greatly simplifies the calculation of the determinant. + + if (dist < smallest) + smallest = dist, ptNextHighlight = pts.GetNext(i), ptHighlight = i; + } + + if (ptNextHighlight != oldPtNextHighlight) + { + oldPtNextHighlight = ptNextHighlight; + InvalidateRect(hWnd, NULL, TRUE); + } + } + } + } + + ptPrevious.x = pt.x, ptPrevious.y = pt.y; + + break; + + case WM_NOTIFY: + + if (((NMHDR *)lParam)->code == TTN_NEEDTEXT) + { + LoadString(hInst, ((TOOLTIPTEXT *)lParam)->hdr.idFrom + 0x80, toolTipTxt, 16); + ((TOOLTIPTEXT *)lParam)->lpszText = toolTipTxt; + } + + break; + + case WM_MENUSELECT: + { + statusBarTxt[0] = 0; // Clear status bar text + uint16 flags = wParam >> 16; // Extract flags + + if (!(flags & MFT_SEPARATOR)) + { + uint16 id = wParam & 0xFFFF; + + if (flags & MF_POPUP) + { + if (flags & MF_SYSMENU) + id = IDS_SYSMENU; + else + id = IDM_FILEMENU + wParam; + } + + LoadString(hInst, id, statusBarTxt, 64); + } + + SendMessage(hStatusBar, SB_SETTEXT, 0 + SBT_NOBORDERS, (LPARAM)statusBarTxt); + break; + } + case WM_COMMAND: + { + uint16 cmd = wParam & 0xFFFF; + + if (cmd == IDM_NEW) + { +// call CmdIDM_NEW + } + else if (cmd == IDM_OPEN) + { +// call SaveChanges +// .IF (eax) +// movmov ofn.hwndOwner, eax, hMainWnd +// mov ofn.Flags, OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST +// invoke GetOpenFileName, ADDR ofn +// .IF (eax) +//////// +//jmp @F +//szDMsg1a BYTE "Could not open the file (GetOpenFileName)...", 0 +//szDMsg1b BYTE "Open error!", 0 +//szDMsg1c BYTE "About to attempt to open file...", 0 +//@@: +////invoke MessageBox, hWnd, ADDR szDMsg1a, ADDR szDMsg1b, MB_ICONERROR or MB_OK +//invoke MessageBox, hMainWnd, ADDR szDMsg1c, ADDR szFile, MB_ICONERROR or MB_OK +// invoke LoadTTF, ADDR szFile +// +////// +// // <<< FILE OPEN CODE HERE >>> +// or fFileStatus, NAMEDbit +// and fFileStatus, NOT CHANGEDbit +// call NewWindowName +// mov eax, TRUE // return TRUE +// jmp Return +// //�������������������������������������� +//OpenError: invoke GetLastError +// // <<< FILE OPEN ERROR CODE HERE >>> +// .ENDIF +// zero eax // return FALSE +// .ENDIF + } + else if (cmd == IDM_SAVEAS) + { +// and fFileStatus, NOT NAMEDbit +// call CmdIDM_SAVE + } + else if (cmd == IDM_SAVE) + { +// call CmdIDM_SAVE + } + else if (cmd == IDM_ABOUT) + DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_ABOUT), hMainWnd, AboutProc, NULL); + else if (cmd == IDM_EXIT) + SendMessage(hWnd, WM_CLOSE, 0, 0); + else if (cmd == ID_TBCHARWIN) + { + ShowWindow(hCharWnd, (IsWindowVisible(hCharWnd) ? SW_HIDE : SW_SHOWNOACTIVATE)); + +#ifdef DEBUGFOO +wpC.length = sizeof(WINDOWPLACEMENT); +GetWindowPlacement(hCharWnd, &wpC); +wsprintf(strBuf, "Char window showCmd = %08X...\n", wpC.showCmd); +WriteLogMsg(strBuf); +#endif + } + else + return DefWindowProc(hWnd, msgID, wParam, lParam); + + break; + } + default: + return DefWindowProc(hWnd, msgID, wParam, lParam); + } + + return 0; +} + +// +// Initialize TTF data +// +void CreateNewDoc(void) +{ +} + +// +// Save changes to document before quitting +// +bool SaveChanges(void) +{ + return true; +} + + + +// +// ABOUT Dialog WndProc +// +BOOL CALLBACK AboutProc(HWND hDlg, UINT msgID, WPARAM wParam, LPARAM lParam) +{ + switch (msgID) + { + case WM_INITDIALOG: + + MiscCenterWnd(hDlg, hMainWnd); + break; + + case WM_COMMAND: + + if (wParam == IDOK || wParam == IDCANCEL) + EndDialog(hDlg, TRUE); + + break; + + default: + return FALSE; + } + + return TRUE; +} + +// +// Character Window WndProc +// +WndProcCW PROC STDCALL, hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM + + mov eax, uMsg // pickup our message + .IF (eax == WM_PAINT) + mov eax, 0 // Non-sense... (placeholder!) +// Scan conversion etc. goes here... + .ELSEIF (eax == WM_LBUTTONDOWN) + invoke SetCapture, hCharWnd + .ELSEIF (eax == WM_LBUTTONUP) + invoke ReleaseCapture + invoke SetFocus, hMainWnd // Make sure the main wnd keeps focus! + .ELSEIF (eax == WM_NCLBUTTONDOWN) + invoke DefWindowProc, hWnd, uMsg, wParam, lParam // Let it do its thing + invoke SetFocus, hMainWnd // Make sure the main wnd keeps focus! + .ELSE +DefProc: invoke DefWindowProc, hWnd, uMsg, wParam, lParam + .ENDIF + ret + +WndProcCW ENDP + +// +// Character Window WndProc +// +LRESULT CALLBACK WndProcCW(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) +{ + switch (msgID) + { + default: + return DefWindowProc(hWnd, msgID, wParam, lParam); + } + + return 0; +} + + +// Function prototypes + +int32 FindSelectedTool(void); + +// +// Tool Palette WndProc +// +LRESULT CALLBACK WndProcTP(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + HDC hdc; + POINT pt; + static uint32 prevTool = -1; + + switch (msgID) + { + case WM_PAINT: + { + hdc = BeginPaint(hWnd, &ps); + HDC newDC = CreateCompatibleDC(NULL); + SelectObject(newDC, hBMToolPal1); + BitBlt(hdc, 0, 0, sizeTPBM.x, sizeTPBM.y, newDC, 0, 0, SRCCOPY); + DeleteDC(newDC); + +// This is crappy. Find some way to tighten this up! + int32 tool = FindSelectedTool(); + + if (tool != -1) + { + newDC = CreateCompatibleDC(NULL); + SelectObject(newDC, hBMToolPal1); + //need ul corner of bitmap, ul corner of dest, width/height + pt.x = sizeStamp.x * (tool & 0x03), pt.y = sizeStamp.y * (tool >> 2); + BitBlt(hdc, pt.x, pt.y, sizeStamp.x, sizeStamp.y, newDC, pt.x, pt.y, NOTSRCCOPY); + DeleteDC(newDC); + } + + EndPaint(hWnd, &ps); + break; + } + case WM_MOUSEMOVE: + { + int32 tool = FindSelectedTool(); + + if (tool != prevTool) + { + prevTool = tool; + InvalidateRect(hWnd, NULL, FALSE); + } + + break; + } + case WM_RBUTTONUP: + { + int32 tool = FindSelectedTool(), oldTool = currentTool; + + if (tool != -1) + currentTool = tool; + + if (currentTool != TOOLSelect && currentTool != TOOLDelPt && currentTool != TOOLAddPt + && currentTool != TOOLPolySelect) + ptHighlight = -1; + + if (currentTool != oldTool) + InvalidateRect(hMainWnd, NULL, TRUE); + + if (currentTool == TOOLAddPoly) +#ifdef DEBUGFOO +{ +#endif + polyFirstPoint = true; +#ifdef DEBUGFOO +wsprintf(strBuf, "--> Selected poly tool, polyFirstPoint is %s\n", polyFirstPoint ? "true" : "false"); +WriteLogMsg(strBuf); +} +#endif + + ReleaseCapture(); + ShowWindow(hToolPalWnd, SW_HIDE); + SetFocus(hMainWnd); // Make sure the main wnd keeps focus! + + break; + } + default: + return DefWindowProc(hWnd, msgID, wParam, lParam); + } + + return 0; +} + +// +// Find which tool we're pointing at +// Use: xcoord = mouse.x / (bmsize.x/4), ycoord = mouse.y / (bmsize.y/2) +// +int32 FindSelectedTool(void) +{ + POINT pt; + + GetCursorPos(&pt); + ScreenToClient(hToolPalWnd, &pt); + + uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y, tool = -1; + + if (x < 4 && y < 2) +// { + tool = (y * 4) + x; + +// if (tool == 7) +// tool = -1; // 7 has no tool... +// } + + return tool; +} + + +// +// Misc center window +// +void MiscCenterWnd(HWND hChild, HWND hParent) +{ + RECT parent, child; + + if (!GetWindowRect(hParent, &parent) || !GetWindowRect(hChild, &child)) + return; + + int32 x = parent.left + (((parent.right - parent.left) - (child.right - child.left)) / 2), + y = parent.top + (((parent.bottom - parent.top) - (child.bottom - child.top)) / 2); + + if (x < 0) + x = 0; + else if (x > GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left)) + x = GetSystemMetrics(SM_CXFULLSCREEN) - (child.right - child.left); + + if (y < 0) + y = 0; + else if (y > GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top)) + y = GetSystemMetrics(SM_CYFULLSCREEN) - (child.bottom - child.top); + + SetWindowPos(hChild, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + +// +// Allow only one instance +// +bool OnlyOneInstance(void) +{ + HWND window = FindWindow(className, NULL); + + if (window == NULL) + return true; + + ShowWindow(window, SW_SHOWNORMAL); + SetWindowPos(window, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); + + return false; +} + +// +// Load/Allocate all resources +// +bool LoadResources(void) +{ + hCur[0] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR1)); + hCur[1] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR2)); + hCur[2] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR3)); + hCur[3] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR4)); + hCur[4] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR5)); + hCur[5] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR6)); + hCur[6] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR7)); + hCur[7] = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR8)); + + BITMAP bm; + + hBMToolPal1 = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_TOOLPAL1)); + GetObject(hBMToolPal1, sizeof(bm), &bm); + + // Set up sizes + + sizeTPBM.x = bm.bmWidth, sizeTPBM.y = bm.bmHeight; + sizeStamp.x = bm.bmWidth / 4, sizeStamp.y = bm.bmHeight / 2; + + hBluePen1 = CreatePen(PS_DOT, 1, 0x00FF0000); + hRedPen1 = CreatePen(PS_SOLID, 1, 0x000000FF); + hGreenPen1 = CreatePen(PS_SOLID, 1, 0x0000AF00); + hBlackPen1 = CreatePen(PS_SOLID, 1, 0x00000000); + + LOGBRUSH lb = { BS_NULL, 0, 0 }; + + hNullBrush = CreateBrushIndirect(&lb); + + return true; +} + +// +// Deallocate all resources +// +void DeallocateResources(void) +{ + DeleteObject(hBMToolPal1); + DeleteObject(hBluePen1); + DeleteObject(hRedPen1); + DeleteObject(hGreenPen1); + DeleteObject(hBlackPen1); + DeleteObject(hNullBrush); +} + +// +// Save all application specific data, so we can pick up where we last left off... +// +void SaveAppState(void) +{ + SetINIInt("Main", "flags", wpM.flags); + SetINIInt("Main", "showCmd", wpM.showCmd); + SetINIInt("Main", "x1", wpM.rcNormalPosition.left); + SetINIInt("Main", "y1", wpM.rcNormalPosition.top); + SetINIInt("Main", "x2", wpM.rcNormalPosition.right); + SetINIInt("Main", "y2", wpM.rcNormalPosition.bottom); + + SetINIInt("Main", "vpx", ptVPM.x); + SetINIInt("Main", "vpy", ptVPM.y); + + SetINIInt("Char", "flags", wpC.flags); + SetINIInt("Char", "showCmd", wpC.showCmd); + SetINIInt("Char", "x1", wpC.rcNormalPosition.left); + SetINIInt("Char", "y1", wpC.rcNormalPosition.top); + SetINIInt("Char", "x2", wpC.rcNormalPosition.right); + SetINIInt("Char", "y2", wpC.rcNormalPosition.bottom); + + // Need to write out currently opened font, character looking at, other misc. crap +// SetINIString("Main", "currentFile", pDoc->GetPathName()); +// SetINIInt("Main", "currentChar", pDoc->character_num); +} + +// +// Restore all application specific data previously saved +// +bool RestoreAppState(void) +{ + InitINIFile(); + + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hMainWnd, &wp); + + wp.flags = GetINIInt("Main", "flags", wp.flags); + wp.showCmd = GetINIInt("Main", "showCmd", wp.showCmd); + wp.rcNormalPosition.left = GetINIInt("Main", "x1", wp.rcNormalPosition.left); + wp.rcNormalPosition.top = GetINIInt("Main", "y1", wp.rcNormalPosition.top); + wp.rcNormalPosition.right = GetINIInt("Main", "x2", wp.rcNormalPosition.right); + wp.rcNormalPosition.bottom = GetINIInt("Main", "y2", wp.rcNormalPosition.bottom); + + SetWindowPlacement(hMainWnd, &wp); + + HDC hdc; + POINT pt; + hdc = GetDC(hMainWnd); + GetViewportOrgEx(hdc, &pt); + + pt.x = GetINIInt("Main", "vpx", pt.x); + pt.y = GetINIInt("Main", "vpy", pt.y); + + SetViewportOrgEx(hdc, pt.x, pt.y, NULL); + ReleaseDC(hMainWnd, hdc); + + GetWindowPlacement(hCharWnd, &wp); + + wp.flags = GetINIInt("Char", "flags", wp.flags); + wp.showCmd = GetINIInt("Char", "showCmd", wp.showCmd); + wp.rcNormalPosition.left = GetINIInt("Char", "x1", wp.rcNormalPosition.left); + wp.rcNormalPosition.top = GetINIInt("Char", "y1", wp.rcNormalPosition.top); + wp.rcNormalPosition.right = GetINIInt("Char", "x2", wp.rcNormalPosition.right); + wp.rcNormalPosition.bottom = GetINIInt("Char", "y2", wp.rcNormalPosition.bottom); + + SetWindowPlacement(hCharWnd, &wp); + + if (wp.showCmd == SW_HIDE) + SendMessage(hToolBar, TB_SETSTATE, ID_TBCHARWIN, MAKELONG(TBSTATE_ENABLED, 0)); + +// CString lastFile = theApplicationObject.GetProfileString(version, "currentFile", ""); +// int lastChar = theApplicationObject.GetProfileInt(version, "currentChar", 0); +// if (lastFile.GetLength()) +// { +// // Attempt to restore the last session by open the last file used, etc... +// if (!pDoc->m_myFont.Load(lastFile)) +// { +// // Err, make sure you can support any allegations you make below, buddy! +// AfxMessageBox("The last file opened with TTF Edit\n\rseems to have been moved or deleted."); +// } +// else +// { +// pDoc->m_myFont.SetGlyph(lastChar); // Set TTF object to last used char +// pDoc->character_num = lastChar; +// pDoc->SetPathName(lastFile); +// +// BYTE name[512]; +// pDoc->m_myFont.GetCharName(lastChar, name); +// m_wndOwned.SetWindowText((char *)name); +// } +// } + + return true; +} + +// +// Initialization +// +bool Initialization(void) +{ + WNDCLASSEX wcex; + + if (!LoadResources()) + return false; + + RtlFillMemory(&wcex, sizeof(WNDCLASSEX), 0); + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wcex.lpfnWndProc = WndProc; + wcex.hInstance = hInst; + wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON)); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDM_MENU); + wcex.lpszClassName = className; + wcex.hIconSm = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, NULL); + + if (!RegisterClassEx(&wcex)) + return false; + + hMainWnd = CreateWindowEx(NULL, className, className, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, + 0, 0, 0x1A0, 0x180, NULL, NULL, hInst, NULL); + + if (!hMainWnd) + return false; + + ShowWindow(hMainWnd, nCmdShow); + UpdateWindow(hMainWnd); + + // Character window creation + + wcex.lpfnWndProc = WndProcCW; + wcex.lpszMenuName = NULL; + wcex.lpszClassName = CNCharWin; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // Owned windows have "regular" cursors + + if (!RegisterClassEx(&wcex)) + return false; + + hCharWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW, CNCharWin, + curCharName, WS_POPUP | WS_CAPTION | WS_VISIBLE | WS_THICKFRAME, + 100, 100, 120, 120, hMainWnd, NULL, hInst, NULL); + + if (!hCharWnd) + return false; + + ShowWindow(hCharWnd, SW_SHOWNORMAL); + UpdateWindow(hCharWnd); + SetFocus(hMainWnd); // Make sure main wnd has focus! + + // Tool palette window creation + + wcex.lpfnWndProc = WndProcTP; + wcex.lpszClassName = CNToolPal; + + if (!RegisterClassEx(&wcex)) + return false; + + hToolPalWnd = CreateWindowEx(WS_EX_WINDOWEDGE, CNToolPal, NULL, WS_POPUP, + 0, 0, sizeTPBM.x, sizeTPBM.y, hMainWnd, NULL, hInst, NULL); + + if (!hToolPalWnd) + return false; + +// Note: A better way to handle this would be to have a sub that registers ALL +// classes beforehand and passes a TRUE/FALSE back depending on whether or not +// all the classes were able to be registered or not, THEN create the windows +// and controls... + + RestoreAppState(); // Restore app related stuff + + return true; +} + +#endif diff --git a/src/editwindow.h b/src/editwindow.h new file mode 100755 index 0000000..8034d7e --- /dev/null +++ b/src/editwindow.h @@ -0,0 +1,52 @@ +// +// EDITWINDOW.H: Header file +// +// by James L. Hammons +// (C) 2008 Underground Software +// + +#ifndef __EDITWINDOW_H__ +#define __EDITWINDOW_H__ + +#include // So that whoever uses this can without having + // to pull in a bunch of references manually +#include "types.h" +#include "ttedit.h" // For TTEditApp +#include "toolwindow.h" // For ToolType enum +#include "glyphpoints.h" + +class TTEditWindow: public wxWindow +{ + private: + TTEditApp & app; // Reference to the application object + double scale; // Window scaling factor + int32 offsetX, offsetY; // Window offsets + ToolType tool; // Current tool + GlyphPoints pts; // Glyph point structure + int32 ptHighlight, oldPtHighlight, ptNextHighlight, oldPtNextHighlight; + bool polyFirstPoint; + + protected: + public: + wxBitmap * bmp; + wxPoint pt, ptOffset, ptPrevious; + + // Constructor and destructor + TTEditWindow(wxFrame * parent, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0); + ~TTEditWindow(void); + + void OnPaint(wxPaintEvent &e); + void OnMouseEvent(wxMouseEvent &e); + + protected: + wxPoint GetAdjustedMousePosition(wxMouseEvent &e); + wxPoint GetAdjustedClientPosition(wxCoord x, wxCoord y); + void DrawRoundDot(wxDC &, int32, int32); + void DrawSquareDot(wxDC &, int32, int32); + void DrawRoundDotN(wxDC &, int32, int32, uint32); + void DrawSquareDotN(wxDC &, int32, int32, uint32); + + DECLARE_EVENT_TABLE() +}; + +#endif // __EDITWINDOW_H__ diff --git a/src/toolwindow.cpp b/src/toolwindow.cpp new file mode 100755 index 0000000..4532964 --- /dev/null +++ b/src/toolwindow.cpp @@ -0,0 +1,95 @@ +// +// TOOLWINDOW.CPP - Tool Palette window +// by James L. Hammons +// (C) 2008 Underground Software +// +// JLH = James L. Hammons +// +// Who When What +// --- ---------- ------------------------------------------------------------- +// JLH 08/28/2008 Created this file +// + +// FIXED: +// +// STILL TO BE DONE: +// +// + +// Uncomment this for debugging... +#define DEBUG +#define DEBUGFOO // Various tool debugging... +#define DEBUGTP // Toolpalette debugging... + +#include "toolwindow.h" +#include "types.h" + +// Pixmap resources + +#include "res/toolpal1.xpm" // Docs say this is portable... Let's see! + + +BEGIN_EVENT_TABLE(ToolWindow, wxFrame) + EVT_PAINT(ToolWindow::OnPaint) +END_EVENT_TABLE() + + +ToolWindow::ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, + const wxSize &size, long style): wxFrame(parent, -1, title, pos, size, style), + bmp(NULL), prevTool(TOOLNone) +{ + bmp = new wxBitmap(toolpal1_xpm); + + // Set up sizes + + sizeTPBM.x = bmp->GetWidth(), sizeTPBM.y = bmp->GetHeight(); + sizeStamp.x = sizeTPBM.x / 4, sizeStamp.y = sizeTPBM.y / 2; + + SetSize(0, 0, sizeTPBM.x, sizeTPBM.y); + Show(false); +} + +ToolWindow::~ToolWindow() +{ + if (bmp) + delete bmp; +} + +void ToolWindow::OnPaint(wxPaintEvent &e) +{ + wxPaintDC dc(this); + + wxMemoryDC memDC; + memDC.SelectObject(*bmp); + dc.Blit(0, 0, sizeTPBM.x, sizeTPBM.y, &memDC, 0, 0, wxCOPY); + + if (prevTool != -1) + { + //need ul corner of bitmap, ul corner of dest, width/height + wxPoint pt(sizeStamp.x * (prevTool & 0x03), sizeStamp.y * (prevTool >> 2)); + dc.Blit(pt.x, pt.y, sizeStamp.x, sizeStamp.y, &memDC, pt.x, pt.y, wxSRC_INVERT); + } + + memDC.SelectObject(wxNullBitmap); +} + +// +// Find which tool we're pointing at +// +ToolType ToolWindow::FindSelectedTool(void) +{ + // Get mouse coords relative to the tool palette window + wxPoint pt = ScreenToClient(wxGetMousePosition()); + + // Divide mouse coords by the bitmap stamp size to find which one is pointed to + uint32 x = (uint32)pt.x / sizeStamp.x, y = (uint32)pt.y / sizeStamp.y; + + // Preset failure into newTool, in case no new tool is selected + ToolType newTool = TOOLNone; + + // NOTE: This works because x and y are UNSIGNED + if (x < 4 && y < 2) + newTool = (ToolType)((y * 4) + x); + + return newTool; +} diff --git a/src/toolwindow.h b/src/toolwindow.h new file mode 100755 index 0000000..5d1ee3e --- /dev/null +++ b/src/toolwindow.h @@ -0,0 +1,47 @@ +// +// TOOLWINDOW.H: Header file +// +// by James L. Hammons +// (C) 2008 Underground Software +// + +#ifndef __TOOLWINDOW_H__ +#define __TOOLWINDOW_H__ + +#include // So that whoever uses this can without having + // to pull in a bunch of references manually + +// Enumerations (prolly go into ToolWindow class--?) + +enum ToolType { + TOOLNone = -1, // No tool + TOOLSelect = 0, // The "selection" tool + TOOLPolySelect, // Polygon selection tool + TOOLScroll, // Scroll window tool + TOOLZoom, // Zoom window tool + TOOLAddPt, // Add point tool + TOOLAddPoly, // Polygon creation tool + TOOLDelPt, // Delete point tool + TOOLDelPoly // Delete polygon tool +}; + +class ToolWindow: public wxFrame +{ + private: + protected: + public: + wxBitmap * bmp; + wxPoint sizeStamp, sizeTPBM; + ToolType prevTool; + + // Constructor and destructor + ToolWindow(wxFrame * parent, const wxString &title, const wxPoint &pos, const wxSize &size, long style); + ~ToolWindow(void); + + void OnPaint(wxPaintEvent &e); + ToolType FindSelectedTool(void); + + DECLARE_EVENT_TABLE() +}; + +#endif // __TOOLWINDOW_H__