Merge commit '81396a5322a7a48764fcf254d5d933ba1e57bdc5' as 'kiwi'
This commit is contained in:
4
kiwi/docs/source/api/cpp.rst
Normal file
4
kiwi/docs/source/api/cpp.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
Kiwisolver C++ API
|
||||
==================
|
||||
|
||||
Under construction
|
||||
8
kiwi/docs/source/api/index.rst
Normal file
8
kiwi/docs/source/api/index.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
kiwisolver
|
||||
==========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Python API <python.rst>
|
||||
C++ API <cpp.rst>
|
||||
7
kiwi/docs/source/api/python.rst
Normal file
7
kiwi/docs/source/api/python.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
Kiwisolver Python API
|
||||
=====================
|
||||
|
||||
.. automodule:: kiwisolver
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
213
kiwi/docs/source/basis/basic_systems.rst
Normal file
213
kiwi/docs/source/basis/basic_systems.rst
Normal file
@@ -0,0 +1,213 @@
|
||||
.. _basis-basic-systems:
|
||||
|
||||
Constraints definition and system solving
|
||||
=========================================
|
||||
|
||||
.. include:: ../substitutions.sub
|
||||
|
||||
A system within Kiwi is defined by a set of constraints, which may
|
||||
be either equalities or inequalities (limited to >= and <=, as strict inequalities
|
||||
are not supported). Each constraint can be assigned a specific 'strength',
|
||||
indicating its relative importance in the problem-solving process. The subsequent
|
||||
sections will delve into the methods of defining these constraints and extracting
|
||||
results from the solver.
|
||||
|
||||
Defining variables and constraints
|
||||
----------------------------------
|
||||
|
||||
The initial step involves defining variables, which represent
|
||||
the values that the solver aims to determine. These variables are
|
||||
encapsulated by |Variable| objects. The creation of these objects
|
||||
can be accomplished as follows:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
from kiwisolver import Variable
|
||||
|
||||
x1 = Variable('x1')
|
||||
x2 = Variable('x2')
|
||||
xm = Variable('xm')
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
#include <kiwi/kiwi.h>
|
||||
|
||||
using namespace kiwi
|
||||
|
||||
Variable x1("x1");
|
||||
Variable x2("x2");
|
||||
Variable xm("xm");
|
||||
|
||||
.. note::
|
||||
|
||||
Naming your variables is not mandatory but it is recommended since it will
|
||||
help the solver in providing more meaningful error messages.
|
||||
|
||||
Now that we have some variables we can define our constraints.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
constraints = [x1 >= 0, x2 <= 100, x2 >= x1 + 10, xm == (x1 + x2) / 2]
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
Constraint constraints[] = { Constraint {x1 >= 0},
|
||||
Constraint {x2 <= 100},
|
||||
Constraint {x2 >= x1 + 20},
|
||||
Constraint {xm == (x1 + x2) / 2}
|
||||
};
|
||||
|
||||
Next, add these variables to the solver, an instance of |Solver|:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
from kiwisolver import Solver
|
||||
|
||||
solver = Solver()
|
||||
|
||||
for cn in constraints:
|
||||
solver.addConstraint(cn)
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
Solver solver;
|
||||
|
||||
for(auto& constraint : constraints)
|
||||
{
|
||||
solver.addConstraint(constraint);
|
||||
}
|
||||
|
||||
.. note::
|
||||
|
||||
You can start adding constraints to the solver without creating all your
|
||||
variables first.
|
||||
|
||||
|
||||
So far, we have defined a system representing three points on the segment
|
||||
[0, 100], with one of them being the middle of the others, which cannot get
|
||||
closer than 10. All those constraints have to be satisfied; in the context
|
||||
of Cassowary, they are required constraints.
|
||||
|
||||
.. note::
|
||||
|
||||
Cassowary (and Kiwi) allows for redundant constraints, which means
|
||||
even with two constraints (x == 10, x + y == 30) being equivalent to a
|
||||
third one (y == 20), all three can be added to the solver without issues.
|
||||
|
||||
However, it is advisable not to add the same constraint multiple times
|
||||
in the same form to the solver.
|
||||
|
||||
|
||||
Managing constraints strength
|
||||
-----------------------------
|
||||
|
||||
Cassowary also supports constraints that are not required. Those are only
|
||||
respected on a best effort basis. To express that a constraint is not required
|
||||
we need to assign it a *strength*. Kiwi specifies three standard strengths
|
||||
besides the "required" strength: strong, medium, weak. A strong constraint
|
||||
will always win over a medium constraint, which in turn will always override
|
||||
a weak constraint [#f1]_ .
|
||||
|
||||
In our example, let's assume x1 would like to be at 40, without this being a
|
||||
requirement. This is translated as follows:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
solver.addConstraint((x1 == 40) | "weak")
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
solver.addConstraint(x1 == 40 | strength::weak);
|
||||
|
||||
|
||||
Adding edit variables
|
||||
---------------------
|
||||
|
||||
So far our system is pretty static; we have no way of trying to find solutions
|
||||
for a particular value of `xm`, let's say. This is a problem. In a real
|
||||
application (e.g. a GUI layout), we would like to find the size of the widgets
|
||||
based on the top window but also react to the window resizing, so actually
|
||||
adding and removing constraints all the time wouldn't be optimal. And there is
|
||||
a better way: edit variables.
|
||||
|
||||
Edit variables are variables for which you can suggest values. Edit variables
|
||||
have a strength which can be at most strong (the value of a edit variable can
|
||||
never be required).
|
||||
|
||||
For the sake of our example, we will make "xm" editable:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
solver.addEditVariable(xm, 'strong')
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
solver.addEditVariable(xm, strength::strong);
|
||||
|
||||
Once a variable has been added as an edit variable, you can suggest a value for
|
||||
it and the solver will try to solve the system with it.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
solver.suggestValue(xm, 60)
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
solver.suggestValue(xm, 60);
|
||||
|
||||
This would give the following solution: ``xm == 60, x1 == 40, x2 == 80``.
|
||||
|
||||
|
||||
Solving and updating variables
|
||||
------------------------------
|
||||
|
||||
Kiwi solves the system each time a constraint is added or removed, or a new
|
||||
value is suggested for an edit variable. Solving the system each time makes for
|
||||
faster updates and allows to keep the solver in a consinstent state. However,
|
||||
the variable values are not updated automatically, and you need to ask
|
||||
the solver to perform this operation before reading the values, as illustrated
|
||||
below:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
solver.suggestValue(xm, 90)
|
||||
solver.updateVariables()
|
||||
print(xm.value(), x1.value(), x2.value())
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
solver.suggestValue(xm, 90);
|
||||
solver.updateVariables();
|
||||
std::cout << xm.value() << ", " << x1.value() << ", " << x2.value();
|
||||
|
||||
This last update creates an infeasible situation by pushing x2 further than
|
||||
100, if we keep x1 where it would like to be. As a consequence, we get the
|
||||
following solution: ``xm == 90, x1 == 80, x2 == 100``
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
To determine if a non-required constraint was violated when solving the system,
|
||||
you can use the constraint's ``violated`` method.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
|
||||
.. [#f1] Actually, there are some corner cases in which this can be violated.
|
||||
See :ref:`basics-internals`
|
||||
22
kiwi/docs/source/basis/index.rst
Normal file
22
kiwi/docs/source/basis/index.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
.. _basis:
|
||||
|
||||
Kiwisolver usage
|
||||
================
|
||||
|
||||
.. include:: ../substitutions.sub
|
||||
|
||||
This section of the docs aims at getting you up and running with Kiwi. You will
|
||||
in particular learn how to install Kiwi, create a system of constraints, solve,
|
||||
update it etc... By the end of it you will know how to use the solver.
|
||||
|
||||
However if you are not familiar with Cassowary (or constraints solver in
|
||||
general) it may not be enough to get you started using it in your project.
|
||||
Hopefully the real world use cases described in :ref:`uses` will shed
|
||||
more light on how to use it in real applications.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation.rst
|
||||
basic_systems.rst
|
||||
solver_internals.rst
|
||||
87
kiwi/docs/source/basis/installation.rst
Normal file
87
kiwi/docs/source/basis/installation.rst
Normal file
@@ -0,0 +1,87 @@
|
||||
.. _basis-installation:
|
||||
|
||||
Installing Kiwisolver on Python
|
||||
===============================
|
||||
|
||||
.. include:: ../substitutions.sub
|
||||
|
||||
Kiwisolver is supported on Python 3.7+. Installing it is a straight-forward
|
||||
process. There are three approaches to choose from.
|
||||
|
||||
The easy way: Pre-compiled packages
|
||||
-----------------------------------
|
||||
|
||||
The easiest way to install atom is through pre-compiled packages. Kiwisolver is
|
||||
distributed pre-compiled in two-forms.
|
||||
|
||||
Conda packages
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
If you use the `Anaconda`_ Python distribution platform (or `Miniconda`_, its
|
||||
lighter-weight companion), the latest release of Kiwisolver can be installed
|
||||
using conda from the default channel or the conda-forge channel::
|
||||
|
||||
$ conda install kiwisolver
|
||||
|
||||
$ conda install kiwisolver -c conda-forge
|
||||
|
||||
.. _Anaconda: https://store.continuum.io/cshop/anaconda
|
||||
.. _Miniconda: https://conda.io/miniconda.html
|
||||
|
||||
Wheels
|
||||
^^^^^^
|
||||
|
||||
If you don't use Anaconda, you can install Kiwisolver pre-compiled,
|
||||
through PIP, for most common platforms::
|
||||
|
||||
$ pip install kiwisolver
|
||||
|
||||
Compiling it yourself: The Hard Way
|
||||
-----------------------------------
|
||||
|
||||
Building Kiwisolver from scratch requires Python and a C++ compiler. On Unix
|
||||
platform getting a C++ compiler properly configured is generally
|
||||
straighforward. On Windows, starting with Python 3.6 the free version of the
|
||||
Microsoft toolchain should work out of the box. Installing Kiwisolver is then
|
||||
as simple as::
|
||||
|
||||
$ pip install .
|
||||
|
||||
.. note::
|
||||
|
||||
For MacOSX users on OSX Mojave, one needs to set MACOSX_DEPLOYMENT_TARGET
|
||||
to higher than 10.9 to force the compiler to use the new C++ stdlib::
|
||||
|
||||
$ export MACOSX_DEPLOYMENT_TARGET=10.10
|
||||
|
||||
|
||||
Supported Platforms
|
||||
-------------------
|
||||
|
||||
Kiwisolver is known to run on Windows, OSX, and Linux; and compiles cleanly
|
||||
with MSVC, Clang, GCC, and MinGW. If you encounter a bug, please report
|
||||
it on the `Issue Tracker`_.
|
||||
|
||||
.. _Issue Tracker: http://github.com/nucleic/enaml/issues
|
||||
|
||||
|
||||
Checking your install
|
||||
---------------------
|
||||
|
||||
Once you installed kiwisolver you should be able to import it as follows:
|
||||
|
||||
.. code:: python
|
||||
|
||||
import kiwisolver
|
||||
|
||||
.. note::
|
||||
|
||||
On Windows, the import may fail with `ImportError: DLL load failed`. If it
|
||||
does, it means your system is missing the Microsoft Visual C++
|
||||
redistributable matching your Python version. To fix the issue download
|
||||
and install the package corresponding to your Python version
|
||||
(https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads):
|
||||
|
||||
- Python 2.7: Visual C++ Redistributable 2008
|
||||
- Python 3.4: Visual C++ Redistributable 2010
|
||||
- Python 3.5+: Visual C++ Redistributable 2015 or more recent
|
||||
196
kiwi/docs/source/basis/solver_internals.rst
Normal file
196
kiwi/docs/source/basis/solver_internals.rst
Normal file
@@ -0,0 +1,196 @@
|
||||
.. _basics-internals:
|
||||
|
||||
Solver internals and tips
|
||||
=========================
|
||||
|
||||
.. include:: ../substitutions.sub
|
||||
|
||||
|
||||
Kiwi is not a mere rewriting of Cassowary, and due to this, it does not always
|
||||
perfectly reflect the original implementation. The following sections point out
|
||||
these discrepancies and provide tips on how to work effectively with Kiwi.
|
||||
|
||||
|
||||
Inspecting the solver state
|
||||
---------------------------
|
||||
|
||||
The state of the solver can be inspected by dumping a text representation of
|
||||
its state either to stdout using the ``dump`` method of the solver, or to a
|
||||
string using the ``dumps`` method. Typically, at least a basic understanding of
|
||||
the Cassowary algorithm is necessary to analyse the output.
|
||||
|
||||
A typical output is reproduced below:
|
||||
|
||||
|
||||
.. code::
|
||||
|
||||
Objective
|
||||
---------
|
||||
-2 + 2 * e2 + 1 * s8 + -2 * s10
|
||||
|
||||
Tableau
|
||||
-------
|
||||
v1 | 1 + 1 * s10
|
||||
e3 | -1 + 1 * e2 + -1 * s10
|
||||
v4 | -1 + -1 * d5 + -1 * s10
|
||||
s6 | -2 + -1 * s10
|
||||
e9 | -1 + 1 * s8 + -1 * s10
|
||||
|
||||
Infeasible
|
||||
----------
|
||||
e3
|
||||
e9
|
||||
|
||||
Variables
|
||||
---------
|
||||
bar = v1
|
||||
foo = v4
|
||||
|
||||
Edit Variables
|
||||
--------------
|
||||
bar
|
||||
|
||||
Constraints
|
||||
-----------
|
||||
1 * bar + -0 >= 0 | strength = 1
|
||||
1 * bar + 1 <= 0 | strength = 1.001e+09
|
||||
1 * foo + 1 * bar + 0 == 0 | strength = 1.001e+09
|
||||
1 * bar + 0 == 0 | strength = 1
|
||||
|
||||
In the dump, the letters have the following meaning:
|
||||
|
||||
- v: external variable, corresponds to the variable created by you, the user
|
||||
- s: slack symbol, used to represent inequalities
|
||||
- e: error symbol, used to represent non-required constraints
|
||||
- d: dummy variable, always zero, used to keep track of the impact of an
|
||||
external variable in the tableau.
|
||||
- i: invalid symbol, returned when no valid symbol can be found.
|
||||
|
||||
|
||||
Stay constraints emulation
|
||||
--------------------------
|
||||
|
||||
One feature of Cassowary that Kiwi abandoned is the notion of stay
|
||||
constraints. Stay constraints are typically used in under-constrained
|
||||
situations (drag and drop) to allow the solver to find a solution by keeping
|
||||
non-modified variable close to their original position. A typical example is
|
||||
a rectangle whose one corner is being dragged in a drawing application.
|
||||
|
||||
Kiwi does not have stay constraints mostly because in the context of widget
|
||||
placement, the system is typically well constrained, rendering stay constraints
|
||||
unnecessary.
|
||||
|
||||
If your application requires them, several workarounds can be considered:
|
||||
|
||||
- adding/removing non-required equality constraints to mimic stay constraints
|
||||
- using edit-variables to mimic stay constraints
|
||||
|
||||
The first method will require to remove the old constraints as soon as they
|
||||
stop making sense, while the second will require to update the suggested value.
|
||||
|
||||
|
||||
Creating strengths and their internal representation
|
||||
----------------------------------------------------
|
||||
|
||||
Kiwi provides three strengths in addition to the required strength by default:
|
||||
"weak", "medium", and "strong". Contrary to Cassowary, which uses lexicographic
|
||||
ordering to ensure that strength are always respected, Kiwi strives for speed
|
||||
and uses simple floating point numbers.
|
||||
|
||||
.. note::
|
||||
|
||||
Using simple floating point, means that in some rare corner cases, a large
|
||||
number of weak constraints may outweigh a medium constraint. However, in
|
||||
practice, this rarely happens.
|
||||
|
||||
Kiwi allows to create custom strengths in the following manner:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: python
|
||||
|
||||
from kiwisolver import strength
|
||||
|
||||
my_strength = strength.create(1, 1, 1)
|
||||
my_strength2 = strength.create(1, 1, 1, 2)
|
||||
|
||||
.. code-tab:: c++
|
||||
|
||||
double my_strength = strength::create(1, 1, 1);
|
||||
double my_strength = strength::create(1, 1, 1, 2);
|
||||
|
||||
The first argument is multiplied by 1 000 000, the second argument by 1 000,
|
||||
and the third by 1. No strength can be create larger than the required
|
||||
strength. The default strengths in Kiwi correspond to:
|
||||
|
||||
.. code:: python
|
||||
|
||||
weak = strength.create(0, 0, 1)
|
||||
medium = strength.create(0, 1, 0)
|
||||
strong = strength.create(1, 0, 0)
|
||||
required = strength.create(1000, 1000, 1000)
|
||||
|
||||
While Cassowary differentiates between strength and weight, those two concepts
|
||||
are fused in Kiwi: when creating a strength, one can apply a weight (the fourth
|
||||
argument) that will multiply it.
|
||||
|
||||
.. note::
|
||||
|
||||
Because strengths are implemented as floating point numbers, in order to be
|
||||
effective, strengths must be different enough from one another. The
|
||||
following is unlikely to produce any really useful result.
|
||||
|
||||
.. code:: python
|
||||
|
||||
weak1 = strength.create(0, 0, 1)
|
||||
weak2 = strength.create(0, 0, 2)
|
||||
weak3 = strength.create(0, 0, 3)
|
||||
|
||||
|
||||
Managing memory
|
||||
---------------
|
||||
|
||||
When removing a constraint, Kiwi does not check whether or not the variables
|
||||
used in the constraint are still in use in other constraints. This is mostly
|
||||
because such checks could be quite expensive. However, this means the map of
|
||||
variables can grow over time.
|
||||
|
||||
To avoid this possibly causing large memory leaks, it is recommended to reset
|
||||
the solver state (using the method of the same name) and to add back the
|
||||
constraints, that are still valid at this point.
|
||||
|
||||
|
||||
Representation of constraints
|
||||
-----------------------------
|
||||
|
||||
If you browse through the API documentation you may notice a number of classes
|
||||
that do not appear anywhere in this documentation: Term and Expression.
|
||||
|
||||
Those classes are used internally in constraints and are created automatically
|
||||
by the library. A |Term| represents a variable/symbol and the coefficient that
|
||||
multiplies it, |Expression| represents a sum of terms and a constant value and
|
||||
is used as the left hand side of a constraint.
|
||||
|
||||
|
||||
Performance implementation tricks
|
||||
---------------------------------
|
||||
|
||||
Map type
|
||||
^^^^^^^^
|
||||
|
||||
Kiwi uses maps to represent the state of the solver and to manipulate it. As a
|
||||
consequence, the map type should be fast, with a particular emphasis on
|
||||
iteration. The C++ standard library provides unordered_map and map that could
|
||||
be used in kiwi, but none of those are very friendly to the CPU cache. For
|
||||
this reason, Kiwi uses the AssocVector class implemented in Loki (slightly
|
||||
updated to respect c++11 standards). The use of this class provides a 2x
|
||||
speedup over std::map.
|
||||
|
||||
|
||||
Symbol representation
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Symbols are used in Kiwi to represent the state of the solver. Since solving the
|
||||
system requires a large number of manipulations of the symbols, the operations
|
||||
have to compile down to an efficient representation. In Kiwi, symbols compile
|
||||
down to long long meaning that a vector of them fits in a CPU cache line.
|
||||
169
kiwi/docs/source/conf.py
Normal file
169
kiwi/docs/source/conf.py
Normal file
@@ -0,0 +1,169 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/main/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# NOTE the project needs to be installed for the docs to be properly built.
|
||||
import kiwisolver
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "kiwisolver"
|
||||
copyright = "2018-2021, Nucleic team"
|
||||
author = "Nucleic team"
|
||||
|
||||
# The short X.Y version
|
||||
version = ".".join(kiwisolver.__version__.split(".")[:2])
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = kiwisolver.__version__
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.doctest",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.todo",
|
||||
"sphinx.ext.coverage",
|
||||
"sphinx.ext.imgmath",
|
||||
"sphinx.ext.ifconfig",
|
||||
"sphinx.ext.viewcode",
|
||||
"sphinx.ext.graphviz",
|
||||
"sphinx.ext.inheritance_diagram",
|
||||
"sphinx.ext.autosummary",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx_tabs.tabs",
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ["_templates"]
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The main toctree document.
|
||||
main_doc = "index"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = "en"
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path .
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = "sphinx"
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
# html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = "kiwidoc"
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(main_doc, "kiwi.tex", "kiwi Documentation", "Nucleic team", "manual"),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [(main_doc, "kiwi", "kiwi Documentation", [author], 1)]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(
|
||||
main_doc,
|
||||
"kiwi",
|
||||
"kiwi Documentation",
|
||||
author,
|
||||
"kiwi",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
29
kiwi/docs/source/developer_notes/index.rst
Normal file
29
kiwi/docs/source/developer_notes/index.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
.. _developer:
|
||||
|
||||
Developer notes
|
||||
================
|
||||
|
||||
These notes are meant to help developers and contributors with regards to some
|
||||
details of the implementation and coding style of the project.
|
||||
|
||||
C++ codebase
|
||||
------------
|
||||
|
||||
The C++ codebase currently targets C++11 compliance. It is header-only since
|
||||
one of the focus of the library is speed.
|
||||
|
||||
|
||||
Python bindings
|
||||
---------------
|
||||
|
||||
Python bindings targets Python 3.7 and above. The bindings are hand-written and
|
||||
relies on cppy (https://github.com/nucleic/cppy). Kiwisolver tries to use a
|
||||
reasonably modern C API and to support sub-interpreter, this has a couple of
|
||||
consequences:
|
||||
|
||||
- all the non exported symbol are enclosed in anonymous namespaces
|
||||
- kiwisolver does not use static types and only dynamical types (note that the
|
||||
type slots and related structures are stored in a static variable)
|
||||
- modules use the multi-phases initialization mechanism as defined in
|
||||
PEP 489 -- Multi-phase extension module initialization
|
||||
- static variables use is limited to type slots, method def
|
||||
32
kiwi/docs/source/index.rst
Normal file
32
kiwi/docs/source/index.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
.. kiwi documentation main file, created by
|
||||
sphinx-quickstart on Mon Oct 29 21:48:45 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Kiwisolver's documentation!
|
||||
======================================
|
||||
|
||||
Kiwisolver is an efficient C++ implementation of the Cassowary constraint
|
||||
solving algorithm. Kiwi is an implementation of the algorithm based on the
|
||||
seminal Cassowary paper. It is *not* a refactoring of the original C++ solver.
|
||||
Kiwisolver has been designed from the ground up to be lightweight and fast.
|
||||
Kiwisolver range from 10x to 500x faster than the original Cassowary solver
|
||||
with typical use cases gaining a 40x improvement. Memory savings are
|
||||
consistently > 5x.
|
||||
|
||||
In addition to the C++ solver, Kiwi ships with hand-rolled Python bindings.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Getting started <basis/index.rst>
|
||||
Use cases <use_cases/index.rst>
|
||||
Developer notes <developer_notes/index.rst>
|
||||
API Documentation <api/index.rst>
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
16
kiwi/docs/source/substitutions.sub
Normal file
16
kiwi/docs/source/substitutions.sub
Normal file
@@ -0,0 +1,16 @@
|
||||
..
|
||||
This file holds some common substitutions (mainly for referencing code).
|
||||
To use it add the directive include:: substitutions.rst at the beginning of
|
||||
the file.
|
||||
|
||||
.. ============================================================================
|
||||
.. Kiwi substitutions
|
||||
.. ============================================================================
|
||||
|
||||
.. |Variable| replace:: :py:class:`~kiwisolver.Variable`
|
||||
|
||||
.. |Solver| replace:: :py:class:`~kiwisolver.Solver`
|
||||
|
||||
.. |Term| replace:: :py:class:`~kiwisolver.Term`
|
||||
|
||||
.. |Expression| replace:: :py:class:`~kiwisolver.Expression`
|
||||
142
kiwi/docs/source/use_cases/enaml.rst
Normal file
142
kiwi/docs/source/use_cases/enaml.rst
Normal file
@@ -0,0 +1,142 @@
|
||||
.. _uses-enaml:
|
||||
|
||||
Enaml
|
||||
=====
|
||||
|
||||
.. include:: ../substitutions.sub
|
||||
|
||||
Enaml is a programming language and framework for creating professional-quality
|
||||
user interfaces with minimal effort. It relies on Kiwi to layout widgets.
|
||||
|
||||
To implement its layout, Enaml uses a nestable model. Containers widgets
|
||||
handle the constraints generation used to layout their children. Furthermore,
|
||||
they pass to their their children a representation of the bounding box in
|
||||
which they should live which allows the widgets to position themselves inside
|
||||
their parent. Since each leaf component has a "preferred size", the system can
|
||||
be solved from the bottom-up and set the size the parents based on the required
|
||||
space of the children. If at a later time the parent is resized, this new input
|
||||
can be used to solve the layout problem.
|
||||
|
||||
The following sections will describe in more details how the constraints are
|
||||
generated and the preferred size estimated.
|
||||
|
||||
Widget variables
|
||||
----------------
|
||||
|
||||
In Enaml, each widget that can be constrained defines a bunch of Kiwi
|
||||
|Variable|: ``left``, ``top``, ``width`` and ``height``. In addition,
|
||||
it provides easy access to combination of those: ``right``, ``bottom``,
|
||||
``h_center``, ``v_center``. Those variables will be used to define the layout.
|
||||
|
||||
In addition, because each widget has a preferred size, it defines a set of
|
||||
constraints related to that preferred size on which the user can act upon by
|
||||
modifying their strength:
|
||||
- hug_width: equivalent to (width == hint) | hug_width
|
||||
- hug_height: equivalent to (height == hint) | hug_height
|
||||
- resist_width: equivalent to (width >= hint) | resist_width
|
||||
- resist_height: equivalent to (height >= hint) | resist_height
|
||||
- limit_width: equivalent to (width <= hint) | limit_width
|
||||
- limit_height: equivalent to (height <= hint) | limit_height
|
||||
|
||||
Finally, widget that can contain other widgets define a set of variables that
|
||||
they expose to their children to allow to place themselves relative to their
|
||||
parents. Those are: ``contents_left``, ``contents_top``, ``contents_width``,
|
||||
``contents_height``, ``contents_right``, ``contents_bottom``,
|
||||
``contents_h_center``, ``contents_v_center``. Those are usually not equivalent
|
||||
to the non-prefixed variables (even-though they are related) because of the
|
||||
container margins.
|
||||
|
||||
The base classes used a mixin to implement those behaviors are defined in:
|
||||
https://github.com/nucleic/enaml/blob/main/enaml/layout/constrainable.py
|
||||
|
||||
Constraints definition
|
||||
----------------------
|
||||
|
||||
Using the above variable, one can express any constraints. However, even for
|
||||
simple vertical or horizontal boxes, the constraints to define, in
|
||||
particular if one needs to introduce some spacing around the objects, become
|
||||
quite painful to write by hand.
|
||||
|
||||
To make constraints definition easier, Enaml relies on helpers function and
|
||||
classes. In the following, we will focus on how horizontal and vertical boxes
|
||||
constraints are handled, by studying the following example in details:
|
||||
|
||||
.. image:: enaml_hbox.svg
|
||||
|
||||
Here we consider a container widget with three child widgets. The outer black
|
||||
frame represents the limit of the container. The dashed frame represents the
|
||||
contents visible to children when defining their constraint. The container uses
|
||||
the margin definition to relate the outer left, top, width and height to their
|
||||
'contents' equivalent.
|
||||
|
||||
The three widgets are arranged according to a horizontal box for which the
|
||||
constraints are created using the `hbox` helper function which simply accepts
|
||||
a list of widgets and spacers . To define the constraints from that list, Enaml
|
||||
relies on the spacers represented here in orange. Each spacer has a
|
||||
given size and a policy regarding that size (is it a minimum value, maximum,
|
||||
how strongly to enforce that size). For each orientation, `hbox` add spacers so
|
||||
that there is a spacer between each widget and between the widgets and the
|
||||
parent boundaries. Some spacers can have a zero size, simply meaning that
|
||||
widgets should be in contact.
|
||||
|
||||
When generating the constraints, `hbox` will be passed the container and use
|
||||
the spacers to generate the constraints by simply glueing the anchors of
|
||||
surrounding widgets. Each spacer can generate multiple constraints which gives
|
||||
this process a lot of flexibility. Furthermore, those helpers define the same
|
||||
variable as the widgets allowing for to position groups with respect to one
|
||||
another.
|
||||
|
||||
.. note::
|
||||
|
||||
In practice, `hbox` itself relies on some helpers but the above gives you
|
||||
the general idea.
|
||||
|
||||
For further details you can have a look at the source of the helpers described
|
||||
in this section which can be found in the Enaml source:
|
||||
|
||||
- spacers: https://github.com/nucleic/enaml/blob/main/enaml/layout/spacers.py
|
||||
- helpers:
|
||||
|
||||
- https://github.com/nucleic/enaml/blob/main/enaml/layout/layout_helpers.py
|
||||
- https://github.com/nucleic/enaml/blob/main/enaml/layout/linear_box_helper.py
|
||||
- https://github.com/nucleic/enaml/blob/main/enaml/layout/sequence_helper.py
|
||||
|
||||
|
||||
Setting up the solver
|
||||
---------------------
|
||||
|
||||
So far we have only defined the constraints that represent the layout, we will
|
||||
now turn to how Enaml pass those to the solver and how it handle updates and
|
||||
solver resets.
|
||||
|
||||
By default, each container manages its own solver independently. This has
|
||||
the advantage of keeping the system relatively smalls and hence allow for
|
||||
faster updates. When setting up the solver, the container will add for each
|
||||
widget a set of constraints reflecting the preference of the widget regarding
|
||||
its size as reported by the widget, and add to those the constraints defining
|
||||
the layout. It will also add two edit variable representing the width and
|
||||
height of the container.
|
||||
|
||||
Once the solver has been set up it can be used to compute different values,
|
||||
such as the best size for the container (requesting a size of 0 with a 0.1*weak
|
||||
strength), its min size (0 size, medium strength) and max size (max size,
|
||||
medium strength).
|
||||
|
||||
When the parent is resized, the solver is invoked again with the new width and
|
||||
height as suggestion. On the other hand, if the constraints change either
|
||||
because widgets have been added or removed or because the users modified them,
|
||||
the solver is reset and the constraints are rebuilt-from scratch. This means
|
||||
that we never keep the solver around long enough to have to worry about memory
|
||||
consumption due to unused variables in the solver.
|
||||
|
||||
In a complex hierarchy, the top parent will request the sizes of the nested
|
||||
containers which will trigger the solving of their constraints. At some point
|
||||
in the nested structure, we will only find widgets which provides a size hint
|
||||
without requiring to solve constraints (ex: a button). This will allow to solve
|
||||
the system and then propagate back upward.
|
||||
|
||||
|
||||
Hopefully this brief introduction will have clarified how Enaml make use of
|
||||
kiwi to layout its widgets. Some fine mechanics have been simplified for the
|
||||
sake of this description but you can check Enaml sources for a more in depth
|
||||
description.
|
||||
244
kiwi/docs/source/use_cases/enaml_hbox.svg
Normal file
244
kiwi/docs/source/use_cases/enaml_hbox.svg
Normal file
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 449.8 112.7" enable-background="new 0 0 449.8 112.7" xml:space="preserve">
|
||||
<font horiz-adv-x="1000">
|
||||
<!-- Copyright 2000, 2004 , 2005Adobe Systems Incorporated. All Rights Reserved. U.S. Patent D454,582.Myriad is a registered trademark of Adobe Systems Incorporated. -->
|
||||
<font-face font-family="MyriadPro-Bold" units-per-em="1000" underline-position="-100" underline-thickness="50"/>
|
||||
<missing-glyph horiz-adv-x="500" d="M0,0l500,0l0,700l-500,0M250,395l-170,255l340,0M280,350l170,255l0,-510M80,50l170,255l170,-255M50,605l170,-255l-170,-255z"/>
|
||||
<glyph unicode="C" horiz-adv-x="595" d="M538,138C508,126 457,116 411,116C275,116 195,201 195,336C195,486 289,559 410,559C464,559 507,547 538,534l31,121C542,669 482,685 403,685C199,685 35,557 35,327C35,135 155,-11 388,-11C470,-11 533,5 561,19z"/>
|
||||
<glyph unicode="W" horiz-adv-x="888" d="M342,0l64,290C422,358 433,422 445,498l2,0C455,421 466,358 479,290l57,-290l165,0l174,674l-155,0l-55,-276C651,318 636,239 626,164l-2,0C614,239 603,311 588,390l-54,284l-162,0l-57,-276C298,315 282,234 271,161l-2,0C258,229 244,316 229,397l-51,277l-163,0l160,-674z"/>
|
||||
<glyph unicode="a" horiz-adv-x="528" d="M469,289C469,404 417,500 254,500C165,500 98,476 64,457l28,-98C124,379 177,396 227,396C302,396 316,359 316,333l0,-7C143,327 29,266 29,139C29,61 88,-11 187,-11C245,-11 295,10 327,49l3,0l9,-49l137,0C471,27 469,72 469,119M321,178C321,169 320,160 318,152C308,121 277,96 239,96C205,96 179,115 179,154C179,213 241,232 321,231z"/>
|
||||
<glyph unicode="d" horiz-adv-x="596" d="M383,710l0,-265l-2,0C359,479 312,500 252,500C135,500 32,405 33,240C33,88 126,-11 242,-11C305,-11 364,17 395,72l2,0l7,-72l135,0C537,33 535,91 535,146l0,564M383,218C383,205 382,194 379,183C370,140 335,110 291,110C228,110 187,162 187,245C187,322 223,384 292,384C339,384 372,350 381,309C382,301 383,290 383,282z"/>
|
||||
<glyph unicode="e" horiz-adv-x="528" d="M493,196C495,207 498,230 498,256C498,377 438,500 280,500C110,500 33,363 33,239C33,86 128,-11 294,-11C360,-11 421,0 471,20l-20,103C410,110 368,103 316,103C245,103 183,133 178,196M177,300C181,341 207,399 271,399C341,399 357,337 357,300z"/>
|
||||
<glyph unicode="g" horiz-adv-x="585" d="M524,344C524,417 526,458 528,489l-132,0l-5,-58l-2,0C364,471 322,500 255,500C135,500 33,400 33,243C33,102 119,4 240,4C296,4 343,27 372,68l2,0l0,-32C374,-54 319,-93 247,-93C190,-93 136,-74 105,-56l-30,-115C119,-196 187,-209 251,-209C323,-209 396,-195 450,-149C505,-100 524,-23 524,71M372,218C372,205 371,189 367,178C357,142 326,116 287,116C223,116 187,173 187,246C187,335 232,385 287,385C329,385 358,358 369,318C371,310 372,300 372,290z"/>
|
||||
<glyph unicode="i" horiz-adv-x="274" d="M213,0l0,489l-152,0l0,-489M137,702C88,702 56,669 57,625C56,583 88,549 136,549C186,549 218,583 218,625C217,669 186,702 137,702z"/>
|
||||
<glyph unicode="n" horiz-adv-x="586" d="M61,0l152,0l0,282C213,296 215,310 219,320C229,348 254,377 296,377C351,377 373,334 373,271l0,-271l152,0l0,290C525,434 450,500 350,500C269,500 219,453 199,422l-3,0l-7,67l-132,0C59,446 61,394 61,333z"/>
|
||||
<glyph unicode="o" horiz-adv-x="577" d="M294,500C137,500 33,399 33,241C33,83 143,-11 286,-11C417,-11 544,71 544,250C544,397 444,500 294,500M290,392C359,392 387,318 387,245C387,157 349,98 290,98C225,98 190,161 190,245C190,317 217,392 290,392z"/>
|
||||
<glyph unicode="1" horiz-adv-x="555" d="M236,0l147,0l0,650l-126,0l-172,-80l25,-114l124,59l2,0z"/>
|
||||
<glyph unicode="r" horiz-adv-x="380" d="M61,0l152,0l0,248C213,260 214,272 216,282C226,329 264,359 320,359C337,359 350,357 361,354l0,144C350,500 343,500 329,500C282,500 222,470 197,399l-4,0l-5,90l-131,0C59,447 61,400 61,328z"/>
|
||||
<glyph unicode=" " horiz-adv-x="202"/>
|
||||
<glyph unicode="t" horiz-adv-x="367" d="M82,581l0,-92l-65,0l0,-112l65,0l0,-200C82,108 96,61 124,32C148,7 189,-11 238,-11C281,-11 317,-5 337,3l-1,115C321,115 312,114 291,114C245,114 231,141 231,200l0,177l109,0l0,112l-109,0l0,133z"/>
|
||||
<glyph unicode="3" horiz-adv-x="555" d="M38,35C76,11 147,-11 231,-11C396,-11 497,73 497,188C497,273 434,332 356,346l0,2C436,376 475,430 475,499C475,588 398,661 259,661C175,661 97,637 58,612l31,-110C116,518 172,541 225,541C289,541 321,512 321,473C321,418 256,399 205,398l-59,0l0,-109l62,0C275,289 339,260 339,196C339,147 299,109 220,109C158,109 96,135 69,149z"/>
|
||||
<glyph unicode="2" horiz-adv-x="555" d="M503,0l0,125l-245,0l0,2l60,50C412,261 491,348 491,457C491,575 410,661 263,661C175,661 99,631 50,594l43,-109C127,511 176,539 232,539C307,539 339,497 339,444C337,368 268,295 126,168l-84,-76l0,-92z"/>
|
||||
</font>
|
||||
|
||||
<font horiz-adv-x="1000">
|
||||
<!-- Copyright 2000, 2004 , 2005Adobe Systems Incorporated. All Rights Reserved. U.S. Patent D454,582.Myriad is a registered trademark of Adobe Systems Incorporated. -->
|
||||
<font-face font-family="MyriadPro-Regular" units-per-em="1000" underline-position="-100" underline-thickness="50"/>
|
||||
<missing-glyph horiz-adv-x="500" d="M0,0l500,0l0,700l-500,0M250,395l-170,255l340,0M280,350l170,255l0,-510M80,50l170,255l170,-255M50,605l170,-255l-170,-255z"/>
|
||||
<glyph unicode="a" horiz-adv-x="482" d="M413,297C413,394 377,495 229,495C168,495 110,478 70,452l20,-58C124,416 171,430 216,430C315,430 326,358 326,318l0,-10C139,309 35,245 35,128C35,58 85,-11 183,-11C252,-11 304,23 331,61l3,0l7,-61l80,0C415,33 413,74 413,116M328,163C328,154 326,144 323,135C309,94 269,54 206,54C161,54 123,81 123,138C123,232 232,249 328,247z"/>
|
||||
<glyph unicode="b" horiz-adv-x="569" d="M73,125C73,82 71,33 69,0l76,0l4,80l3,0C188,16 244,-11 314,-11C422,-11 531,75 531,248C532,395 447,495 327,495C249,495 193,460 162,406l-2,0l0,304l-87,0M160,281C160,295 163,307 165,317C183,384 239,425 299,425C393,425 443,342 443,245C443,134 388,59 296,59C232,59 181,101 164,162C162,172 160,183 160,194z"/>
|
||||
<glyph unicode="e" horiz-adv-x="501" d="M462,226C463,235 465,249 465,267C465,356 423,495 265,495C124,495 38,380 38,234C38,88 127,-11 276,-11C353,-11 406,6 437,20l-15,63C389,69 351,58 288,58C200,58 124,107 122,226M123,289C130,350 169,432 258,432C357,432 381,345 380,289z"/>
|
||||
<glyph unicode="f" horiz-adv-x="292" d="M169,0l0,417l117,0l0,67l-117,0l0,26C169,584 188,650 263,650C288,650 306,645 319,639l12,68C314,714 287,721 256,721C215,721 171,708 138,676C97,637 82,575 82,507l0,-23l-68,0l0,-67l68,0l0,-417z"/>
|
||||
<glyph unicode="g" horiz-adv-x="559" d="M486,351C486,410 488,449 490,484l-77,0l-4,-73l-2,0C386,451 340,495 256,495C145,495 38,402 38,238C38,104 124,2 244,2C319,2 371,38 398,83l2,0l0,-54C400,-93 334,-140 244,-140C184,-140 134,-122 102,-102l-22,-67C119,-195 183,-209 241,-209C302,-209 370,-195 417,-151C464,-109 486,-41 486,70M399,206C399,191 397,174 392,159C373,103 324,69 270,69C175,69 127,148 127,243C127,355 187,426 271,426C335,426 378,384 394,333C398,321 399,308 399,293z"/>
|
||||
<glyph unicode="h" horiz-adv-x="555" d="M73,0l88,0l0,292C161,309 162,322 167,334C183,382 228,422 285,422C368,422 397,356 397,278l0,-278l88,0l0,288C485,455 381,495 316,495C283,495 252,485 226,470C199,455 177,433 163,408l-2,0l0,302l-88,0z"/>
|
||||
<glyph unicode="i" horiz-adv-x="234" d="M161,0l0,484l-88,0l0,-484M117,675C85,675 62,651 62,620C62,590 84,566 115,566C150,566 172,590 171,620C171,651 150,675 117,675z"/>
|
||||
<glyph unicode="l" horiz-adv-x="236" d="M73,0l88,0l0,710l-88,0z"/>
|
||||
<glyph unicode="m" horiz-adv-x="834" d="M73,0l86,0l0,292C159,307 161,322 166,335C180,379 220,423 275,423C342,423 376,367 376,290l0,-290l86,0l0,299C462,315 465,331 469,343C484,386 523,423 573,423C644,423 678,367 678,274l0,-274l86,0l0,285C764,453 669,495 605,495C559,495 527,483 498,461C478,446 459,425 444,398l-2,0C421,455 371,495 305,495C225,495 180,452 153,406l-3,0l-4,78l-77,0C72,444 73,403 73,353z"/>
|
||||
<glyph unicode="n" horiz-adv-x="555" d="M73,0l88,0l0,291C161,306 163,321 167,332C182,381 227,422 285,422C368,422 397,357 397,279l0,-279l88,0l0,289C485,455 381,495 314,495C234,495 178,450 154,404l-2,0l-5,80l-78,0C72,444 73,403 73,353z"/>
|
||||
<glyph unicode="o" horiz-adv-x="549" d="M278,495C144,495 38,400 38,238C38,85 139,-11 270,-11C387,-11 511,67 511,246C511,394 417,495 278,495M276,429C380,429 421,325 421,243C421,134 358,55 274,55C188,55 127,135 127,241C127,333 172,429 276,429z"/>
|
||||
<glyph unicode="p" horiz-adv-x="569" d="M73,-198l87,0l0,263l2,0C191,17 247,-11 311,-11C425,-11 531,75 531,249C531,396 443,495 326,495C247,495 190,460 154,401l-2,0l-4,83l-79,0C71,438 73,388 73,326M160,280C160,292 163,305 166,316C183,382 239,425 299,425C392,425 443,342 443,245C443,134 389,58 296,58C233,58 180,100 164,161C162,172 160,184 160,197z"/>
|
||||
<glyph unicode="r" horiz-adv-x="327" d="M73,0l87,0l0,258C160,273 162,287 164,299C176,365 220,412 282,412C294,412 303,411 312,409l0,83C304,494 297,495 287,495C228,495 175,454 153,389l-4,0l-3,95l-77,0C72,439 73,390 73,333z"/>
|
||||
<glyph unicode=" " horiz-adv-x="212"/>
|
||||
<glyph unicode="t" horiz-adv-x="331" d="M93,573l0,-89l-75,0l0,-67l75,0l0,-264C93,96 102,53 127,27C148,3 181,-11 222,-11C256,-11 283,-5 300,2l-4,66C283,64 269,62 245,62C196,62 179,96 179,156l0,261l126,0l0,67l-126,0l0,116z"/>
|
||||
</font>
|
||||
|
||||
<g>
|
||||
<g>
|
||||
<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="418.2,95.1 418.2,101.1 412.2,101.1 "/>
|
||||
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="12.2842,12.2842" x1="399.9" y1="101.1" x2="37.5" y2="101.1"/>
|
||||
<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="31.4,101.1 25.4,101.1 25.4,95.1 "/>
|
||||
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="11.6852,11.6852" x1="25.4" y1="83.4" x2="25.4" y2="42.5"/>
|
||||
<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="25.4,36.6 25.4,30.6 31.4,30.6 "/>
|
||||
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="12.2842,12.2842" x1="43.6" y1="30.6" x2="406" y2="30.6"/>
|
||||
<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="412.2,30.6 418.2,30.6 418.2,36.6 "/>
|
||||
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="11.6852,11.6852" x1="418.2" y1="48.3" x2="418.2" y2="89.2"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect x="14.7" y="19.5" fill="none" stroke="#000000" stroke-miterlimit="10" width="414.1" height="92.7"/>
|
||||
<g>
|
||||
<rect x="34" y="58.4" fill="#349980" stroke="#000000" stroke-miterlimit="10" width="87.4" height="20.8"/>
|
||||
<text transform="matrix(1 0 0 1 55.2495 72.3085)" font-family="'MyriadPro-Bold'" font-size="12">Widget 1</text>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="144.1" y="48.3" fill="#349980" stroke="#000000" stroke-miterlimit="10" width="102.2" height="41"/>
|
||||
<text transform="matrix(1 0 0 1 172.7653 72.3085)" font-family="'MyriadPro-Bold'" font-size="12">Widget 2</text>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="275.8" y="44" fill="#349980" stroke="#000000" stroke-miterlimit="10" width="120" height="42.2"/>
|
||||
<text transform="matrix(1 0 0 1 313.3092 68.6263)" font-family="'MyriadPro-Bold'" font-size="12">Widget 3</text>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="15.9" y1="35.1" x2="24.2" y2="35.1"/>
|
||||
<g>
|
||||
<polygon points="17.9,36.8 16.2,35.1 17.9,33.4 16.4,33.4 14.7,35.1 16.4,36.8 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="22.2,36.8 23.9,35.1 22.2,33.4 23.7,33.4 25.4,35.1 23.7,36.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="419.3" y1="32.1" x2="427.7" y2="32.1"/>
|
||||
<g>
|
||||
<polygon points="421.3,33.8 419.6,32.1 421.3,30.4 419.9,30.4 418.2,32.1 419.9,33.8 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="425.7,33.8 427.4,32.1 425.7,30.4 427.1,30.4 428.8,32.1 427.1,33.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="395.8" y1="69.1" x2="418.2" y2="69.1"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="396.9" y1="69.1" x2="417" y2="69.1"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="398.9,70.8 397.2,69.1 398.9,67.4 397.5,67.4 395.8,69.1 397.5,70.8 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="415,70.8 416.7,69.1 415,67.4 416.5,67.4 418.2,69.1 416.5,70.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="245.7" y1="69.1" x2="275.8" y2="69.1"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="246.9" y1="69.1" x2="274.6" y2="69.1"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="248.9,70.8 247.2,69.1 248.9,67.4 247.4,67.4 245.7,69.1 247.4,70.8 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="272.6,70.8 274.3,69.1 272.6,67.4 274.1,67.4 275.8,69.1 274.1,70.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="122.5" y1="68.8" x2="143" y2="68.8"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="124.5,70.5 122.8,68.8 124.5,67.1 123.1,67.1 121.4,68.8 123.1,70.5 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="141,70.5 142.7,68.8 141,67.1 142.4,67.1 144.1,68.8 142.4,70.5 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="25.4" y1="71.1" x2="34" y2="71.1"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="26.5" y1="71.1" x2="32.9" y2="71.1"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="28.5,72.8 26.8,71.1 28.5,69.4 27.1,69.4 25.4,71.1 27.1,72.8 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="30.9,72.8 32.6,71.1 30.9,69.4 32.3,69.4 34,71.1 32.3,72.8 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="73.2" y1="58.9" x2="73.2" y2="30.6"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="73.2" y1="57.8" x2="73.2" y2="31.8"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="74.9,55.8 73.2,57.5 71.5,55.8 71.5,57.2 73.2,58.9 74.9,57.2 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="74.9,33.8 73.2,32.1 71.5,33.8 71.5,32.3 73.2,30.6 74.9,32.3 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="73.2" y1="100.7" x2="73.2" y2="79.2"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="73.2" y1="99.6" x2="73.2" y2="80.3"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="74.9,97.6 73.2,99.3 71.5,97.6 71.5,99 73.2,100.7 74.9,99 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="74.9,82.3 73.2,80.6 71.5,82.3 71.5,80.9 73.2,79.2 74.9,80.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="195.2" y1="100.6" x2="195.2" y2="89.9"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="195.2" y1="99.4" x2="195.2" y2="91.1"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="196.9,97.4 195.2,99.1 193.5,97.4 193.5,98.9 195.2,100.6 196.9,98.9 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="196.9,93.1 195.2,91.4 193.5,93.1 193.5,91.6 195.2,89.9 196.9,91.6 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="189.9" y1="48.3" x2="189.9" y2="30.6"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="189.9" y1="47.1" x2="189.9" y2="31.8"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="191.6,45.1 189.9,46.8 188.2,45.1 188.2,46.6 189.9,48.3 191.6,46.6 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="191.6,33.8 189.9,32.1 188.2,33.8 188.2,32.3 189.9,30.6 191.6,32.3 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="330.9" y1="101.1" x2="330.9" y2="86.2"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="330.9" y1="99.9" x2="330.9" y2="87.3"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="332.6,97.9 330.9,99.6 329.2,97.9 329.2,99.4 330.9,101.1 332.6,99.4 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="332.6,89.3 330.9,87.6 329.2,89.3 329.2,87.9 330.9,86.2 332.6,87.9 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="#13007C" x1="330.9" y1="44" x2="330.9" y2="30.6"/>
|
||||
<g>
|
||||
<line fill="none" stroke="#FF8000" stroke-miterlimit="10" x1="330.9" y1="42.9" x2="330.9" y2="31.8"/>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="332.6,40.9 330.9,42.6 329.2,40.9 329.2,42.3 330.9,44 332.6,42.3 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon fill="#FF8000" points="332.6,33.8 330.9,32.1 329.2,33.8 329.2,32.3 330.9,30.6 332.6,32.3 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="175.8" y1="111" x2="175.8" y2="102.7"/>
|
||||
<g>
|
||||
<polygon points="177.5,109.1 175.8,110.7 174.1,109.1 174.1,110.5 175.8,112.2 177.5,110.5 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="177.5,104.7 175.8,103 174.1,104.7 174.1,103.2 175.8,101.6 177.5,103.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<line fill="none" stroke="#000000" stroke-miterlimit="10" x1="172.8" y1="29" x2="172.8" y2="20.7"/>
|
||||
<g>
|
||||
<polygon points="174.5,27 172.8,28.7 171.1,27 171.1,28.4 172.8,30.1 174.5,28.4 "/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="174.5,22.6 172.8,20.9 171.1,22.6 171.1,21.2 172.8,19.5 174.5,21.2 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<text transform="matrix(1 0 0 1 175.7678 27.3395)" font-family="'MyriadPro-Regular'" font-size="10">top margin</text>
|
||||
<text transform="matrix(1 0 0 1 178.9794 109.875)" font-family="'MyriadPro-Regular'" font-size="10">bottom margin</text>
|
||||
<text transform="matrix(1 0 0 1 1.220703e-04 16.7404)" font-family="'MyriadPro-Regular'" font-size="10">left margin</text>
|
||||
<text transform="matrix(1 0 0 1 397.8374 16.7405)" font-family="'MyriadPro-Regular'" font-size="10">right margin</text>
|
||||
<text transform="matrix(1 0 0 1 199.7852 8.3701)" font-family="'MyriadPro-Bold'" font-size="10">Container</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 17 KiB |
13
kiwi/docs/source/use_cases/index.rst
Normal file
13
kiwi/docs/source/use_cases/index.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
.. _uses:
|
||||
|
||||
Kiwisolver real uses
|
||||
====================
|
||||
|
||||
The following sections describe how kiwisolver is used in third-party project,
|
||||
and aim at providing more involved example of how kiwisolver can be used in
|
||||
real life project.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
enaml.rst
|
||||
Reference in New Issue
Block a user