From: Anton Gladky Date: Sat, 31 Dec 2016 08:50:56 +0000 (+0100) Subject: New upstream version 2.3+repack1 X-Git-Tag: archive/raspbian/3.1+ds1-4+rpi1^2~30^2~7 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4bcf775e6adf23548562b4b2a24251a60a894714;p=solvespace.git New upstream version 2.3+repack1 --- diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 7c97503..0000000 --- a/.gitattributes +++ /dev/null @@ -1,22 +0,0 @@ -# .gitattributes for SolveSpace - -# Set default behaviour, in case users don't have core.autocrlf set. -* text=auto - -# Explicitly declare text files we want to always be normalized and converted -# to native line endings on checkout. -*.cpp text -*.h text -*.txt text - -# Declare files that will always have CRLF line endings on checkout. -*.sln text eol=crlf - -# Denote all files that are truly binary and should not be modified. -*.gz binary -*.ico binary -*.jpg binary -*.lib binary -*.png binary - -# end .gitattributes diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 28be69f..0000000 --- a/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -/CMakeCache.txt -/build*/ -*.trace # OpenGL apitrace files -/debian/tmp/ -/debian/*.log -/debian/*.substvars -/debian/*.debhelper -/debian/files -/debian/solvespace/ -/debian/libslvs1/ -/debian/libslvs1-dev/ -/obj-*/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index dabc567..0000000 --- a/.gitmodules +++ /dev/null @@ -1,13 +0,0 @@ -[submodule "extlib/zlib"] - path = extlib/zlib - url = https://github.com/madler/zlib - ignore = dirty -[submodule "extlib/libpng"] - path = extlib/libpng - url = https://github.com/glennrp/libpng -[submodule "extlib/libfreetype"] - path = extlib/libfreetype - url = http://git.sv.nongnu.org/r/freetype/freetype2.git -[submodule "extlib/libdxfrw"] - path = extlib/libdxfrw - url = https://github.com/solvespace/libdxfrw.git diff --git a/.travis.yml b/.travis.yml index 5e831b1..b51c80c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,18 +11,6 @@ script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./.travis/build-debian.sh; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.travis/build-macos.sh; fi deploy: - # Releases to solvespace/solvespace - - provider: releases - api_key: - secure: dDlkIawHcODlW9B/20/cQCtzeoocvs0hKuNngRKXKqzXLWTRq33oq/B7+39tAixWbmv6exTpijiKrRNFiSCW5Z4iwHLwaRD4XJznxw63e/Hus/dxg2Tvqx7XFpkCz8mT1Z+gZQE5YxAngeZPpI/sZbZtF1UO3yH5eLeeokZ15p26ZskQUPoYuzrTgTzYL3XfpG3F+20rNBawH1ycsCTVD/08/n31d2m3CrKAsbW7er92ek6w4fzKr7NW8WeXjrPJETVpw5fQg1Od3pRGW8dPQaJcvKQEogMp8Mm0ETYd0qigg89/giBz7QwOgmAWQ4dH+DfZH4Ojl//127QztBolMvyDMQBykWrtJoGcij05sT6K2IJr2FHeUBO12MAEdjiVvhQj3DtTzjPiZAHHDBSLWxLKWWhlhHE4pq7g1MQhqXkaAHI2BLNzwLmaowbMT0bECf9yfz6xx18h6XPQFX44oOktraobVALFlyHqeKa8zdcUt22LF6uAL1m5dxL0tny3eXCIPE4UH/RZgua/cHV9G3cUvKQa/QnFSLRhvWVSbGB+7YsHouBJcsUOOW1gmd5442XuC7mpppccRldh+GSxUk6TBJRAx7TeQ0ybDUaoco9MUqp2twv3KreR2+8Q12PDaAhfQVNEGdF3wTm1sShImjCN4VN3eSLlBEbve1QRQXM= - skip_cleanup: true - file_glob: true - file: - - ../*.deb - on: - repo: solvespace/solvespace - tags: true - condition: "$TRAVIS_OS_NAME == linux" - provider: releases api_key: secure: dDlkIawHcODlW9B/20/cQCtzeoocvs0hKuNngRKXKqzXLWTRq33oq/B7+39tAixWbmv6exTpijiKrRNFiSCW5Z4iwHLwaRD4XJznxw63e/Hus/dxg2Tvqx7XFpkCz8mT1Z+gZQE5YxAngeZPpI/sZbZtF1UO3yH5eLeeokZ15p26ZskQUPoYuzrTgTzYL3XfpG3F+20rNBawH1ycsCTVD/08/n31d2m3CrKAsbW7er92ek6w4fzKr7NW8WeXjrPJETVpw5fQg1Od3pRGW8dPQaJcvKQEogMp8Mm0ETYd0qigg89/giBz7QwOgmAWQ4dH+DfZH4Ojl//127QztBolMvyDMQBykWrtJoGcij05sT6K2IJr2FHeUBO12MAEdjiVvhQj3DtTzjPiZAHHDBSLWxLKWWhlhHE4pq7g1MQhqXkaAHI2BLNzwLmaowbMT0bECf9yfz6xx18h6XPQFX44oOktraobVALFlyHqeKa8zdcUt22LF6uAL1m5dxL0tny3eXCIPE4UH/RZgua/cHV9G3cUvKQa/QnFSLRhvWVSbGB+7YsHouBJcsUOOW1gmd5442XuC7mpppccRldh+GSxUk6TBJRAx7TeQ0ybDUaoco9MUqp2twv3KreR2+8Q12PDaAhfQVNEGdF3wTm1sShImjCN4VN3eSLlBEbve1QRQXM= @@ -32,25 +20,3 @@ deploy: repo: solvespace/solvespace tags: true condition: "$TRAVIS_OS_NAME == osx" - # Releases to whitequark/solvespace (to be removed) - - provider: releases - api_key: - secure: DA3tW0My37vbi2t3dZ061281Xm8KSIkeLdFZsQISrut0g1kkbWuBTPxAfvE3B6OE8p47wAclE/wxA1+obMTVkY0oYpd5u+JelYNHxU/oL8Ww0xdUANwKNJ1JD2EZP8nSz7JSvxuGILC6AFPoTjawsG97SXwiTyp7z0PA6nvzraE= - skip_cleanup: true - file_glob: true - file: - - ../*.deb - on: - repo: whitequark/solvespace - tags: true - condition: "$TRAVIS_OS_NAME == linux" - - provider: releases - api_key: - secure: DA3tW0My37vbi2t3dZ061281Xm8KSIkeLdFZsQISrut0g1kkbWuBTPxAfvE3B6OE8p47wAclE/wxA1+obMTVkY0oYpd5u+JelYNHxU/oL8Ww0xdUANwKNJ1JD2EZP8nSz7JSvxuGILC6AFPoTjawsG97SXwiTyp7z0PA6nvzraE= - skip_cleanup: true - file: build/solvespace.dmg - on: - repo: whitequark/solvespace - tags: true - condition: "$TRAVIS_OS_NAME == osx" - diff --git a/CHANGELOG.md b/CHANGELOG.md index 63dee5b..095eee6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,22 @@ Changelog ========= +2.3 +--- + +Bug fixes: + * Do not crash when applying a symmetry constraint to two points. + * Fix TTF font metrics again (properly this time). + * Fix the "draw back faces in red" option. + * Fix export of wireframe as 3D DXF. + * Various minor crashes. + 2.2 --- Other new features: * OS X: support 3Dconnexion devices (SpaceMouse, SpaceNavigator, etc). + * GTK: files with uppercase extensions can be opened. Bug fixes: * Do not remove autosaves after successfully opening a file, preventing @@ -20,6 +31,11 @@ Bug fixes: * Forcibly show the current group once we start a drawing operation. * DXF export: always declare layers before using them. * Do not truncate operations on selections to first 32 selected entities. + * Translate and rotate groups inherit the "suppress solid model" setting. + * DXF: files with paths containing non-ASCII or spaces can be exported + or imported. + * Significantly improved performance when dragging an entity. + * Various crashes and minor glitches. 2.1 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 90a3eb8..ea464e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,11 +17,16 @@ set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX # project +# NOTE TO PACKAGERS: The embedded git commit hash is critical for rapid bug triage when the builds +# can come from a variety of sources. If you are mirroring the sources or otherwise build when +# the .git directory is not present, please comment the following line: include(GetGitCommitHash) +# and instead uncomment the following, adding the complete git hash of the checkout you are using: +# set(GIT_COMMIT_HASH 0000000000000000000000000000000000000000) project(solvespace) set(solvespace_VERSION_MAJOR 2) -set(solvespace_VERSION_MINOR 1) +set(solvespace_VERSION_MINOR 3) string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH) if(NOT WIN32 AND NOT APPLE) diff --git a/README.md b/README.md index a1a49ec..838b92f 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,13 @@ Building on Linux ### Building for Linux You will need CMake, libpng, zlib, json-c, fontconfig, freetype, gtkmm 2.4, -pangomm 1.4, OpenGL and OpenGL GLU. +pangomm 1.4, OpenGL, OpenGL GLU and OpenGL GLEW, and optionally, the Space Navigator +client library. On a Debian derivative (e.g. Ubuntu) these can be installed with: apt-get install libpng12-dev libjson-c-dev libfreetype6-dev \ libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \ - libgl-dev libglu-dev libglew-dev cmake + libgl-dev libglu-dev libglew-dev libspnav-dev cmake Before building, check out the necessary submodules: diff --git a/appveyor.yml b/appveyor.yml index 8078a56..4f4b3ae 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.{build} +version: 2.2.{build} clone_depth: 1 before_build: - git submodule update --init @@ -19,7 +19,6 @@ artifacts: - path: build\src\RelWithDebInfo\solvespace.pdb name: solvespace.pdb deploy: - # Releases to solvespace/solvespace - provider: GitHub auth_token: secure: P9/pf2nM+jlWKe7pCjMp41HycBNP/+5AsmE/TETrDUoBOa/9WFHelqdVFrbRn9IC @@ -27,11 +26,3 @@ deploy: artifact: solvespace.exe on: appveyor_repo_tag: true - # Releases to whitequark/solvespace (to be removed) - - provider: GitHub - auth_token: - secure: Flqxu1cz6PyxVT1wzTP4bSrQOY8wFrO7pJxYxvjEkLqIUU4dsDQrs2rac/A9deet - description: "" - artifact: solvespace.exe - on: - appveyor_repo_tag: true diff --git a/extlib/libdxfrw/intern/dwgbuffer.cpp b/extlib/libdxfrw/intern/dwgbuffer.cpp index a8d9b68..8bf914f 100644 --- a/extlib/libdxfrw/intern/dwgbuffer.cpp +++ b/extlib/libdxfrw/intern/dwgbuffer.cpp @@ -151,7 +151,7 @@ dwgBuffer::dwgBuffer(duint8 *buf, int size, DRW_TextCodec *dc){ bitPos = 0; } -dwgBuffer::dwgBuffer(std::ifstream *stream, DRW_TextCodec *dc){ +dwgBuffer::dwgBuffer(std::istream *stream, DRW_TextCodec *dc){ filestr = new dwgFileStream(stream); decoder = dc; maxSize = filestr->size(); diff --git a/extlib/libdxfrw/intern/dwgbuffer.h b/extlib/libdxfrw/intern/dwgbuffer.h index bfc4fa6..2dffc23 100644 --- a/extlib/libdxfrw/intern/dwgbuffer.h +++ b/extlib/libdxfrw/intern/dwgbuffer.h @@ -35,7 +35,7 @@ public: class dwgFileStream: public dwgBasicStream{ public: - dwgFileStream(std::ifstream *s){ + dwgFileStream(std::istream *s){ stream =s; stream->seekg (0, std::ios::end); sz = stream->tellg(); @@ -49,7 +49,7 @@ public: virtual bool good(){return stream->good();} virtual dwgBasicStream* clone(){return new dwgFileStream(stream);} private: - std::ifstream *stream; + std::istream *stream; duint64 sz; }; @@ -77,7 +77,7 @@ private: class dwgBuffer { public: - dwgBuffer(std::ifstream *stream, DRW_TextCodec *decoder = NULL); + dwgBuffer(std::istream *stream, DRW_TextCodec *decoder = NULL); dwgBuffer(duint8 *buf, int size, DRW_TextCodec *decoder= NULL); dwgBuffer( const dwgBuffer& org ); dwgBuffer& operator=( const dwgBuffer& org ); diff --git a/extlib/libdxfrw/intern/dwgreader.h b/extlib/libdxfrw/intern/dwgreader.h index 9f34885..4e88932 100644 --- a/extlib/libdxfrw/intern/dwgreader.h +++ b/extlib/libdxfrw/intern/dwgreader.h @@ -120,7 +120,7 @@ public: class dwgReader { friend class dwgR; public: - dwgReader(std::ifstream *stream, dwgR *p){ + dwgReader(std::istream *stream, dwgR *p){ fileBuf = new dwgBuffer(stream); parent = p; decoder.setVersion(DRW::AC1021, false);//default 2007 in utf8(no convert) diff --git a/extlib/libdxfrw/intern/dwgreader15.h b/extlib/libdxfrw/intern/dwgreader15.h index 8b3dc24..e3a1f97 100644 --- a/extlib/libdxfrw/intern/dwgreader15.h +++ b/extlib/libdxfrw/intern/dwgreader15.h @@ -21,7 +21,7 @@ class dwgReader15 : public dwgReader { public: - dwgReader15(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ } + dwgReader15(std::istream *stream, dwgR *p):dwgReader(stream, p){ } virtual ~dwgReader15() {} bool readMetaData(); bool readFileHeader(); diff --git a/extlib/libdxfrw/intern/dwgreader18.h b/extlib/libdxfrw/intern/dwgreader18.h index 4b66313..f814096 100644 --- a/extlib/libdxfrw/intern/dwgreader18.h +++ b/extlib/libdxfrw/intern/dwgreader18.h @@ -43,7 +43,7 @@ static const int DRW_magicNumEnd18[] = { class dwgReader18 : public dwgReader { public: - dwgReader18(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ + dwgReader18(std::istream *stream, dwgR *p):dwgReader(stream, p){ objData = NULL; } virtual ~dwgReader18(){ diff --git a/extlib/libdxfrw/intern/dwgreader21.h b/extlib/libdxfrw/intern/dwgreader21.h index 9cecd69..f95c77a 100644 --- a/extlib/libdxfrw/intern/dwgreader21.h +++ b/extlib/libdxfrw/intern/dwgreader21.h @@ -22,7 +22,7 @@ //reader for AC1021 aka v2007, chapter 5 class dwgReader21 : public dwgReader { public: - dwgReader21(std::ifstream *stream, dwgR *p):dwgReader(stream, p){ + dwgReader21(std::istream *stream, dwgR *p):dwgReader(stream, p){ objData = NULL; dataSize = 0; } diff --git a/extlib/libdxfrw/intern/dwgreader24.h b/extlib/libdxfrw/intern/dwgreader24.h index 36ac7fe..e5fc43a 100644 --- a/extlib/libdxfrw/intern/dwgreader24.h +++ b/extlib/libdxfrw/intern/dwgreader24.h @@ -21,7 +21,7 @@ class dwgReader24 : public dwgReader18 { public: - dwgReader24(std::ifstream *stream, dwgR *p):dwgReader18(stream, p){ } + dwgReader24(std::istream *stream, dwgR *p):dwgReader18(stream, p){ } virtual ~dwgReader24(){} bool readFileHeader(); bool readDwgHeader(DRW_Header& hdr); diff --git a/extlib/libdxfrw/intern/dwgreader27.h b/extlib/libdxfrw/intern/dwgreader27.h index 676cdc1..32c67f6 100644 --- a/extlib/libdxfrw/intern/dwgreader27.h +++ b/extlib/libdxfrw/intern/dwgreader27.h @@ -21,7 +21,7 @@ class dwgReader27 : public dwgReader18 { public: - dwgReader27(std::ifstream *stream, dwgR *p):dwgReader18(stream, p){ } + dwgReader27(std::istream *stream, dwgR *p):dwgReader18(stream, p){ } virtual ~dwgReader27(){} bool readFileHeader(); bool readDwgHeader(DRW_Header& hdr); diff --git a/extlib/libdxfrw/intern/dxfreader.h b/extlib/libdxfrw/intern/dxfreader.h index bcb3c1a..a0fa327 100644 --- a/extlib/libdxfrw/intern/dxfreader.h +++ b/extlib/libdxfrw/intern/dxfreader.h @@ -27,7 +27,7 @@ public: }; enum TYPE type; public: - dxfReader(std::ifstream *stream){ + dxfReader(std::istream *stream){ filestr = stream; type = INVALID; } @@ -58,7 +58,7 @@ protected: virtual bool readBool() = 0; protected: - std::ifstream *filestr; + std::istream *filestr; std::string strData; double doubleData; signed int intData; //32 bits integer @@ -70,7 +70,7 @@ private: class dxfReaderBinary : public dxfReader { public: - dxfReaderBinary(std::ifstream *stream):dxfReader(stream){skip = false; } + dxfReaderBinary(std::istream *stream):dxfReader(stream){skip = false; } virtual ~dxfReaderBinary() {} virtual bool readCode(int *code); virtual bool readString(std::string *text); @@ -84,7 +84,7 @@ public: class dxfReaderAscii : public dxfReader { public: - dxfReaderAscii(std::ifstream *stream):dxfReader(stream){skip = true; } + dxfReaderAscii(std::istream *stream):dxfReader(stream){skip = true; } virtual ~dxfReaderAscii(){} virtual bool readCode(int *code); virtual bool readString(std::string *text); diff --git a/extlib/libdxfrw/intern/dxfwriter.cpp b/extlib/libdxfrw/intern/dxfwriter.cpp index b31d69a..2276e7c 100644 --- a/extlib/libdxfrw/intern/dxfwriter.cpp +++ b/extlib/libdxfrw/intern/dxfwriter.cpp @@ -214,7 +214,7 @@ bool dxfWriterBinary::writeBool(int code, bool data) { return (filestr->good()); } -dxfWriterAscii::dxfWriterAscii(std::ofstream *stream):dxfWriter(stream){ +dxfWriterAscii::dxfWriterAscii(std::ostream *stream):dxfWriter(stream){ filestr->precision(16); } diff --git a/extlib/libdxfrw/intern/dxfwriter.h b/extlib/libdxfrw/intern/dxfwriter.h index 2af464b..adabe02 100644 --- a/extlib/libdxfrw/intern/dxfwriter.h +++ b/extlib/libdxfrw/intern/dxfwriter.h @@ -17,7 +17,7 @@ class dxfWriter { public: - dxfWriter(std::ofstream *stream){filestr = stream; /*count =0;*/} + dxfWriter(std::ostream *stream){filestr = stream; /*count =0;*/} virtual ~dxfWriter(){} virtual bool writeString(int code, std::string text) = 0; bool writeUtf8String(int code, std::string text); @@ -32,14 +32,14 @@ public: void setCodePage(std::string *c){encoder.setCodePage(c, true);} std::string getCodePage(){return encoder.getCodePage();} protected: - std::ofstream *filestr; + std::ostream *filestr; private: DRW_TextCodec encoder; }; class dxfWriterBinary : public dxfWriter { public: - dxfWriterBinary(std::ofstream *stream):dxfWriter(stream){} + dxfWriterBinary(std::ostream *stream):dxfWriter(stream){} virtual ~dxfWriterBinary() {} virtual bool writeString(int code, std::string text); virtual bool writeInt16(int code, int data); @@ -51,7 +51,7 @@ public: class dxfWriterAscii : public dxfWriter { public: - dxfWriterAscii(std::ofstream *stream); + dxfWriterAscii(std::ostream *stream); virtual ~dxfWriterAscii(){} virtual bool writeString(int code, std::string text); virtual bool writeInt16(int code, int data); diff --git a/extlib/libdxfrw/libdwgr.cpp b/extlib/libdxfrw/libdwgr.cpp index 4ba77ff..adca43c 100644 --- a/extlib/libdxfrw/libdwgr.cpp +++ b/extlib/libdxfrw/libdwgr.cpp @@ -35,9 +35,8 @@ secObjects };*/ -dwgR::dwgR(const char* name){ +dwgR::dwgR(){ DRW_DBGSL(DRW_dbg::NONE); - fileName = name; reader = NULL; // writer = NULL; applyExt = false; @@ -62,11 +61,10 @@ void dwgR::setDebug(DRW::DBG_LEVEL lvl){ } /*reads metadata and loads image preview*/ -bool dwgR::getPreview(){ +bool dwgR::getPreview(std::istream &stream){ bool isOk = false; - std::ifstream filestr; - isOk = openFile(&filestr); + isOk = open(&stream); if (!isOk) return false; @@ -76,7 +74,6 @@ bool dwgR::getPreview(){ } else error = DRW::BAD_READ_METADATA; - filestr.close(); if (reader != NULL) { delete reader; reader = NULL; @@ -84,70 +81,13 @@ bool dwgR::getPreview(){ return isOk; } -bool dwgR::testReader(){ - bool isOk = false; - - std::ifstream filestr; - filestr.open (fileName.c_str(), std::ios_base::in | std::ios::binary); - if (!filestr.is_open() || !filestr.good() ){ - error = DRW::BAD_OPEN; - return isOk; - } - - dwgBuffer fileBuf(&filestr); - duint8 *tmpStrData = new duint8[fileBuf.size()]; - fileBuf.getBytes(tmpStrData, fileBuf.size()); - dwgBuffer dataBuf(tmpStrData, fileBuf.size()); - fileBuf.setPosition(0); - DRW_DBG("\ndwgR::testReader filebuf size: ");DRW_DBG(fileBuf.size()); - DRW_DBG("\ndwgR::testReader dataBuf size: ");DRW_DBG(dataBuf.size()); - DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition()); - DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition()); - DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos()); - DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos()); - DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8()); - DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8()); - fileBuf.setBitPos(4); - dataBuf.setBitPos(4); - DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8()); - DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8()); - DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition()); - DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition()); - DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos()); - DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos()); - fileBuf.setBitPos(6); - dataBuf.setBitPos(6); - DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition()); - DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition()); - DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos()); - DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos()); - DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8()); - DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8()); - fileBuf.setBitPos(0); - dataBuf.setBitPos(0); - DRW_DBG("\n filebuf first byte : ");DRW_DBGH(fileBuf.getRawChar8()); - DRW_DBG("\n dataBuf first byte : ");DRW_DBGH(dataBuf.getRawChar8()); - DRW_DBG("\n filebuf pos: ");DRW_DBG(fileBuf.getPosition()); - DRW_DBG("\n dataBuf pos: ");DRW_DBG(dataBuf.getPosition()); - DRW_DBG("\n filebuf bitpos: ");DRW_DBG(fileBuf.getBitPos()); - DRW_DBG("\n dataBuf bitpos: ");DRW_DBG(dataBuf.getBitPos()); - - delete[]tmpStrData; - filestr.close(); - DRW_DBG("\n\n"); - return isOk; -} - -/*start reading dwg file header and, if can read it, continue reading all*/ -bool dwgR::read(DRW_Interface *interface_, bool ext){ - bool isOk = false; +bool dwgR::read(std::istream &stream, DRW_Interface *interface_, bool ext){ applyExt = ext; iface = interface_; -//testReader();return false; + bool isOk = false; - std::ifstream filestr; - isOk = openFile(&filestr); + isOk = open(&stream); if (!isOk) return false; @@ -161,7 +101,6 @@ bool dwgR::read(DRW_Interface *interface_, bool ext){ } else error = DRW::BAD_READ_METADATA; - filestr.close(); if (reader != NULL) { delete reader; reader = NULL; @@ -170,23 +109,9 @@ bool dwgR::read(DRW_Interface *interface_, bool ext){ return isOk; } -/* Open the file and stores it in filestr, install the correct reader version. - * If fail opening file, error are set as DRW::BAD_OPEN - * If not are DWG or are unsupported version, error are set as DRW::BAD_VERSION - * and closes filestr. - * Return true on succeed or false on fail -*/ -bool dwgR::openFile(std::ifstream *filestr){ - bool isOk = false; - DRW_DBG("dwgR::read 1\n"); - filestr->open (fileName.c_str(), std::ios_base::in | std::ios::binary); - if (!filestr->is_open() || !filestr->good() ){ - error = DRW::BAD_OPEN; - return isOk; - } - +bool dwgR::open(std::istream *stream){ char line[7]; - filestr->read (line, 6); + stream->read (line, 6); line[6]='\0'; DRW_DBG("dwgR::read 2\n"); DRW_DBG("dwgR::read line version: "); @@ -200,35 +125,33 @@ bool dwgR::openFile(std::ifstream *filestr){ // reader = new dwgReader09(&filestr, this); }else if (strcmp(line, "AC1012") == 0){ version = DRW::AC1012; - reader = new dwgReader15(filestr, this); + reader = new dwgReader15(stream, this); } else if (strcmp(line, "AC1014") == 0) { version = DRW::AC1014; - reader = new dwgReader15(filestr, this); + reader = new dwgReader15(stream, this); } else if (strcmp(line, "AC1015") == 0) { version = DRW::AC1015; - reader = new dwgReader15(filestr, this); + reader = new dwgReader15(stream, this); } else if (strcmp(line, "AC1018") == 0){ version = DRW::AC1018; - reader = new dwgReader18(filestr, this); + reader = new dwgReader18(stream, this); } else if (strcmp(line, "AC1021") == 0) { version = DRW::AC1021; - reader = new dwgReader21(filestr, this); + reader = new dwgReader21(stream, this); } else if (strcmp(line, "AC1024") == 0) { version = DRW::AC1024; - reader = new dwgReader24(filestr, this); + reader = new dwgReader24(stream, this); } else if (strcmp(line, "AC1027") == 0) { version = DRW::AC1027; - reader = new dwgReader27(filestr, this); + reader = new dwgReader27(stream, this); } else version = DRW::UNKNOWNV; if (reader == NULL) { error = DRW::BAD_VERSION; - filestr->close(); - } else - isOk = true; - - return isOk; + return false; + } + return true; } /********* Reader Process *********/ diff --git a/extlib/libdxfrw/libdwgr.h b/extlib/libdxfrw/libdwgr.h index 8e035fe..0601004 100644 --- a/extlib/libdxfrw/libdwgr.h +++ b/extlib/libdxfrw/libdwgr.h @@ -24,18 +24,17 @@ class dwgReader; class dwgR { public: - dwgR(const char* name); + dwgR(); ~dwgR(); //read: return true if all ok - bool read(DRW_Interface *interface_, bool ext); - bool getPreview(); + bool read(std::istream &stream, DRW_Interface *interface_, bool ext); + bool getPreview(std::istream &stream); DRW::Version getVersion(){return version;} DRW::error getError(){return error;} -bool testReader(); void setDebug(DRW::DBG_LEVEL lvl); private: - bool openFile(std::ifstream *filestr); + bool open(std::istream *stream); bool processDwg(); private: DRW::Version version; diff --git a/extlib/libdxfrw/libdxfrw.cpp b/extlib/libdxfrw/libdxfrw.cpp index d1edcfe..9eecea7 100644 --- a/extlib/libdxfrw/libdxfrw.cpp +++ b/extlib/libdxfrw/libdxfrw.cpp @@ -32,9 +32,8 @@ secObjects };*/ -dxfRW::dxfRW(const char* name){ +dxfRW::dxfRW(){ DRW_DBGSL(DRW_dbg::NONE); - fileName = name; reader = NULL; writer = NULL; applyExt = false; @@ -61,63 +60,46 @@ void dxfRW::setDebug(DRW::DBG_LEVEL lvl){ } } -bool dxfRW::read(DRW_Interface *interface_, bool ext){ - drw_assert(fileName.empty() == false); - bool isOk = false; +bool dxfRW::read(std::istream &stream, DRW_Interface *interface_, bool ext){ applyExt = ext; - std::ifstream filestr; - if ( interface_ == NULL ) - return isOk; - DRW_DBG("dxfRW::read 1def\n"); - filestr.open (fileName.c_str(), std::ios_base::in | std::ios::binary); - if (!filestr.is_open()) - return isOk; - if (!filestr.good()) - return isOk; + + if(interface_ == NULL) + return false; char line[22]; char line2[22] = "AutoCAD Binary DXF\r\n"; line2[20] = (char)26; line2[21] = '\0'; - filestr.read (line, 22); - filestr.close(); + stream.read (line, 22); iface = interface_; DRW_DBG("dxfRW::read 2\n"); if (strcmp(line, line2) == 0) { - filestr.open (fileName.c_str(), std::ios_base::in | std::ios::binary); binFile = true; - //skip sentinel - filestr.seekg (22, std::ios::beg); - reader = new dxfReaderBinary(&filestr); + reader = new dxfReaderBinary(&stream); DRW_DBG("dxfRW::read binary file\n"); } else { binFile = false; - filestr.open (fileName.c_str(), std::ios_base::in); - reader = new dxfReaderAscii(&filestr); + stream.seekg(0, std::ios::beg); + reader = new dxfReaderAscii(&stream); } - isOk = processDxf(); - filestr.close(); + bool isOk = processDxf(); delete reader; reader = NULL; return isOk; } -bool dxfRW::write(DRW_Interface *interface_, DRW::Version ver, bool bin){ - bool isOk = false; - std::ofstream filestr; +bool dxfRW::write(std::ostream &stream, DRW_Interface *interface_, DRW::Version ver, bool bin){ version = ver; binFile = bin; iface = interface_; if (binFile) { - filestr.open (fileName.c_str(), std::ios_base::out | std::ios::binary | std::ios::trunc); //write sentinel - filestr << "AutoCAD Binary DXF\r\n" << (char)26 << '\0'; - writer = new dxfWriterBinary(&filestr); + stream << "AutoCAD Binary DXF\r\n" << (char)26 << '\0'; + writer = new dxfWriterBinary(&stream); DRW_DBG("dxfRW::read binary file\n"); } else { - filestr.open (fileName.c_str(), std::ios_base::out | std::ios::trunc); - writer = new dxfWriterAscii(&filestr); + writer = new dxfWriterAscii(&stream); std::string comm = std::string("dxfrw ") + std::string(DRW_VERSION); writer->writeString(999, comm); } @@ -153,12 +135,10 @@ bool dxfRW::write(DRW_Interface *interface_, DRW::Version ver, bool bin){ writer->writeString(0, "ENDSEC"); } writer->writeString(0, "EOF"); - filestr.flush(); - filestr.close(); - isOk = true; + stream.flush(); delete writer; writer = NULL; - return isOk; + return true; } bool dxfRW::writeEntity(DRW_Entity *ent) { diff --git a/extlib/libdxfrw/libdxfrw.h b/extlib/libdxfrw/libdxfrw.h index 18c2649..b3de272 100644 --- a/extlib/libdxfrw/libdxfrw.h +++ b/extlib/libdxfrw/libdxfrw.h @@ -25,7 +25,7 @@ class dxfWriter; class dxfRW { public: - dxfRW(const char* name); + dxfRW(); ~dxfRW(); void setDebug(DRW::DBG_LEVEL lvl); /// reads the file specified in constructor @@ -36,10 +36,10 @@ public: * @param ext should the extrusion be applied to convert in 2D? * @return true for success */ - bool read(DRW_Interface *interface_, bool ext); + bool read(std::istream &stream, DRW_Interface *interface_, bool ext); void setBinary(bool b) {binFile = b;} - bool write(DRW_Interface *interface_, DRW::Version ver, bool bin); + bool write(std::ostream &stream, DRW_Interface *interface_, DRW::Version ver, bool bin); bool writeLineType(DRW_LType *ent); bool writeLayer(DRW_Layer *ent); bool writeDimstyle(DRW_Dimstyle *ent); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b3e0b17..5c53130 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -342,8 +342,9 @@ if(APPLE) set(fixups) foreach(lib ${platform_BUNDLED_LIBS}) get_filename_component(name ${lib} NAME) - execute_process(COMMAND otool -XD ${lib} + execute_process(COMMAND otool -D ${lib} OUTPUT_VARIABLE canonical_lib OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REGEX REPLACE "^.+:\n" "" canonical_lib ${canonical_lib}) add_custom_command(TARGET solvespace POST_BUILD COMMAND install_name_tool -change ${canonical_lib} @executable_path/${name} $ diff --git a/src/cocoa/cocoamain.mm b/src/cocoa/cocoamain.mm index 8d21e9c..1b6d3e6 100644 --- a/src/cocoa/cocoamain.mm +++ b/src/cocoa/cocoamain.mm @@ -374,8 +374,6 @@ CONVERT(Rect) if(NSString *nsChr = [event charactersIgnoringModifiers]) chr = [nsChr characterAtIndex:0]; - if(chr == NSDeleteCharacter) /* map delete back to backspace */ - chr = '\b'; if(chr >= NSF1FunctionKey && chr <= NSF12FunctionKey) chr = SolveSpace::GraphicsWindow::FUNCTION_KEY_BASE + (chr - NSF1FunctionKey); @@ -650,12 +648,15 @@ void InitMainMenu(NSMenu *mainMenu) { label = [[NSString stringWithUTF8String:entry->label] stringByReplacingOccurrencesOfString:@"&" withString:@""]; - unichar accel_char = entry->accel & + unichar accelChar = entry->accel & ~(GraphicsWindow::SHIFT_MASK | GraphicsWindow::CTRL_MASK); - if(accel_char > GraphicsWindow::FUNCTION_KEY_BASE && - accel_char <= GraphicsWindow::FUNCTION_KEY_BASE + 12) - accel_char = NSF1FunctionKey + (accel_char - GraphicsWindow::FUNCTION_KEY_BASE - 1); - NSString *accel = [NSString stringWithCharacters:&accel_char length:1]; + if(accelChar > GraphicsWindow::FUNCTION_KEY_BASE && + accelChar <= GraphicsWindow::FUNCTION_KEY_BASE + 12) { + accelChar = NSF1FunctionKey + (accelChar - GraphicsWindow::FUNCTION_KEY_BASE - 1); + } else if(accelChar == GraphicsWindow::DELETE_KEY) { + accelChar = NSBackspaceCharacter; + } + NSString *accel = [NSString stringWithCharacters:&accelChar length:1]; menuItem = [levels[entry->level] addItemWithTitle:label action:NULL keyEquivalent:[accel lowercaseString]]; @@ -809,6 +810,9 @@ bool SolveSpace::GetSaveFile(std::string *file, const std::string &defExtension, if(defExtension != "") { extensionIndex = [extensions indexOfObject: [NSString stringWithUTF8String:defExtension.c_str()]]; + if(extensionIndex == -1) { + extensionIndex = 0; + } } [button selectItemAtIndex:extensionIndex]; @@ -1028,17 +1032,12 @@ void InitTextWindow() { [TW setFrameAutosaveName:@"TextWindow"]; [TW setFloatingPanel:YES]; [TW setBecomesKeyOnlyIfNeeded:YES]; - [GW addChildWindow:TW ordered:NSWindowAbove]; - - // Without this, graphics window is also hidden when the text window is shown - // (and is its child window). We replicate the standard behavior manually, in - // the application delegate; - [TW setHidesOnDeactivate:NO]; NSScrollView *scrollView = [[NSScrollView alloc] init]; [TW setContentView:scrollView]; [scrollView setBackgroundColor:[NSColor blackColor]]; [scrollView setHasVerticalScroller:YES]; + [scrollView setScrollerKnobStyle:NSScrollerKnobStyleLight]; [[scrollView contentView] setCopiesOnScroll:YES]; TWView = [[TextWindowView alloc] init]; @@ -1052,9 +1051,9 @@ void InitTextWindow() { void ShowTextWindow(bool visible) { if(visible) - [GW addChildWindow:TW ordered:NSWindowAbove]; + [TW orderFront:nil]; else - [TW orderOut:GW]; + [TW close]; } void GetTextWindowSize(int *w, int *h) { @@ -1097,7 +1096,7 @@ bool TextEditControlIsVisible(void) { void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error) { NSAlert *alert = [[NSAlert alloc] init]; [alert setAlertStyle:(error ? NSWarningAlertStyle : NSInformationalAlertStyle)]; - [[alert addButtonWithTitle:@"OK"] setKeyEquivalent: @"\033"]; + [alert addButtonWithTitle:@"OK"]; /* do some additional formatting of the message these are heuristics, but they are made failsafe and lead to nice results. */ @@ -1145,8 +1144,6 @@ std::vector SolveSpace::GetFontFiles() { - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; - (void)applicationWillTerminate:(NSNotification *)aNotification; -- (void)applicationWillBecomeActive:(NSNotification *)aNotification; -- (void)applicationWillResignActive:(NSNotification *)aNotification; - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; - (IBAction)preferences:(id)sender; @end @@ -1167,18 +1164,6 @@ std::vector SolveSpace::GetFontFiles() { SolveSpace::SS.Exit(); } -- (void)applicationWillBecomeActive:(NSNotification *)aNotification { - if(SolveSpace::SS.GW.showTextWindow) { - [GW addChildWindow:TW ordered:NSWindowAbove]; - } -} - -- (void)applicationWillResignActive:(NSNotification *)aNotification { - [TW setAnimationBehavior:NSWindowAnimationBehaviorNone]; - [TW orderOut:nil]; - [TW setAnimationBehavior:NSWindowAnimationBehaviorDefault]; -} - - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { return SolveSpace::SS.OpenFile([filename UTF8String]); } diff --git a/src/constraint.cpp b/src/constraint.cpp index 6137021..e5aae1b 100644 --- a/src/constraint.cpp +++ b/src/constraint.cpp @@ -370,16 +370,21 @@ void Constraint::MenuConstrain(int id) { ((gs.workplanes == 1 && gs.n == 3) || (gs.n == 2))) { - c.entityA = gs.entity[0]; + if(gs.entities > 0) + c.entityA = gs.entity[0]; c.ptA = gs.point[0]; c.ptB = gs.point[1]; } else if(gs.lineSegments == 1 && ((gs.workplanes == 1 && gs.n == 2) || (gs.n == 1))) { - int i = SK.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0; - Entity *line = SK.GetEntity(gs.entity[i]); - c.entityA = gs.entity[1-i]; + Entity *line; + if(SK.GetEntity(gs.entity[0])->IsWorkplane()) { + line = SK.GetEntity(gs.entity[1]); + c.entityA = gs.entity[0]; + } else { + line = SK.GetEntity(gs.entity[0]); + } c.ptA = line->point[0]; c.ptB = line->point[1]; } else if(SS.GW.LockedInWorkplane() diff --git a/src/exportvector.cpp b/src/exportvector.cpp index 1b76b8e..ca625ec 100644 --- a/src/exportvector.cpp +++ b/src/exportvector.cpp @@ -259,14 +259,17 @@ public: found = true; e->tag = 1; - DRW_LWPolyline polyline; + DRW_Polyline polyline; assignEntityDefaults(&polyline, e->style); - polyline.vertlist.push_back(new DRW_Vertex2D(start->pos.x, start->pos.y, 0.0)); - polyline.vertlist.push_back(new DRW_Vertex2D(next->pos.x, next->pos.y, 0.0)); + polyline.vertlist.push_back( + new DRW_Vertex(start->pos.x, start->pos.y, start->pos.z, 0.0)); + polyline.vertlist.push_back( + new DRW_Vertex(next->pos.x, next->pos.y, next->pos.z, 0.0)); while(next->getNext(e->style, &next)) { - polyline.vertlist.push_back(new DRW_Vertex2D(next->pos.x, next->pos.y, 0.0)); + polyline.vertlist.push_back( + new DRW_Vertex(next->pos.x, next->pos.y, next->pos.z, 0.0)); } - dxf->writeLWPolyline(&polyline); + dxf->writePolyline(&polyline); } if(!found && !loop) { @@ -384,7 +387,7 @@ public: Vector dna = norm.Cross(da).WithMagnitude(1.0); double thetaf = acos(da.DirectionCosineWith(db)); - + // Calculate median Vector m = da.WithMagnitude(1.0).ScaledBy(cos(thetaf/2)).Plus( dna.ScaledBy(sin(thetaf/2))); @@ -479,16 +482,14 @@ public: List lv = {}; sb->MakePwlInto(&lv, SS.ExportChordTolMm()); hStyle hs = { (uint32_t)sb->auxA }; - DRW_LWPolyline polyline; + DRW_Polyline polyline; assignEntityDefaults(&polyline, hs); for(int i = 0; i < lv.n; i++) { Vector *v = &lv.elem[i]; - DRW_Vertex2D *vertex = new DRW_Vertex2D(); - vertex->x = v->x; - vertex->y = v->y; + DRW_Vertex *vertex = new DRW_Vertex(v->x, v->y, v->z, 0.0); polyline.vertlist.push_back(vertex); } - dxf->writeLWPolyline(&polyline); + dxf->writePolyline(&polyline); lv.Clear(); } @@ -527,7 +528,8 @@ public: spline.ncontrol = sb->deg + 1; makeKnotsFor(&spline); for(int i = 0; i <= sb->deg; i++) { - spline.controllist.push_back(new DRW_Coord(sb->ctrl[i].x, sb->ctrl[i].y, 0.0)); + spline.controllist.push_back( + new DRW_Coord(sb->ctrl[i].x, sb->ctrl[i].y, sb->ctrl[i].z)); if(isRational) spline.weightlist.push_back(sb->weight[i]); } dxf->writeSpline(&spline); @@ -684,12 +686,19 @@ void DxfFileWriter::Bezier(SBezier *sb) { paths.back().beziers.push_back(sb); } -void DxfFileWriter::FinishAndCloseFile(void) { - dxfRW dxf(filename.c_str()); +void DxfFileWriter::FinishAndCloseFile() { + dxfRW dxf; + DxfWriteInterface interface(this, &dxf); - dxf.write(&interface, DRW::AC1021, false); + std::stringstream stream; + dxf.write(stream, &interface, DRW::AC1021, /*bin=*/false); paths.clear(); constraint = NULL; + + if(!WriteFile(filename, stream.str())) { + Error("Couldn't write to '%s'", filename.c_str()); + return; + } } bool DxfFileWriter::NeedToOutput(Constraint *c) { diff --git a/src/generate.cpp b/src/generate.cpp index 2784098..581add6 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -308,7 +308,7 @@ void SolveSpaceUI::GenerateAll(GenerateType type, bool andFindFree, bool genForB // The group falls inside the range, so really solve it, // and then regenerate the mesh based on the solved stuff. if(genForBBox) { - SolveGroup(g->h, andFindFree); + SolveGroupAndReport(g->h, andFindFree); } else { g->GenerateLoops(); g->GenerateShellAndMesh(); @@ -491,6 +491,23 @@ void SolveSpaceUI::MarkDraggedParams(void) { } } +void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) { + SolveGroup(hg, andFindFree); + + Group *g = SK.GetGroup(hg); + if(g->solved.how == System::REDUNDANT_OKAY) { + // Solve again, in case we lost a degree of freedom because of a numeric error. + SolveGroup(hg, andFindFree); + } + + bool isOkay = g->solved.how == System::SOLVED_OKAY || + (g->allowRedundant && g->solved.how == System::REDUNDANT_OKAY); + + if(!isOkay || (isOkay && !g->IsSolvedOkay())) { + TextWindow::ReportHowGroupSolved(g->h); + } +} + void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { int i; // Clear out the system to be solved. @@ -518,12 +535,6 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) { g->solved.remove.Clear(); int how = sys.Solve(g, &(g->solved.dof), &(g->solved.remove), true, andFindFree); - bool isOkay = how == System::SOLVED_OKAY || - (g->allowRedundant && how == System::REDUNDANT_OKAY); - if(!isOkay || (isOkay && !g->IsSolvedOkay())) - { - TextWindow::ReportHowGroupSolved(g->h); - } g->solved.how = how; FreeAllTemporary(); } diff --git a/src/groupmesh.cpp b/src/groupmesh.cpp index 342f0c2..77130bc 100644 --- a/src/groupmesh.cpp +++ b/src/groupmesh.cpp @@ -203,8 +203,10 @@ void Group::GenerateShellAndMesh(void) { // not our own previous group. srcg = SK.GetGroup(opA); - GenerateForStepAndRepeat(&(srcg->thisShell), &thisShell); - GenerateForStepAndRepeat (&(srcg->thisMesh), &thisMesh); + if(!srcg->suppress) { + GenerateForStepAndRepeat(&(srcg->thisShell), &thisShell); + GenerateForStepAndRepeat (&(srcg->thisMesh), &thisMesh); + } } else if(type == EXTRUDE && haveSrc) { Group *src = SK.GetGroup(opA); Vector translate = Vector::From(h.param(0), h.param(1), h.param(2)); diff --git a/src/gtk/gtkmain.cpp b/src/gtk/gtkmain.cpp index 0f67fb7..386e970 100644 --- a/src/gtk/gtkmain.cpp +++ b/src/gtk/gtkmain.cpp @@ -55,10 +55,7 @@ #include "../unix/gloffscreen.h" #ifdef HAVE_SPACEWARE -# include -# ifndef SI_APP_FIT_BUTTON -# define SI_APP_FIT_BUTTON 31 -# endif +#include #endif namespace SolveSpace { @@ -1086,6 +1083,7 @@ static std::string ConvertFilters(std::string active, const FileFilter ssFilters for(const char *const *ssPattern = ssFilter->patterns; *ssPattern; ssPattern++) { std::string pattern = "*." + std::string(*ssPattern); filter->add_pattern(pattern); + filter->add_pattern(Glib::ustring(pattern).uppercase()); if(active == "") active = pattern.substr(2); if("*." + active == pattern) @@ -1522,7 +1520,7 @@ static GdkFilterReturn GdkSpnavFilter(GdkXEvent *gxevent, GdkEvent *, gpointer) break; case SPNAV_EVENT_BUTTON: - if(!sev.button.press && sev.button.bnum == SI_APP_FIT_BUTTON) { + if(!sev.button.press && sev.button.bnum == 0) { SS.GW.SpaceNavigatorButtonUp(); } break; diff --git a/src/importdxf.cpp b/src/importdxf.cpp index 5b7d6bd..dbd4e47 100644 --- a/src/importdxf.cpp +++ b/src/importdxf.cpp @@ -902,13 +902,21 @@ public: }; void ImportDxf(const std::string &filename) { - SS.UndoRemember(); - dxfRW dxf(filename.c_str()); DxfReadInterface interface; interface.clearBlockTransform(); - if(!dxf.read(&interface, false)) { - Error("Corrupted DXF file!"); + + std::string data; + if(!ReadFile(filename, &data)) { + Error("Couldn't read from '%s'", filename.c_str()); + return; + } + + SS.UndoRemember(); + std::stringstream stream(data); + if(!dxfRW().read(stream, &interface, /*ext=*/false)) { + Error("Corrupted DXF file."); } + if(interface.unknownEntities > 0) { Message(ssprintf("%u DXF entities of unknown type were ignored.", interface.unknownEntities).c_str()); @@ -916,13 +924,21 @@ void ImportDxf(const std::string &filename) { } void ImportDwg(const std::string &filename) { - SS.UndoRemember(); - dwgR dwg(filename.c_str()); DxfReadInterface interface; interface.clearBlockTransform(); - if(!dwg.read(&interface, false)) { - Error("Corrupted DWG file!"); + + std::string data; + if(!ReadFile(filename, &data)) { + Error("Couldn't read from '%s'", filename.c_str()); + return; + } + + SS.UndoRemember(); + std::stringstream stream(data); + if(!dwgR().read(stream, &interface, /*ext=*/false)) { + Error("Corrupted DWG file."); } + if(interface.unknownEntities > 0) { Message(ssprintf("%u DWG entities of unknown type were ignored.", interface.unknownEntities).c_str()); diff --git a/src/mesh.cpp b/src/mesh.cpp index 4fec2b4..6458e5d 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -34,7 +34,8 @@ void SMesh::AddTriangle(STriMeta meta, Vector a, Vector b, Vector c) { AddTriangle(&t); } void SMesh::AddTriangle(STriangle *st) { - if(st->meta.color.alpha != 255) isTransparent = true; + RgbaColor color = st->meta.color; + if(color.ToARGB32() != 0 && color.alpha != 255) isTransparent = true; l.Add(st); } diff --git a/src/mouse.cpp b/src/mouse.cpp index 352c17e..700b765 100644 --- a/src/mouse.cpp +++ b/src/mouse.cpp @@ -463,6 +463,15 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, pending.operation != DRAGGING_MARQUEE) { SS.GenerateAll(); + + // Activate degraded mode, and regenerate display items without edges. + if(activeGroup.v != 0) { + bool showEdges = SS.GW.showEdges; + SS.GW.showEdges = false; + SK.GetGroup(activeGroup)->GenerateDisplayItems(); + SS.GW.showEdges = showEdges; + isDegraded = true; + } } } @@ -470,6 +479,12 @@ void GraphicsWindow::ClearPending(void) { pending.points.Clear(); pending = {}; SS.ScheduleShowTW(); + + // If degraded mode was enabled, we need to regenerate again to get edges back. + if(isDegraded) { + isDegraded = false; + SK.GetGroup(activeGroup)->displayDirty = true; + } } void GraphicsWindow::MouseMiddleOrRightDown(double x, double y) { diff --git a/src/solvespace.cpp b/src/solvespace.cpp index 398cba0..c923b7b 100644 --- a/src/solvespace.cpp +++ b/src/solvespace.cpp @@ -427,8 +427,11 @@ void SolveSpaceUI::UpdateWindowTitle(void) { static std::string Extension(const std::string &filename) { int dot = filename.rfind('.'); - if(dot >= 0) - return filename.substr(dot + 1, filename.length()); + if(dot >= 0) { + std::string ext = filename.substr(dot + 1, filename.length()); + std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); + return ext; + } return ""; } @@ -548,7 +551,10 @@ void SolveSpaceUI::MenuFile(int id) { ImportDxf(importFile); } else if(Extension(importFile) == "dwg") { ImportDwg(importFile); - } else oops(); + } else { + Error("Can't identify file type from file extension of " + "filename '%s'; try .dxf or .dwg.", importFile.c_str()); + } SS.GenerateAll(SolveSpaceUI::GENERATE_UNTIL_ACTIVE); SS.ScheduleShowTW(); diff --git a/src/solvespace.h b/src/solvespace.h index 46debb9..6cb59c7 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef WIN32 # include // required by GL headers #endif @@ -135,6 +136,7 @@ class RgbaColor; #endif FILE *ssfopen(const std::string &filename, const char *mode); +std::fstream ssfstream(const std::string &filename, std::ios_base::openmode mode); void ssremove(const std::string &filename); #define MAX_RECENT 8 @@ -374,6 +376,8 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, double a41, double a42, double a43, double a44); std::string MakeAcceleratorLabel(int accel); bool FilenameHasExtension(const std::string &str, const char *ext); +bool ReadFile(const std::string &filename, std::string *data); +bool WriteFile(const std::string &filename, const std::string &data); void Message(const char *str, ...); void Error(const char *str, ...); void CnfFreezeBool(bool v, const std::string &name); @@ -908,6 +912,7 @@ public: void GenerateAll(GenerateType type = GENERATE_DIRTY, bool andFindFree = false, bool genForBBox = false); void SolveGroup(hGroup hg, bool andFindFree); + void SolveGroupAndReport(hGroup hg, bool andFindFree); void MarkDraggedParams(void); void ForceReferences(void); diff --git a/src/srf/surface.cpp b/src/srf/surface.cpp index 9b36cb9..3f3178c 100644 --- a/src/srf/surface.cpp +++ b/src/srf/surface.cpp @@ -426,6 +426,7 @@ void SSurface::TriangulateInto(SShell *shell, SMesh *sm) { for(i = start; i < sm->l.n; i++) { STriangle *st = &(sm->l.elem[i]); st->meta = meta; + if(st->meta.color.alpha != 255) sm->isTransparent = true; st->an = NormalAt(st->a.x, st->a.y); st->bn = NormalAt(st->b.x, st->b.y); st->cn = NormalAt(st->c.x, st->c.y); diff --git a/src/system.cpp b/src/system.cpp index 5ff118e..6b222b9 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -463,36 +463,34 @@ int System::Solve(Group *g, int *dof, List *bad, if(!rankOk) { if(!g->allowRedundant) { if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad); - return System::REDUNDANT_OKAY; } - } - - // This is not the full Jacobian, but any substitutions or single-eq - // solves removed one equation and one unknown, therefore no effect - // on the number of DOF. - if(dof) *dof = mat.n - mat.m; - - // If requested, find all the free (unbound) variables. This might be - // more than the number of degrees of freedom. Don't always do this, - // because the display would get annoying and it's slow. - for(i = 0; i < param.n; i++) { - Param *p = &(param.elem[i]); - p->free = false; - - if(andFindFree) { - if(p->tag == 0) { - p->tag = VAR_DOF_TEST; - WriteJacobian(0); - EvalJacobian(); - int rank = CalculateRank(); - if(rank == mat.m) { - p->free = true; + } else { + // This is not the full Jacobian, but any substitutions or single-eq + // solves removed one equation and one unknown, therefore no effect + // on the number of DOF. + if(dof) *dof = mat.n - mat.m; + + // If requested, find all the free (unbound) variables. This might be + // more than the number of degrees of freedom. Don't always do this, + // because the display would get annoying and it's slow. + for(i = 0; i < param.n; i++) { + Param *p = &(param.elem[i]); + p->free = false; + + if(andFindFree) { + if(p->tag == 0) { + p->tag = VAR_DOF_TEST; + WriteJacobian(0); + EvalJacobian(); + int rank = CalculateRank(); + if(rank == mat.m) { + p->free = true; + } + p->tag = 0; } - p->tag = 0; } } } - // System solved correctly, so write the new values back in to the // main parameter table. for(i = 0; i < param.n; i++) { diff --git a/src/textwin.cpp b/src/textwin.cpp index 78e4308..656ac62 100644 --- a/src/textwin.cpp +++ b/src/textwin.cpp @@ -988,7 +988,7 @@ void TextWindow::MouseEvent(bool leftClick, bool leftDown, double x, double y) { break; } } - if(r >= rows) { + if(r < 0 || c < 0 || r >= rows || c >= MAX_COLS) { SetMousePointerToHand(false); goto done; } diff --git a/src/ttf.cpp b/src/ttf.cpp index 0d9bfa7..79cbffd 100644 --- a/src/ttf.cpp +++ b/src/ttf.cpp @@ -88,7 +88,9 @@ void TtfFontList::PlotString(const std::string &font, const std::string &str, [&](const TtfFont &tf) { return tf.FontFileBaseName() == font; }); if(!str.empty() && tf != &l.elem[l.n]) { - tf->LoadFromFile(fontLibrary, /*nameOnly=*/false); + if(tf->fontFace == NULL) { + tf->LoadFromFile(fontLibrary, /*nameOnly=*/false); + } tf->PlotString(str, sbl, origin, u, v); } else { // No text or no font; so draw a big X for an error marker. @@ -135,6 +137,7 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) { dbp("freetype: loading unicode CMap for file '%s' failed: %s", fontFile.c_str(), ft_error_string(fterr)); FT_Done_Face(fontFace); + fontFace = NULL; return false; } @@ -144,6 +147,47 @@ bool TtfFont::LoadFromFile(FT_Library fontLibrary, bool nameOnly) { if(nameOnly) { FT_Done_Face(fontFace); fontFace = NULL; + return true; + } + + // We always ask Freetype to give us a unit size character. + // It uses fixed point; put the unit size somewhere in the middle of the dynamic + // range of its 26.6 fixed point type, and adjust the factors so that the unit + // matches cap height. + FT_Size_RequestRec sizeRequest; + sizeRequest.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + sizeRequest.width = 1 << 16; + sizeRequest.height = 1 << 16; + sizeRequest.horiResolution = 128; + sizeRequest.vertResolution = 128; + if(int fterr = FT_Request_Size(fontFace, &sizeRequest)) { + dbp("freetype: cannot set character size: %s", + ft_error_string(fterr)); + FT_Done_Face(fontFace); + fontFace = NULL; + return false; + } + + char chr = 'A'; + uint32_t gid = FT_Get_Char_Index(fontFace, 'A'); + if (gid == 0) { + dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID", + chr, ft_error_string(gid)); + gid = chr; + } + + if(gid) { + if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) { + dbp("freetype: cannot load glyph for GID 0x%04x: %s", + gid, ft_error_string(fterr)); + FT_Done_Face(fontFace); + fontFace = NULL; + return false; + } + + FT_BBox bbox; + FT_Outline_Get_CBox(&fontFace->glyph->outline, &bbox); + capHeight = (double)bbox.yMax; } return true; @@ -225,27 +269,12 @@ void TtfFont::PlotString(const std::string &str, outlineFuncs.delta = 0; FT_Pos dx = 0; - for(char32_t chr : ReadUTF8(str)) { - uint32_t gid = FT_Get_Char_Index(fontFace, chr); + for(char32_t cid : ReadUTF8(str)) { + uint32_t gid = FT_Get_Char_Index(fontFace, cid); if (gid == 0) { dbp("freetype: CID-to-GID mapping for CID 0x%04x failed: %s; using CID as GID", - chr, ft_error_string(gid)); - } - - // We always ask Freetype to give us a unit size character. - // It uses fixed point; put the unit size somewhere in the middle of the dynamic - // range of its 26.6 fixed point type, and adjust the factors so that the unit - // matches cap height. - FT_Size_RequestRec sizeRequest; - sizeRequest.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; - sizeRequest.width = 1 << 16; - sizeRequest.height = 1 << 16; - sizeRequest.horiResolution = 128; - sizeRequest.vertResolution = 128; - if(int fterr = FT_Request_Size(fontFace, &sizeRequest)) { - dbp("freetype: cannot set character size: %s", - ft_error_string(fterr)); - return; + cid, ft_error_string(gid)); + gid = cid; } /* @@ -257,7 +286,7 @@ void TtfFont::PlotString(const std::string &str, * ones, antialiasing mitigates this considerably though. */ if(int fterr = FT_Load_Glyph(fontFace, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) { - dbp("freetype: cannot load glyph (gid %d): %s", + dbp("freetype: cannot load glyph for GID 0x%04x: %s", gid, ft_error_string(fterr)); return; } @@ -287,7 +316,7 @@ void TtfFont::PlotString(const std::string &str, data.u = u; data.v = v; data.beziers = sbl; - data.factor = 1.0f/(float)(1 << 16); + data.factor = 1.0 / capHeight; data.bx = bx; if(int fterr = FT_Outline_Decompose(&fontFace->glyph->outline, &outlineFuncs, &data)) { dbp("freetype: bezier decomposition failed (gid %d): %s", diff --git a/src/ttf.h b/src/ttf.h index fb26ab9..ec91127 100644 --- a/src/ttf.h +++ b/src/ttf.h @@ -14,6 +14,7 @@ public: std::string fontFile; std::string name; FT_FaceRec_ *fontFace; + double capHeight; std::string FontFileBaseName() const; bool LoadFromFile(FT_LibraryRec_ *fontLibrary, bool nameOnly = true); diff --git a/src/ui.h b/src/ui.h index ebb60b2..a041ed3 100644 --- a/src/ui.h +++ b/src/ui.h @@ -504,6 +504,9 @@ public: // allowing a paint in between. The extra solves are wasted if they're // not displayed. bool havePainted; + // Similarly, don't draw edges and outlines, since that's too slow + // for real-time dragging. + bool isDegraded; // Some state for the context menu. struct { diff --git a/src/util.cpp b/src/util.cpp index f1c50e4..847f378 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -61,6 +61,33 @@ bool SolveSpace::FilenameHasExtension(const std::string &str, const char *ext) return true; } +bool SolveSpace::ReadFile(const std::string &filename, std::string *data) +{ + FILE *f = ssfopen(filename.c_str(), "rb"); + if(f == NULL) + return false; + + fseek(f, 0, SEEK_END); + data->resize(ftell(f)); + fseek(f, 0, SEEK_SET); + fread(&(*data)[0], 1, data->size(), f); + fclose(f); + + return true; +} + +bool SolveSpace::WriteFile(const std::string &filename, const std::string &data) +{ + FILE *f = ssfopen(filename.c_str(), "wb"); + if(f == NULL) + return false; + + fwrite(&data[0], 1, data.size(), f); + fclose(f); + + return true; +} + void SolveSpace::MakeMatrix(double *mat, double a11, double a12, double a13, double a14, double a21, double a22, double a23, double a24, diff --git a/src/win32/w32main.cpp b/src/win32/w32main.cpp index f96ed81..562499b 100644 --- a/src/win32/w32main.cpp +++ b/src/win32/w32main.cpp @@ -56,6 +56,7 @@ SiHdl SpaceNavigator = SI_NO_HANDLE; HWND MessageWnd, OkButton; bool MessageDone; +int MessageWidth, MessageHeight; const char *MessageString; static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam, @@ -76,21 +77,13 @@ static LRESULT CALLBACK MessageProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); - int row = 0, col = 0, i; SelectObject(hdc, FixedFont); SetTextColor(hdc, 0x000000); SetBkMode(hdc, TRANSPARENT); - for(i = 0; MessageString[i]; i++) { - if(MessageString[i] == '\n') { - col = 0; - row++; - } else { - TextOutW(hdc, col*SS.TW.CHAR_WIDTH + 10, - row*SS.TW.LINE_HEIGHT + 10, - Widen(&(MessageString[i])).c_str(), 1); - col++; - } - } + RECT rc; + SetRect(&rc, 10, 10, MessageWidth, MessageHeight); + std::wstring text = Widen(MessageString); + DrawText(hdc, text.c_str(), text.length(), &rc, DT_LEFT | DT_WORDBREAK); EndPaint(hwnd, &ps); break; } @@ -147,6 +140,8 @@ void SolveSpace::DoMessageBox(const char *str, int rows, int cols, bool error) const char *title = error ? "SolveSpace - Error" : "SolveSpace - Message"; int width = cols*SS.TW.CHAR_WIDTH + 20, height = rows*SS.TW.LINE_HEIGHT + 60; + MessageWidth = width; + MessageHeight = height; MessageWnd = CreateWindowClient(0, L"MessageWnd", Widen(title).c_str(), WS_OVERLAPPED | WS_SYSMENU, r.left + 100, r.top + 100, width, height, NULL, NULL, Instance, NULL); diff --git a/src/win32/w32util.cpp b/src/win32/w32util.cpp index 20f3ec6..cba9c78 100644 --- a/src/win32/w32util.cpp +++ b/src/win32/w32util.cpp @@ -67,7 +67,7 @@ std::wstring Widen(const std::string &in) return out; } -FILE *ssfopen(const std::string &filename, const char *mode) +static std::string MakeUNCFilename(const std::string &filename) { // Prepend \\?\ UNC prefix unless already an UNC path. // We never try to fopen paths that are not absolute or @@ -76,9 +76,13 @@ FILE *ssfopen(const std::string &filename, const char *mode) std::string uncFilename = filename; if(uncFilename.substr(0, 2) != "\\\\") uncFilename = "\\\\?\\" + uncFilename; + return uncFilename; +} +FILE *ssfopen(const std::string &filename, const char *mode) +{ if(filename.length() != strlen(filename.c_str())) oops(); - return _wfopen(Widen(uncFilename).c_str(), Widen(mode).c_str()); + return _wfopen(Widen(MakeUNCFilename(filename)).c_str(), Widen(mode).c_str()); } void ssremove(const std::string &filename)