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.
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.
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.
This commit makes common external packages always be included through
find_package to eliminate differences in variables set, wraps
find_package for vendored libraries on Windows to factor out common
code, and removes miscellaneous useless code elsewhere in dependency
handling.
This also fixes a problem where pkg-config would pick up `build`
libraries instead of `host` when cross-compiling.
It was never really needed, since both Linux and OS X, where
GlOffscreen is used, guarantee that the API we need is present,
on all OS versions we're interested in.
Also, reorganize GlOffscreen consistently with the rest of our
codebase, and don't use RAII for OpenGL resource management because
of its requirement for an active context.
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.
This commit integrates the vector font in the resource system, so
that cross-compilation would be easier and a custom font could be
used without recompilation.
The font handling code was carefully written to lazily load glyphs;
as possible; in practice this means that startup is less than 15ms
slower after this commit, most of it spent in inflate().
This also reduces executable size and makes compilation of
glhelper.cpp much faster.
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.
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.
Without resources, it makes no sense anymore to keep these in
separate subdirectories: unixutil* is shared between Cocoa
and GTK ports, and gloffscreen* should be shared between all ports
(but it's still platform-specific).
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.
We had to fork libdxfrw since the upstream doesn't have a git
repository, a CMake buildsystem, and is quite buggy.
libdxfrw is also used in LibreCAD, but they just vendored
their version.
CMake can properly quote inputs to custom commands itself; this is
governed by the VERBATIM flag. If we pass this flag, no quoting
needs to be done except for compiler/linker flags and diagnostic
messages, as CMake doesn't treat whitespace expanded from variables
the same way it treats whitespace that separates arguments.
This font is less complete than our bitmap font, Unifont: Unifont
has essentially complete Unicode coverage and LibreCAD's font only
has Latin, Cyrillic and Japanese, but it can be extended rather
easily, so this should be fine for now.
These embedded fonts fatten glhelper.o quite a bit:
bitmapfont.table.h is about 8M in gzip-compressed bitmaps and
vectorfont.table.h is about 2M in raw vector data.
In spite of that it takes just around five seconds to build
glhelper.c on my laptop, so it should be fine.
The final executable grows from about 2M to about 8M, but this
is a small price to pay for fairly extensive i18n support.
The new font has somewhat different metrics, so the rendering
code has been fudged to make it look good.
We are going to use freetype instead of the old custom TTF parser,
since the old parser has many annoying bugs when handling non-Latin
fonts and fixing it is not really worth the time.
On Windows, Freetype is built from a submodule.
On Linux and OS X, Freetype is provided together with the desktop,
though development files have to be installed separately.
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.
On Windows, freeze.{cpp,h} was factored into w32main.cpp.
The old implementation was too redundant and leaked registry
key handles.
On all platforms, Cnf* functions now use std::string.
This simplifies code everywhere, but will be particularly useful
when the Windows port switches to the *W WinAPI functions.
After this change, SolveSpace does not contain nonfree assets.
Additionally, Perl is not required for the build.
Note that in the US, case law suggests that copyright does
not apply to bitmap fonts:
http://www.renpy.org/wiki/renpy/misc/Bitmap_Fonts_and_Copyright
Nevertheless, it was prudent to replace the asset with something
that is unambiguously free.
As a side effect, zlib and libpng are now git submodules,
based on their respective official git repositories.
This is necessary, because MinGW has a different ABI and
it cannot use the prebuilt binaries built by MSVC.
The submodules are also used for Windows, for several reasons:
* to allow 64-bit builds;
* to allow using newer MSVC, which doesn't like the prebuilt
libraries;
* to keep the libraries updated.
Apparently pbuffers are also a deprecated and unportable
way of offscreen rendering. They're not supported by
Chromium OpenGL implementation, which is what 3D-accelerated
VirtualBox uses.
This would also help a future OS X 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.
fltkutil.cpp should be independent of FLTK so that it can be linked
into libslvs while neither requiring every user of the library to
reimplement these support routines nor requiring linking in FLTK.