Commit Graph

100 Commits (3b241392d4ffa1a98a13f2552662de40d0171fdb)

Author SHA1 Message Date
whitequark 74cb1f589c Add two more points to the TTF text request.
These points can be used for constraining the width of the text
(or to the width of the text).

The main parts of the commit are:
  * TtfFont is restructured to be able to return the aspect ratio
    for a given string.
  * This aspect ratio is written to the savefile, such that even if
    the font is missing, the sketch would still be solved correctly.
  * The two additional points are constrained via perpendicularly
    to the two main points (which form a v vector).

The compatibility features are as follows:
  * When the font is missing in old files, 1:1 aspect ratio is used,
    which works for the replacement symbol anyhow.
  * When the two additional points are missing in old files, their
    would-be positions are calculated and they are moved there,
    avoiding 'jumping' of underconstrained sketches.
2016-11-02 09:22:18 +00:00
EvilSpirit 3a585ea7c2 Try to re-solve groups that fail rank test.
Sometimes, after a large change in a sketch, constraints that are
geometrically fine may still cause the rank test to fail. One way
this can happen is VectorsParallel() pivoting wrong due to the big
move, converging anyways but ending up singular. It would then
re-pivot correctly on the new solution when you re-solve, making
this a transient error. This is visible when dragging the arm in
the jansen-asm.slvs example.

After this commit, if the rank test fails, equations are regenerated
the Jacobian is rewritten, and the rank test is retried, which
prevents these transient errors from interfering with dragging.

The problem described above was invisible before c011444, as rank
test was only performed before solving.
2016-10-14 00:27:38 +00:00
EvilSpirit f4e85127d6 Wavefront OBJ: export mesh color as well. 2016-10-11 14:54:19 +00:00
whitequark d12bf047b4 Update 58db06d8 to not even try to use std::fstream with Unicode paths.
Unfortunately there is no portable way to open an Unicode path with
std::fstream. On *nix, it is enough to call the const char*
constructor. On MSVC, it is enough to call a nonstandard
const wchar_t* constructor. However, on MinGW, there is no way at all
to construct an std::fstream with a wide path, not even using
undocumented APIs. (There used to be a const wchar_t* overload added
back in libstdc++ 4.7, but it got removed for a reason that I was not
able to find out.)
2016-10-09 20:00:02 +00:00
whitequark 58db06d845 DXF: update to use Unicode-aware file open routines on Windows. 2016-10-09 15:19:36 +00:00
whitequark 8e7d2eaa84 Implement "view → set to full scale" text window command. 2016-08-01 14:03:16 +00:00
whitequark 2fdbabc13c Add statement/condition coverage measurement for the test suite.
We're using gcov+lcov, since these tools appear to be the only
usable ones that use the SC/CC metric; and measuring just the line
coverage would be practically criminal negligence.

gcov only works with GCC and Clang, and MSVC's own coverage
measurement tools are not up to the task; so MSVC is out of luck.
2016-08-01 02:19:06 +00:00
whitequark 5e63d8301e Add a simple harness for automated, headless testing.
This commit alters the build system substantially; it adds another
platform, `headless`, that provides stubs in place of all GUI
functions, and provides a library `solvespace_headless` alongside
the main executable. To cut down build times, only the few files
that have #if defined(HEADLESS) are built twice for the executable
and the library; the rest is grouped into a new `solvespace_cad`
library. It is not usable on its own and just serves for grouping.

This commit also gates the tests behind a -DENABLE_TESTS=ON CMake
option, ON by default (but suggested as OFF in the README so that
people don't ever have to install cairo to build the executable.)

The tests introduced in this commit are (so far) rudimentary,
although functional, and they serve as a stepping point towards
introducing coverage analysis.
2016-08-01 00:48:37 +00:00
whitequark 977a0b8e6d Replace the last use of exceptions (in Expr) with setjmp/longjmp.
Without -fno-exceptions, the branch coverage information is
practically useless, as every call becomes a branch.

The functionality of Expr is retained as-is, although SjLj error
handling is a maintenance nightmare. However, the entire parser
probably should be eventually replaced, so for now it is not
a great concern.
2016-08-01 00:48:37 +00:00
whitequark 65e2cccde0 Add a Cairo rendering backend.
This backend will be used for reproducible offscreen rendering
in integration tests.
2016-08-01 00:48:37 +00:00
whitequark 8960ee365a Add a new renderer that prepares geometry for 2d backends.
SurfaceRenderer is a new renderer implementing the Canvas interface
running entirely on the CPU; it projects strokes and triangles
in the exact same way as OpenGL would, and it can be used for
rendering into raster or vector 2d surfaces.
2016-08-01 00:48:37 +00:00
EvilSpirit 7f411d1593 Unify displayEdges and displayOutlines.
This has the following benefits:
  * Less geometry to generate; we can do both in one pass;
  * Less geometry to draw;
  * Eliminate overdraw of outlines on top of emphasized edges;
  * In future, being able to seamlessly stitch stippled lines.

The contour edges are now also drawn before emphasized edges;
this makes intersections of contour and emphasized edges look better
as the thinner emphasized edge doesn't clobber the depth buffer.
2016-07-23 22:41:16 +00:00
whitequark e7c8c1c8f2 Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
  * It is now possible to port SolveSpace to a later version of
    OpenGL, such as OpenGLES 2, so that it runs on platforms that
    only have that OpenGL version;
  * The majority of geometry is now rendered without references to
    the camera in C++ code, so a renderer can now submit it to
    the video card once and re-rasterize with a different projection
    matrix every time the projection is changed, avoiding expensive
    reuploads;
  * The DOGD (draw or get distance) interface is now
    a straightforward Canvas implementation;
  * There are no more direct references to SS.GW.(projection)
    in sketch rendering code, which allows rendering to multiple
    viewports;
  * There are no more unnecessary framebuffer flips on CPU on Cocoa
    and GTK;
  * The platform-dependent GL code is now confined to rendergl1.cpp.
  * The Microsoft and Apple headers required by it that are prone to
    identifier conflicts are no longer included globally;
  * The rendergl1.cpp implementation can now be omitted from
    compilation to run SolveSpace headless or with a different
    OpenGL version.

Note these implementation details of Canvas:
  * GetCamera currently always returns a reference to the field
    `Camera camera;`. This is so that a future renderer that caches
    geometry in the video memory can define it as asserting, which
    would provide assurance against code that could accidentally
    put something projection-dependent in the cache;
  * Line and triangle rendering is specified through a level of
    indirection, hStroke and hFill. This is so that a future renderer
    that batches geometry could cheaply group identical styles.
  * DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
    This is so that a future renderer into an output format that
    uses 2d transforms (e.g. SVG) could easily derive those.

Some additional internal changes were required to enable this:
  * Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
    This is so that the renderer could cache uploaded textures
    between API calls, which requires it to capture a (weak)
    reference.
  * The PlatformPathEqual function was properly extracted into
    platform-specific code. This is so that the <windows.h> header
    could be included only where needed (in platform/w32* as well
    as rendergl1.cpp).
  * The SBsp{2,3}::DebugDraw functions were removed. They can be
    rewritten using the Canvas API if they are ever needed.

While no visual changes were originally intended, some minor fixes
happened anyway:
  * The "emphasis" yellow line from top-left corner is now correctly
    rendered much wider.
  * The marquee rectangle is now pixel grid aligned.
  * The hidden entities now do not clobber the depth buffer, removing
    some minor artifacts.
  * The workplane "tab" now scales with the font used to render
    the workplane name.
  * The workplane name font is now taken from the normals style.
  * Workplane and constraint line stipple is insignificantly
    different. This is so that it can reuse the existing stipple
    codepaths; rendering of workplanes and constraints predates
    those.

Some debug functionality was added:
  * In graphics window, an fps counter that becomes red when
    rendering under 60fps is drawn.
2016-07-23 22:31:18 +00:00
whitequark b0d37c1e78 Replace platform-specific GetMilliseconds using std::chrono. 2016-07-21 06:07:46 +00:00
EvilSpirit 5791310bb1 Annotate constants passed as boolean function arguments.
This is to ensure that:
  * it is clear, when looking at the point of usage, what is
    the purpose of "true" or "false";
  * when refactoring, a simple search will bring up any places that
    need to be changed.

Also, argument names were synchronized between declaration and
implementation.

As an exception, these are not annotated:
  * Printf(/*halfLine=*/), to avoid pointless churn.
2016-05-26 12:43:52 +00:00
EvilSpirit f33ddc94fb Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:

  class Foo {
    enum { X = 1, Y = 2 };
    int kind;
  }
  ... foo.kind = Foo::X; ...

and convert it to this:

  class Foo {
    enum class Kind : uint32_t { X = 1, Y = 2 };
    Kind kind;
  }
  ... foo.kind = Foo::Kind::X;

(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)

The benefits are as follows:
  * The type of the field gives a clear indication of intent, both
    to humans and tools (such as binding generators).
  * The compiler is able to automatically warn when a switch is not
    exhaustive; but this is currently suppressed by the
      default: ssassert(false, ...)
    idiom.
  * Integers and plain enums are weakly type checked: they implicitly
    convert into each other. This can hide bugs where type conversion
    is performed but not intended. Enum classes are strongly type
    checked.
  * Plain enums pollute parent namespaces; enum classes do not.
    Almost every defined enum we have already has a kind of ad-hoc
    namespacing via `NAMESPACE_`, which is now explicit.
  * Plain enums do not have a well-defined ABI size, which is
    important for bindings. Enum classes can have it, if specified.
    We specify the base type for all enums as uint32_t, which is
    a safe choice and allows us to not change the numeric values
    of any variants.

This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-25 07:17:14 +00:00
whitequark 7bda30aca4 Refactor SS.bgImage to use Pixmap. 2016-05-25 03:22:54 +00:00
whitequark 20d87d93c5 Add const qualifiers to functions where trivially possible.
This will allow us in future to accept `const T &` anywhere it's
necessary to reduce the amount of copying.

This commit is quite conservative: it does not attempt very hard to
refactor code that performs incidental mutation. In particular
dogd and caches are not marked with the `mutable` keyword.
dogd will be eliminated later, opening up more opportunities to
add const qualifiers.

This commit also doesn't introduce any uses of the newly added const
qualifers. This will be done later.
2016-05-25 03:22:54 +00:00
EvilSpirit bbca4cc224 Rewrite declarations of form f(void) as f().
In C++ there is no difference and newly added functions are all
declared as f(), so this brings back consistency.
2016-05-20 12:43:20 +00:00
whitequark ad4a204edf Replace all oops() checks with ssassert()s.
This includes explanation and context for non-obvious cases and
shortens debug cycles when just-in-time debugging is not available
(like on Linux) by immediately printing description of the assert
as well as symbolized backtrace.
2016-05-20 12:38:30 +00:00
whitequark 4415f5bb91 Implement ssassert(), a replacement for oops(). 2016-05-20 12:38:29 +00:00
whitequark 1b52c46b81 Remove some dead code. 2016-05-18 23:00:34 +00:00
whitequark ab418b827e Use the `override` C++ keyword everywhere.
This helps to ensure that a base class that changes underneath us
would not leave any overridden functions hanging.

This already highlighted some questionable use of GTKMM's API,
which were also fixed in this commit.
2016-05-18 18:42:33 +00:00
whitequark 645c2d90ac Move bitmap font to res/fonts/; remove unifont2c.
This commit integrates the bitmap font in the resource system, so
that cross-compilation would be easier.

The font handling code was carefully written to do glyph parsing
lazily; in practice this means that after this commit, startup
is less than 25ms slower, most of it spent in inflate().

This should also result in faster rendering, since there is no
rampant plane switching anymore; instead, all characters that are
actually used are stashed into same one texture.
2016-05-18 11:24:24 +00:00
whitequark a525f03371 Move icons to res/icons/; remove png2c.
This commit integrates icons in the resource system so that they
can be loaded (or reloaded, without restarting) in @2x mode, which
will be added in a future commit. png2c is no longer necessary.

png2c used to perform the following transformation:
  if(r + g + b < 11) r = g = b = 11;

This is now achieved by switching the icons to RGBA mode and adding
alpha channel with the following imagemagick invocation, which is
equivalent to the transformation above:
  for i in *.png; do
    convert -fuzz 4% -channel rgba -matte \
            -fill "rgba(255,255,255,0)" -opaque black \
            $i $i
  done

The Debian package solvespace now includes /usr/share/solvespace;
this should be split out into solvespace-data later.
2016-05-18 11:24:24 +00:00
whitequark f4c01f670c Implement a resource system.
Currently, icons, fonts, etc are converted to C structures at compile
time and are hardcoded to the binary. This presents several problems:

  * Cross-compilation is complicated. Right now, it is necessary
    to be able to run executables for the target platform; this
    happens to work with wine-binfmt installed, but is rather ugly.

  * Icons can only have one resolution. On OS X, modern software is
    expected to take advantage of high-DPI ("Retina") screens and
    use so-called @2x assets when ran in high-DPI mode.

  * Localization is complicated. Win32 and OS X provide built-in
    support for loading the resource appropriate for the user's
    locale.

  * Embedding strings can only be done as raw strings, using C++'s
    R"(...)" literals. This precludes embedding sizable strings,
    e.g. JavaScript libraries as used in Three.js export, and makes
    git history less useful. Not embedding the libraries means we
    have to rely on external CDNs, which requires an Internet
    connection and adds a glaring point of failure.

  * Linux distribution guidelines are violated. All architecture-
    independent data, especially large data such as fonts, is
    expected to be in /usr/share, not in the binary.

  * Customization is impossible without recompilation. Minor
    modifications like adding a few missing vector font characters
    or adjusting localization require a complete development
    environment, which is unreasonable to expect from users of
    a mechanical CAD.

As such, this commit adds a resource system that bundles (and
sometimes builds) resources with the executable. Where they go is
platform-dependent:

  * on Win32: into resources of the executable, which allows us to
    keep distributing one file;
  * on OS X: into the app bundle;
  * on other *nix: into /usr/share/solvespace/ or ../res/ (relative
    to the executable path), the latter allowing us to run freshly
    built executables without installation.

It also subsides the platform-specific resources that are in src/.

The resource system is not yet used for anything; this will be added
in later commits.
2016-05-18 11:24:23 +00:00
whitequark e969bc94ad Enable -Wall -Wextra -Wno-unused-parameter on GCC/Clang.
This is good practice and helps to catch bugs. Several changes
were made to accomodate the newly enabled warnings:
  * -Wunused-function:
    * in exposed/, static functions that were supposed to be inlined
      were explicitly marked as inline;
    * some actually unused functions were removed;
  * -Wsign-compare: explicit conversions were added, and in
    the future we should find a nicer way than aux* fields;
  * -Wmissing-field-initializers: added initializers;
  * -Wreorder: reordered properly;
  * -Wunused-but-set-variable: remove variable.

-Wunused-parameter was turned off as enabling it would result in
massive amount of churn in UI code. Despite that, we should enable
it at some point as it has a fairly high SNR otherwise.
2016-05-08 00:01:35 +00:00
whitequark febe0f5282 Rename the old "Import / Assemble" feature to "Link / Assemble".
This better reflects what it does and avoids clashes with the new
DXF import feature.
2016-05-07 05:27:54 +00:00
whitequark d05e9a938b DWG: implement import.
Before this commit, the file filter suggested that DWG was readable,
but it wasn't.

Also, report any failures while reading DWG and DXF files.
2016-05-07 05:17:23 +00:00
EvilSpirit 70d84b30e8 DXF: implement import. 2016-05-07 04:02:34 +00:00
EvilSpirit e1f614101f Only generate split triangles when exporting if needed.
Before this commit, when exporting a vector file without the shaded
model shown, or similarly when using formats that we do not export
the mesh to, we still generate (and then discard) the mesh in paint
order. This is a waste of time.
2016-05-04 04:48:24 +00:00
whitequark e61bac2797 Refactor file filters to not use preprocessor magic.
The immediate reason for refactoring this was that the GTK port broke
after 52af7256 since config.h is not included anymore, but it was
a fragile piece of code I will shed no tears for.

While we're at it, get rid of the mutable std::string &file to be
consistent with our conventions.
2016-05-04 03:21:12 +00:00
whitequark 52af725606 Only #include "config.h" when we need something from it.
config.h now includes the git hash and so, as long as it's included
in solvespace.h, any change of git HEAD will trigger a complete
recompilation, which makes bisecting especially annoying.

While we're at it, remove HAVE_STDINT_H from it, since we require
C++11 and all MSVC versions that include C++11 also include stdint.h.
2016-04-23 23:06:31 +00:00
EvilSpirit 1c51205a11 DXF: reassemble piecewise linear fragments into polylines. 2016-04-23 19:39:39 +00:00
EvilSpirit dabd57847e MSVC: work around binary size explosion. 2016-04-23 19:39:39 +00:00
whitequark a61544ea9c Fix empty space at the end of the tooltips.
Also, bring MakeAcceleratorLabel to modernity.
2016-04-23 04:38:32 +00:00
whitequark 23dc36da9b Make graphics window edit control width fit the content.
Before this commit, the graphics window edit control always had
a width of 30 average character widths.

After this commit, the edit control has a width of 5 average
character widths (for numeric constraints) or 30 average character
widths (for comment constraints), or just enough to display
the entire value being edited, whichever is greater.

This makes the edit control overlap the sketch less in case of
editing numeric constraints (since in most cases, the numbers being
edited are short), and removes annoying scrolling in case of editing
long comments.
2016-04-16 03:10:56 +00:00
whitequark d17771064a Ensure edit control font size matches font size of text being edited.
Before this commit, the position of the edit box was adjusted
by trial and error, as far as I can tell. This commit changes
the positioning machinery for edit controls as follows:

The coordinates passed to ShowTextEditControl/ShowGraphicsEditControl
now denote: X the left bound, and Y the baseline.

The font height passed to ShowGraphicsEditControl denotes
the absolute font height in pixels, i.e. ascent plus descent.

Platform-dependent code uses these coordinates, the font metrics
for the font appropriate for the platform, and the knowledge of
the decorations drawn around the text by the native edit control
to position the edit control in a way that overlays the text inside
the edit control with the rendered text.

On OS X, GNU Unifont (of height 16) has metrics identical to
Monaco (of height 15) and so as an exception, the edit control
is nudged slightly for a pixel-perfect fit.

Also, since the built-in vector font is proportional, this commit
also switches the edit control font to proportional when editing
constraints.
2016-04-15 21:53:08 +00:00
whitequark 0f304b4c64 Rigorously treat font scale factors.
The old values were chosen without a good understanding of font
metrics.
2016-04-15 21:53:08 +00:00
EvilSpirit 24fc65a71c Allow rendering solid outlines using a distinct style.
A new button is added, "Show/hide outline of solid model".

When the outline is hidden, it is rendered using the "solid edge"
style. When the outline is shown, it is rendered using the "outline"
style.

In SolveSpace's true WYSIWYG tradition, the 2d view export follows
the rendered view exactly.

Moreover, shell edges are not rendered anymore, since there is not
much need in them anymore and not drawing them lessens the overlap
between various kinds of lines, which already includes entities,
solid edges and outlines.
2016-04-15 21:53:08 +00:00
EvilSpirit d1a2eb6d18 Allow rendering hidden solid edges using a distinct style.
Before this change, the two buttons "Show/hide shaded model" (S) and
"Show/hide hidden lines" (H) resulted in drawing the following
elements in the following styles:

  Button | Non-occluded | Non-occluded |  Occluded   |   Occluded
  state  | solid edges  |   entities   | solid edges |   entities
 --------+--------------+--------------+-------------+--------------
  !S !H  |              |              | solid-edge  | entity style
 --------+              |              +-------------+--------------
   S !H  |              |              |         invisible
 --------+  solid-edge  | entity style +-------------+--------------
  !S  H  |              |              |             |
 --------+              |              | solid-edge  | entity style
   S  H  |              |              |             |
 --------+--------------+--------------+-------------+--------------

After this change, they are drawn as follows:

  Button | Non-occluded | Non-occluded |  Occluded   |   Occluded
  state  | solid edges  |   entities   | solid edges |   entities
 --------+--------------+--------------+-------------+--------------
  !S !H  |              |              | solid-edge  | entity style
 --------+              |              +-------------+--------------
   S !H  |              |              |         invisible
 --------+  solid-edge  | entity style +-------------+--------------
  !S  H  |              |              |             |
 --------+              |              | hidden-edge |  stippled¹
   S  H  |              |              |             |
 --------+--------------+--------------+-------------+--------------

  ¹ entity style, but the stipple parameters taken from hidden-edge

In SolveSpace's true WYSIWYG tradition, the 2d view export follows
the rendered view exactly.

Also, it is now possible to edit the stipple parameters of built-in
styles, so that by changing the hidden-edge style to non-stippled
it is possible to regain the old behavior.
2016-04-15 21:53:08 +00:00
whitequark 2d25bdb51f When choosing color for a new group, consider active, not last, group. 2016-04-15 06:11:03 +00:00
whitequark 11565e081d Refactor export code to pass around hStyle, not uint32_t. 2016-04-14 18:54:09 +00:00
EvilSpirit 27b403faf5 DXF: refactor. 2016-04-14 18:54:09 +00:00
EvilSpirit 94cba11f2a PDF, EPS: export stippled lines. 2016-04-08 11:32:16 +00:00
EvilSpirit 55e3162a05 When creating a new group, use the color of last requested solid. 2016-04-08 11:21:40 +00:00
EvilSpirit e19a2f4f35 Accept maybeFat in ssglStippledLine. 2016-04-08 10:55:11 +00:00
EvilSpirit e17a24814b DXF: only export visible constraints. 2016-04-08 10:15:29 +00:00
EvilSpirit 96344c85a6 Eliminate DEFAULT_TEXT_HEIGHT from drawing code.
Instead, query the text height for constraint style.
2016-03-05 12:02:13 +00:00
EvilSpirit 1170a91875 Implement stippled line styles from ISO 128.
Now it's possible to use a styled line to indicate e.g.
a centerline.
2016-03-05 12:02:13 +00:00