Commit Graph

40 Commits (803665404e3fbd937f3fcd88a1c363496b4baa11)

Author SHA1 Message Date
whitequark 6846010416 Fix a flip bug in ReadPngIntoPixmap.
The only user of that was the background image, and it was flipped
again when it was rendered, so the two bugs masked out each other.
This adds a `bool flip` to ReadPng and FromPng, since that's cheap
to do when writing the PNG file, expensive on the pixel arrays,
and sometimes inconvenient in OpenGL due to offsets.
2016-07-25 10:58:03 +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
EvilSpirit 5a2eb9fb50 Allow changing stipple width for default styles.
We already allow changing stipple style, so it makes sense to do
the same for width.
2016-06-30 16:39:27 +00:00
EvilSpirit d0a0a0f8cf Use the same line width for hidden and shown edges, by default. 2016-06-30 16:21:55 +00:00
whitequark faa84c61cf Add SHORT_DASH stipple pattern. 2016-05-27 11:41:17 +00:00
EvilSpirit 73d82a6347 Load actual factory default, not saved style, when requested. 2016-05-26 15:49:46 +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
EvilSpirit 70d84b30e8 DXF: implement import. 2016-05-07 04:02:34 +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 6b123f2d34 Refactor Style::LoadFactoryDefaults.
This also fixes a bug where the hidden-edge style would be reset
to continuous when factory defaults are loaded.
2016-04-16 05:49:37 +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
EvilSpirit 7c60be8203 Remove overlapping line segments when exporting a 2d view.
This adds a new style attribute, "Z-index", which is not currently
displayed and cannot be modified. It may be exposed in the UI later.
2016-04-15 21:53:08 +00:00
EvilSpirit 73f28b9731 Make normals and workplanes non-stylable.
This does not seem to have any useful application, and it can
result in odd misrenderings with some styles.
2016-04-08 10:12:28 +00:00
EvilSpirit a0576e2a50 Allow changing text size for default styles.
This is especially useful for High-DPI displays on non-OS X.
2016-03-05 12:02:13 +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
EvilSpirit 171f208cfb Extract Style::FillDefaultStyle. 2016-03-04 15:13:09 +00:00
whitequark 5c15cbf5f6 Remove extraneous instances of .c_str().
Most of these were just converting char* into std::string back and
forth; some more used ReadUTF8, which was converted to use nicer
STL-style iterators over UTF-8 text.

The remaining ones are:
  * arguments to Expr::From, which we'll change when refactoring
    the expression lexer;
  * arguments to varargs functions, which we'll change when adding
    localization (that requires custom printf-style functions to
    allow for changing argument order);
  * arguments where only string literals are ever passed, which
    are OK;
  * in platform-specific code, which is OK.
2016-02-19 10:22:53 +00:00
whitequark 8c83a4a212 Use size_t for indexing where appropriate.
MSVC (rightly) complains about this.
2016-02-12 05:26:26 +00:00
EvilSpirit 76d582720a Don't calculate halfRow for ShowEditControl manually.
Instead, grab it from hoveredRow, since almost always (with only one
exception) this is where the edit control has to be shown.

This makes it much easier to adjust views, e.g. add a new editable
field in the middle of configuration view, because it's not necessary
to manually change and test all the indexes below the row being
changed.

Additionally, it removes a lot of awkward and opaque row calculations.
2016-01-27 09:09:18 +00:00
EvilSpirit fd0b7fbc29 Update remaining sprintf calls with a stack buffer to use ssprintf.
The commit 11f29b123 has replaced most of the uses of sprintf,
but there were still many remaining in Screen* functions, and it
was annoyingly inconsistent. Moreover, while most usage of sprintf
there was fine, it is bad hygiene to leave stack overflow prone
code around.
2016-01-27 09:09:18 +00:00
whitequark 750842610c Simplify file saving code.
There is no need to record default file format choice, as
the first one is selected when an empty string is passed.
2016-01-13 06:45:17 +00:00
whitequark 11f29b1231 Replace NameStr with std::string.
This removes the arbitrary 64 byte restriction (which effectively
limits us to as little as 16 Unicode characters with CJK encodings),
makes classes smaller, and is easier to use.

As a consequence of making the length of all ex-NameStr fields
unbounded, all functions that returned a buffer derived from those
were changed to return std::string. Then, functions that are
contextually similar to the ones described above were changed
to return std::string. Then, functions that now happened to mostly
take an std::string argument converted to a C string were changed
to accept std::string.

This has produced a bit of churn, but is probably for the better.
2016-01-13 06:45:17 +00:00
whitequark 9d2a035a71 Rasterize non-ASCII glyphs in the UI.
Now it is possible to give non-ASCII names to groups
as well as see non-ASCII filenames of imported files.
In the future this makes localization possible.

This works for LTR languages, such as European and CJK,
but not RTL such as Arabic. Does Arabic even exist in
monospaced form? I have no idea.
2016-01-13 06:45:16 +00:00
whitequark ba10a75a7d Use Unicode-aware fopen and remove on Windows.
After this commit, SolveSpace can robustly handle non-ASCII filenames
on every OS. Additionally, on Windows, filenames longer than 260
characeters can be used, and files on network shares can be opened
directly, without mounting them as a network drive.
2016-01-13 06:45:16 +00:00
whitequark 32383d22bf Rewrite all path handling with std::string.
What do we gain from this? Several things.

 * First, usage of PATH_MAX (the POSIX constant) is eliminated.
   PATH_MAX is actually a lie; Linux and OS X (and probably other BSDs
   too) do not have an actual path length limit. Linux claims 4096,
   OS X claims 1024, but it is trivial to construct paths that are
   longer.

 * Second, while Windows does enforce a limit of MAX_PATH (the Win32
   constant) for its ASCII functions, the Unicode variants, when
   used with UNC paths, do not have this restriction.
   The capability to use UNC paths is useful by itself, as it allows
   to access files on network shares directly.

 * Third, representing paths as std::string will make it easier to
   interoperate with *W WinAPI functions later.
2016-01-13 06:45:16 +00:00
whitequark 45f056c852 Replace all ZERO and memset with C++11 brace-initialization.
This will allow us to use non-POD classes inside these objects
in future and is otherwise functionally equivalent, as well
as more concise.

Note that there are some subtleties with handling of
brace-initialization. Specifically:

On aggregates (e.g. simple C-style structures) using an empty
brace-initializer zero-initializes the aggregate, i.e. it makes
all members zero.

On non-aggregates an empty brace-initializer calls the default
constructor. And if the constructor doesn't explicitly initialize
the members (which the auto-generated constructor doesn't) then
the members will be constructed but otherwise uninitialized.

So, what is an aggregate class? To quote the C++ standard
(C++03 8.5.1 §1):

An aggregate is an array or a class (clause 9) with no
user-declared constructors (12.1), no private or protected
non-static data members (clause 11), no base classes (clause 10),
and no virtual functions (10.3).

In SolveSpace, we only have to handle the case of base classes;
Constraint and Entity have those. Thus, they had to gain a default
constructor that does nothing but initializes the members to zero.
2016-01-13 06:45:16 +00:00
whitequark 28166e6200 Use C++ std::{min,max,swap} instead of custom ones.
The main benefit is that std::swap will ensure that the type
of arguments is copy-constructible and move-constructible.
It is more concise as well.

When min and max are defined as macros, they will conflict
with STL header files included by other C++ libraries;
in this case STL will #undef any other definition.
2015-12-28 21:37:06 +08:00
whitequark 5e7c7fce7e Rename RgbColor to RgbaColor. 2015-07-10 15:59:12 +03:00
whitequark 75a3936b64 Add support for transparent solids.
Some extra code is necessary to determine that the back faces
should not be drawn in red for transparent solids. It is expected
that the user will first ensure that the shell is watertight
and then set the opacity; back faces are still drawn if
the opacity is exactly 1.

The savefile format is changed backwards-compatibly by stashing
the alpha value in uppermost byte of 4-byte hex color value
in Surface and Triangle clauses. The existing files have 00
in the high byte, so RgbColor::FromPackedInt treats that
as "opaque".
2015-07-10 15:59:12 +03:00
whitequark 2c39f259db Add a GTK2/3 port.
In principle, GTK3 is the way forward, and GTK2 is officially
deprecated, though still maintained. In practice however, GTK3
is often unbearably buggy; e.g. on my system, combo boxes
don't ever roll up in GTK3 windows. So I have added support
for both.

This required a few minor changes to the core, namely:
  * GTK wants to know beforehand whether a menu item is a check
    menu item or a regular one.
  * GTK doesn't give us an easy way to execute something after
    any event is processed, so an explicit idle timer is added.
    This is a no-op on Win32.
  * A few function signatures were const'ed, since GTK expects
    immutable strings when converting to Glib::ustring.
2015-07-10 15:59:12 +03:00
whitequark c5364fe7a8 Trim trailing whitespace. 2015-07-10 15:59:11 +03:00
whitequark 14690e6e42 Work around poor line rendering with Intel Mesa-based drivers.
However, don't use ssglLineWidth for UI drawing operations.
These only draw horizontal or vertical lines that don't need to
be antialiased, and thus don't require the workaround. In fact
the workaround would make them thicker than needed.
2015-07-05 06:20:25 +03:00
Daniel Richard G 1bc73c4a75 Renamed the RGB() macro to RGBi() to avoid collisions with Microsoft
Microsoft defines an RGB() macro that at one point was compatible with our
version (returning a packed integer containing 8-bit red, green and blue
channels), but is no longer, and the incompatibility led to an awkward
situation in w32main.cpp where we had to restore Microsoft's form of the
macro in order for the commctrl.h header to compile. By renaming the macro
to RGBi()---analogous to the RGBf() macro we already define---we avoid the
hassle entirely.
2013-12-02 04:27:34 -05:00
Daniel Richard G 0a24cf40f0 Moved most of the source into a src/ subdirectory
The SolveSpace top-level directory was getting a bit cluttered, so
following the example of numerous other free-software projects, we move the
main application source into a subdirectory and adjust the build systems
accordingly.

Also, got rid of the obj/ directory in favor of creating it on the fly in
Makefile.msvc.
2013-11-19 18:17:32 -05:00