зеркало из https://github.com/mozilla/gecko-dev.git
Importing libart_lgpl from cvs.gnome.org. Version 2.3.7, plus Raph's
2001-11-07 changes to use the new intersector code. These files are licensed under the LGPL. a=brendan@mozilla.org
This commit is contained in:
Родитель
5e327bb122
Коммит
0382578602
|
@ -0,0 +1,33 @@
|
|||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
art_config.h
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
gen_art_config
|
||||
install-sh
|
||||
libart-features.h
|
||||
libtool
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
testart
|
||||
testuta
|
||||
libart2-config
|
||||
libartConf.sh
|
||||
libart-2.0.pc
|
|
@ -0,0 +1 @@
|
|||
Raph Levien <raph@acm.org>
|
|
@ -0,0 +1,482 @@
|
|||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
|
@ -0,0 +1,879 @@
|
|||
2001-11-07 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_horiz): Fixed important
|
||||
logic bug, failing to test crossings of neighbors when inserting
|
||||
horizontal lines. Also changed printf to art_dprint.
|
||||
|
||||
* art_misc.c (art_dprint): Added function for debug printing,
|
||||
so verbose intersector output doesn't have to go through printf.
|
||||
|
||||
* art_misc.h (ART_USE_NEW_INTERSECTOR): I've turned this on
|
||||
now, as the new intersector certainly seems to be performing
|
||||
better than the old one now.
|
||||
|
||||
2001-10-31 Anders Carlsson <andersca@gnu.org>
|
||||
|
||||
* Release 2.3.7
|
||||
|
||||
2001-10-15 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_horiz): Minor
|
||||
logic fix so that horiz segments successfully cross
|
||||
zero length segments in the active list.
|
||||
|
||||
(art_svp_intersect_test_cross): Flags indicating whether to
|
||||
do add_point (potentially breaking neighbors) to left and
|
||||
to right.
|
||||
|
||||
(art_svp_intersect_insert_cross): Provide ART_BREAK_LEFT and
|
||||
ART_BREAK_RIGHT flags to art_svp_intersect_test_cross,
|
||||
depending on direction of search.
|
||||
|
||||
(art_svp_intersect_advance_cursor): Provide flags (allow
|
||||
both left and right breaking) to test_cross.
|
||||
|
||||
2001-10-15 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (CHEAP_SANITYCHECK): Added an inexpensive
|
||||
sanitycheck to detect multiple insertions of a segment into the
|
||||
horiz list.
|
||||
|
||||
(art_svp_writer_rewind_add_point): Avoid breaking lines below
|
||||
their bottom point.
|
||||
|
||||
(art_svp_intersect_test_cross): Handle cases correctly where
|
||||
intersection point matches y0 of left or right segment. These _do_
|
||||
happen in real world examples. Also, do add_point on newly
|
||||
inserted intersection point.
|
||||
|
||||
2001-10-14 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_add_point): Fixed
|
||||
rather subtle logic bug that misplaced insertion point
|
||||
when seg argument was NULL.
|
||||
|
||||
2001-10-11 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa_iter_step): Got rid
|
||||
of qsort of steps, and now keep the step list in sorted order.
|
||||
Further, we combine duplicate steps with the same x value,
|
||||
which bounds the size of the step list to x1 - x0, so we
|
||||
don't need to dynamically resize it. Thanks greatly to
|
||||
Bruce Q. Hammond for the original version of this patch.
|
||||
|
||||
2001-10-09 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_test_cross): Breaks
|
||||
bottom part of line segments in "too close" cases.
|
||||
|
||||
2001-10-09 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_writer_rewind_add_point): Fixed
|
||||
bbox computation.
|
||||
(art_svp_intersector): Handle degenerate case where input
|
||||
SVP has 0 segments.
|
||||
|
||||
* art_svp_intersect.h: Moved definition of art_svp_intersector
|
||||
inside #ifdef __cplusplus, so it links properly against C++
|
||||
|
||||
2001-10-09 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_break): Handle
|
||||
case when break y equals sweep line correctly. Also adds
|
||||
first try at winding number sanitychecker, but that makes
|
||||
too many false positives.
|
||||
|
||||
2001-10-07 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp.c (EPSILON): Set to zero if new intersector is
|
||||
in use - we want svp's to be in strict sorted order.
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_test_cross): Explicitly
|
||||
check that top points are equal, and swap immediately if b is out
|
||||
of order.
|
||||
(art_svp_intersect_horiz): Break segments that intersect
|
||||
horizontal lines. Now passes "two squares with offset" test.
|
||||
|
||||
2001-10-05 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c: Major changes to accommodate
|
||||
horizontal lines. Intersections of horizontal lines
|
||||
aren't fully processed, but should work a lot better
|
||||
than before.
|
||||
|
||||
* testart.c: Minor tweaks. testpat now frees memory
|
||||
so it can be run under memprof to detect leaks.
|
||||
|
||||
2001-10-03 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_intersect.c (art_svp_intersect_advance_cursor):
|
||||
Made test_cross for inserted segments common between
|
||||
intersection processing and cursor advance, and also took
|
||||
care of a case that hadn't been handled before. Also added
|
||||
invariant sanitychecker for debugging purposes.
|
||||
|
||||
2001-10-02 Raph Levien <raph@pixel.artofcode.com>
|
||||
|
||||
* art_svp_ops.c: ART_USE_NEW_INTERSECTOR variants of svp
|
||||
ops changed to do shallow free of merged svp.
|
||||
|
||||
2001-10-01 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_intersect.c:
|
||||
* art_svp_intersect.h:
|
||||
* Makefile.am:
|
||||
* art_misc.h:
|
||||
* art_svp_wind.h: First commit of new intersector code. It is
|
||||
turned off by default, but can be enabled by #defining
|
||||
ART_USE_NEW_INTERSECTOR in art_misc.h.
|
||||
|
||||
* art_svp_ops.c: Make svp ops use new intersector if enabled.
|
||||
|
||||
* art_svp_vpath_stroke.c: Make vpath stroking use new intersector
|
||||
if enabled.
|
||||
|
||||
* testart.c: New test case for intersector.
|
||||
|
||||
Wed Sep 26 03:48:13 2001 George Lebl <jirka@5z.com>
|
||||
|
||||
* Release 2.3.6
|
||||
|
||||
Wed Sep 26 03:11:40 2001 George Lebl <jirka@5z.com>
|
||||
|
||||
* gen_art_config.c: Fix 64bit issues, cast sizeof return when
|
||||
using %d to print it.
|
||||
|
||||
2001-09-13 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* Makefile.am: rename library to libart_lgpl_2
|
||||
|
||||
* libart-2.0.pc.in (Cflags): move includes
|
||||
|
||||
* libart-config.in: move includes
|
||||
|
||||
* Makefile.am: delete libartConf.sh, rename libart-config
|
||||
(EXTRA_DIST): don't install m4 files
|
||||
(libart_lgplincdir): move headers
|
||||
|
||||
2001-08-03 Michael Meeks <michael@ximian.com>
|
||||
|
||||
* Version 2.3.5 for the API freeze.
|
||||
|
||||
2001-07-12 Darin Adler <darin@bentspoon.com>
|
||||
|
||||
* art_affine.c: (art_affine_expansion): Fix handling of
|
||||
negative numbers. We ran into this bug a while back when
|
||||
figuring out why librsvg couldn't handle certain svg files.
|
||||
|
||||
2001-07-12 Darin Adler <darin@bentspoon.com>
|
||||
|
||||
* art_misc.h: Change art_expand macro so it's a single
|
||||
statement, using the do while (0) trick, which gets rid
|
||||
of some warnings.
|
||||
* art_pixbuf.c: Add a missing include.
|
||||
* art_vpath_svp.c: (art_vpath_from_svp): Initialize a
|
||||
variable to avoid a compiler warning.
|
||||
* gen_art_config.c: Add a missing include.
|
||||
|
||||
2001-03-24 Martin Baulig <baulig@suse.de>
|
||||
|
||||
Applied the patch from Alexander Larsson which was sitting
|
||||
in gnome-libs/patches/libart.diff since February.
|
||||
[FIXME: Alex, can you please provide a ChangeLog?])
|
||||
|
||||
* art_rgb_a_affine.[ch]: New files.
|
||||
|
||||
2001-01-07 Hans Breuer <Hans@Breuer.Org>
|
||||
* art_misc.c : embryonic change to use libart_lgpl on win32
|
||||
* libart.def : new file, exported functions for win32 dll
|
||||
* makefile.msc : handwritten for MSVC compiler
|
||||
|
||||
2000-09-30 Martin Baulig <baulig@suse.de>
|
||||
|
||||
* libart-2.0.pc.in: Provide pkg-config script.
|
||||
|
||||
* configure.in: Create libart-2.0.pc from libart-2.0.pc.in.
|
||||
* Makefile.am (pkgconfig_DATA): Install the libart-2.0.pc
|
||||
script in `$(libdir)/pkgconfig'.
|
||||
|
||||
2000-08-15 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_render.c (art_render_image_solid_negotiate): Only
|
||||
sets ART_IMAGE_SOURCE_CAN_COMPOSITE when a compositing
|
||||
callback is selected. Previously was causing segfaults on
|
||||
non-alpha images. Thanks to Leonard Rosenthol for spotting
|
||||
the bug.
|
||||
|
||||
Fri Jun 30 22:56:58 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_render.c (art_render_composite): Fixed a bug that caused
|
||||
it to ignore the alpha setting. Also art_render_composite_8().
|
||||
|
||||
2000-06-01 John Sullivan <sullivan@eazel.com>
|
||||
|
||||
* art_svp_render_aa.c: (art_svp_render_aa_iter_step):
|
||||
Made it build by correcting struct member name from
|
||||
Raph's previous checkin.
|
||||
|
||||
Wed May 31 11:10:58 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa_iter_step): Updated
|
||||
n_steps_max in iter structure after steps reallocation.
|
||||
|
||||
Tue May 30 10:33:13 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa_iter_step): Fixed not
|
||||
updating iter->steps when steps gets reallocated.
|
||||
|
||||
2000-05-30 Pavel Cisler <pavel@eazel.com>
|
||||
|
||||
* art_rgba.c:
|
||||
Make it build -- fix a broken include.
|
||||
|
||||
Tue May 30 00:09:21 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_render_gradient.c (art_render_gradient_setpix): Fixed
|
||||
an off-by-one loop error.
|
||||
|
||||
Mon May 29 15:00:39 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* Makefile.am: Moved relevant .h files into HEADERS stanza.
|
||||
|
||||
Mon May 29 13:48:49 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
This is a fairly major commit, as it adds both the new, modular
|
||||
rendering architecture and gradients. Quite a bit of the code
|
||||
feels like "reference code" now, in that it is (hopefully)
|
||||
correct, but not necessarily very fast. In addition, there remain
|
||||
a few things not done, including the use of SVP's as non-driver
|
||||
mask sources. AlphaGamma and filter level also remain
|
||||
unimplemented. No compositing modes other than ART_NORMAL are
|
||||
implemented. All in good time!
|
||||
|
||||
* configure.in: added -Wmissing-prototypes flag. Bumped version
|
||||
number to 2.3.0.
|
||||
|
||||
* art_render.h:
|
||||
* art_render.c: Added new rendering architecture.
|
||||
|
||||
* art_render_svp.h:
|
||||
* art_render_svp.c: Added renderers to use SVP's as mask
|
||||
sources in new rendering architecture.
|
||||
|
||||
* art_render_gradient.h:
|
||||
* art_render_gradient.c: Added linear and radial gradients
|
||||
as image sources in new rendering architecture.
|
||||
|
||||
* art_rgba.h:
|
||||
* art_rgba.c: Added functions for manipulating and compositing
|
||||
RGBA pixels.
|
||||
|
||||
* art_svp_wind.c: Added static to trap_epsilon(), #ifdef'd out
|
||||
traverse().
|
||||
|
||||
* art_uta_ops.c: Added #include "art_uta_ops.h".
|
||||
|
||||
* art_uta_rect.c: Added #include "art_uta_rect.h".
|
||||
|
||||
* art_uta_svp.h: fixed __ART_UTA_SVP_H__ name.
|
||||
|
||||
* art_misc.h: Added ART_GNUC_NORETURN attribute, added that
|
||||
to the prototype for art_die(). Added "static" to function
|
||||
declarations to avoid warnings when compiled with
|
||||
|
||||
* testart.c: Added gradient test.
|
||||
|
||||
Thu May 25 23:30:39 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_render_aa.h:
|
||||
* art_svp_render_aa.c: Added art_svp_render_aa_iter functions,
|
||||
suitable for iterative rendering of an svp, one scan line at a
|
||||
time.
|
||||
|
||||
* configure.in: Bumped version to 2.2.0.
|
||||
|
||||
Tue May 16 15:03:35 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_rgb_pixbuf_affine.c: Included corresponding .h file.
|
||||
|
||||
* art_rgb_pixbuf_affine.h: Put recursive #includes inside
|
||||
LIBART_COMPILATION test.
|
||||
|
||||
* art_gray_svp.c:
|
||||
* art_rgb_svp.c: Explicit casts for callback data. Also removed
|
||||
"render the steps into tmpbuf" comment.
|
||||
|
||||
* gen_art_config.c:
|
||||
* Makefile.am:
|
||||
* configure.in: Added code to automatically generate an
|
||||
art_config.h file, to be installed in libart's include dir. This
|
||||
file defines ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}.
|
||||
|
||||
* art_misc.h: Moved definition of art_u8 and art_u32 into
|
||||
art_config.h. Added GCC printf format attributes.
|
||||
|
||||
* art_svp_wind.c (traverse): Fixed UMR bug here. The function
|
||||
isn't actually used, so it's just for cleanliness.
|
||||
|
||||
2000-04-18 Lauris Kaplinski <lauris@ariman.ee>
|
||||
|
||||
* art_affine.c (art_affine_to_string): Replaced snprinf with
|
||||
art_ftoa to avoid localisation of generated numbers
|
||||
|
||||
2000-04-18 ERDI Gergo <cactus@cactus.rulez.org>
|
||||
|
||||
* art_rgb_pixbuf_affine.h: Included the ArtPixBuf declaration
|
||||
|
||||
Fri Apr 14 16:33:55 2000 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_wind.c (art_svp_uncross, art_svp_rewind_uncrossed):
|
||||
Fixed uninitialized memory reads when inserting new segment into
|
||||
active_segs.
|
||||
|
||||
* art_bpath.c (art_bpath_affine_transform): Made it avoid
|
||||
potential uninitialized memory reads when not all the coordinates
|
||||
are needed. Thanks to Morten Welinder for spotting both of these
|
||||
problems.
|
||||
|
||||
2000-04-05 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_wind.c: Make "colinear" warnings go to stderr instead
|
||||
of stdout. Of course, when I finish the new intersector, these
|
||||
will go away entirely.
|
||||
|
||||
2000-04-04 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_uta_vpath.c (art_uta_add_line): Fixed bug that was causing
|
||||
segfaults on alphas. Thanks to msw for localizing it.
|
||||
|
||||
2000-01-17 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_vpath_stroke.c (art_svp_vpath_stroke): Typo in api
|
||||
header (thanks rak).
|
||||
|
||||
2000-01-16 Timur Bakeyev <timur@gnu.org>
|
||||
|
||||
* autoconf.sh: Instead of jumping between srdir and builddir just process
|
||||
all the auto* staff in srcdir. In fact, just saying the same things in
|
||||
other words.
|
||||
|
||||
2000-01-10 Elliot Lee <sopwith@redhat.com>
|
||||
|
||||
* Makefile.am, *.h: Add rather bad hacks to the header files to allow compilation
|
||||
|
||||
* Makefile.am: Distribute libart-config.in
|
||||
|
||||
2000-01-09 Raph Levien <raph@gimp.org>
|
||||
|
||||
art_rgb_pixbuf_affine.c, art_rgb_rgba_affine.c, art_rgb_svp.c,
|
||||
art_svp.c, art_svp_ops.c, art_svp_point.c, art_svp_render_aa.c,
|
||||
art_svp_vpath.c, art_svp_vpath_stroke.c, art_svp_wind.c,
|
||||
art_uta.c, art_uta_ops.c, art_uta_rect.c, art_uta_svp.c,
|
||||
art_uta_vpath.c, art_vpath.c, art_vpath_bpath.c, art_vpath_dash.c,
|
||||
art_vpath_svp.c: Added API documentation.
|
||||
|
||||
Fri Sep 24 17:53:21 1999 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_insert_active): Avoid
|
||||
reading undefined memory (thanks to Morten Welinder).
|
||||
|
||||
1999-09-19 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_pixbuf.c (art_pixbuf_duplicate): Added a duplicate function
|
||||
at the request of Michael Meeks.
|
||||
|
||||
1999-09-11 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.c (art_affine_to_string): Tightened the predicate for
|
||||
matching rotate-only affines, which was too weak. Thanks to lewing
|
||||
for spotting it!
|
||||
|
||||
1999-09-01 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.c, art_alphagamma.c, art_bpath.c, art_gray_svp.c,
|
||||
art_misc.c, art_pixbuf.c, art_rect.c, art_rect_svp.c,
|
||||
art_rect_uta.c, art_rgb.c, art_rgb_affine.c,
|
||||
art_rgb_bitmap_affine.c: Updates to api doc headers.
|
||||
|
||||
1999-08-24 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.c, art_alphagamma.c, art_alphagamma.h, art_bpath.c,
|
||||
art_bpath.h, art_gray_svp.c, art_misc.c, art_pixbuf.c,
|
||||
art_pixbuf.h, art_point.h, art_rect.c, art_rect.h: Added api
|
||||
documentation headers.
|
||||
|
||||
* testart.c: Added "dash" test, for testing the vpath_dash
|
||||
functions.
|
||||
|
||||
* art_rgb_pixbuf_affine.h: Fixed the #ifdef for conditional
|
||||
inclusion. Thanks to Kristian Hogsberg Kristensen for spotting
|
||||
the bug.
|
||||
|
||||
1999-08-24 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa): Added some tests to
|
||||
avoid NaN for infinite slopes, which were causing problems on
|
||||
Alphas. Closes bug #1966.
|
||||
|
||||
1999-08-20 Federico Mena Quintero <federico@redhat.com>
|
||||
|
||||
* configure.in: Fixed library's libtool version number.
|
||||
|
||||
1999-08-03 Larry Ewing <lewing@gimp.org>
|
||||
|
||||
* art_vpath_dash.c (art_vpath_dash): fix a bug/typo that was causing
|
||||
certain paths to loop infinitely.
|
||||
|
||||
1999-07-28 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_vpath_dash.[ch]: Added a function to add a dash style
|
||||
to vpaths. It is tested, but has a couple of rough edges (see
|
||||
code for details).
|
||||
|
||||
* testart.c: added tests for the new vpath_dash functionality.
|
||||
|
||||
* Makefile.am: added art_vpath_dash.[ch] files.
|
||||
|
||||
1999-07-26 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_rgb.c (art_rgb_fill_run): fixed incorrect test for
|
||||
big-endianness. Thanks to Michael Zucchi for spotting it.
|
||||
|
||||
Fri Jul 16 23:42:59 1999 Tim Janik <timj@gtk.org>
|
||||
|
||||
* art_affine.c (art_affine_flip): flip translation matrixes as well, by
|
||||
inverting matrix[4] if (horz) and inverting matrix[5] if (vert).
|
||||
|
||||
Fri Jul 16 23:03:26 1999 Tim Janik <timj@gtk.org>
|
||||
|
||||
* art_pixbuf.[hc]: deprecated art_pixbuf_free_shallow(), people should
|
||||
always free pixbufs with art_pixbuf_free() and use the _dnotify variants
|
||||
for specific destruction behaviour.
|
||||
added art_pixbuf_new_rgb_dnotify() and art_pixbuf_new_rgba_dnotify()
|
||||
which allow for a destruction notification function. (this involved
|
||||
adding two extra pointers to the ArtPixBuf structure, and removal of
|
||||
the recently introduced int flags field).
|
||||
|
||||
Mon Jul 12 01:13:23 1999 Tim Janik <timj@gtk.org>
|
||||
|
||||
* art_affine.[hc]: added art_affine_equal(), which checks two
|
||||
matrixes for equality within grid alignment.
|
||||
|
||||
Fri Jul 9 17:50:19 1999 Tim Janik <timj@gtk.org>
|
||||
|
||||
* art_affine.[hc]: added art_affine_flip() to flip a matrix horizontally
|
||||
and/or vertically, or just copy it.
|
||||
added art_affine_shear() to setup a shearing matrix.
|
||||
|
||||
Tue Jul 6 19:03:39 1999 Tim Janik <timj@gtk.org>
|
||||
|
||||
* art_pixbuf.h: added an int flags; member to the end of the
|
||||
structure, it currently only holds information about whether the
|
||||
pixels member should be freed. (raph: i think flags is more generic
|
||||
than free_pixels, so we can reuse that field if further demands popup
|
||||
in the future).
|
||||
|
||||
* art_pixbuf.c:
|
||||
(art_pixbuf_new_const_rgba):
|
||||
(art_pixbuf_new_const_rgb): new functions that prevent the pixels
|
||||
member from being freed upon art_pixbuf_free ().
|
||||
(art_pixbuf_free): only free the pixels member if it is non-NULL and
|
||||
the PIXBUF_FLAG_DESTROY_PIXELS is set.
|
||||
|
||||
1999-07-02 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_vpath_bpath.c (art_vpath_render_bez): Bad bad uninitialized
|
||||
variables.
|
||||
|
||||
* configure.in: added compile warnings. Guess why :)
|
||||
|
||||
1999-06-28 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_point.h:
|
||||
* art_svp_point.c: Added methods for insideness and distance
|
||||
testing, very useful for ::point methods in canvas items.
|
||||
|
||||
* testart.c: test code to exercise the art_svp_point functions.
|
||||
|
||||
* Makefile.am: Additional entries for art_svp_point.
|
||||
|
||||
1999-06-28 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa): Subtle boundary
|
||||
case in realloc code -- was causing nasty segfaults.
|
||||
|
||||
Wed Jun 23 15:05:43 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_rgb_svp.c (art_rgb_svp_alpha_opaque_callback): Missed a
|
||||
case in the anti-segfault crusade. Thanks lewing!
|
||||
|
||||
Wed Jun 23 11:16:42 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_rgb_svp.c: Made these routines so they won't segfault even
|
||||
if alpha is out of range. Of course, that begs the question of
|
||||
fixing the render routines so they won't _make_ alpha go out of
|
||||
range, but all in good time.
|
||||
|
||||
Fri Jun 18 17:32:34 1999 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_vpath_bpath.c (art_bez_path_to_vec): Switched to a new
|
||||
adaptive subdivision algorithm, which (finally!) takes flatness
|
||||
into account. This should result in both smoother curves and
|
||||
faster operation.
|
||||
|
||||
Sun Jun 13 21:07:20 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_wind.c (art_svp_rewind_uncrossed): Made the winding
|
||||
rule logic even more correct :). I somehow missed the fact that
|
||||
a clockwise path should be given a winding number of zero;
|
||||
last night's commit tried to make it -1 (which worked for the
|
||||
test cases I was using).
|
||||
|
||||
Sun Jun 13 01:23:14 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_wind.c (art_svp_rewind_uncrossed): Change to winding
|
||||
rule logic so that it correctly handles the case where the
|
||||
leftmost segment is negative.
|
||||
|
||||
* Makefile.am (libart_lgplinc_HEADERS): made art_svp_wind.h
|
||||
a public headerfile. This is needed for the bpath canvas item.
|
||||
I'm not sure this is the correct way to do it, but it will do
|
||||
for now.
|
||||
|
||||
* art_vpath_bpath.h:
|
||||
* art_vpath_bpath.c (art_bez_path_to_vec): Added const to arg.
|
||||
|
||||
* art_vpath_bpath.h: Embarrassing typo.
|
||||
|
||||
* art_bpath.h: Minor tweaks to the #include paths. It is now
|
||||
consistent with the other header files.
|
||||
|
||||
Wed Jun 9 20:24:45 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_vpath_stroke.c: Added all remaining line join and cap
|
||||
types, including round, which takes flatness into account. Several
|
||||
new internal functions (art_svp_vpath_stroke_arc) and added
|
||||
flatness argument to a few internal functions. I might want to
|
||||
change the BEVEL join type to MITER for very small turn angles
|
||||
(i.e. within a flatness threshold) for efficiency.
|
||||
|
||||
* art_misc.h: Added M_SQRT2 constant.
|
||||
|
||||
Wed Jun 2 21:56:30 1999 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): Made the
|
||||
closed path detection capable of PostScript semantics (i.e. it
|
||||
now senses the difference between ART_MOVETO and ART_MOVETO_OPEN).
|
||||
|
||||
* art_svp_vpath_stroke.c (art_svp_vpath_stroke_raw): it now
|
||||
filters out successive points that are (nearly) coincident. This
|
||||
fixes some of the crashes and hangs, including Tim Janik's
|
||||
singularity (trying to stroke MOVETO 50, 50; LINETO 50, 50; END).
|
||||
|
||||
* art_svp_wind.c (art_svp_rewind_uncrossed): added a test to
|
||||
correctly handle empty input svp's.
|
||||
|
||||
* art_svp_wind.c (art_svp_uncross): added a test to correctly
|
||||
handle empty input svp's.
|
||||
|
||||
Sun Jan 17 20:53:40 1999 Jeff Garzik <jgarzik@pobox.com>
|
||||
|
||||
* art_affine.c:
|
||||
Include string.h for memcpy.
|
||||
|
||||
* art_svp_vpath.c:
|
||||
Remove conflicting static func definition.
|
||||
|
||||
* art_uta_svp.c:
|
||||
Include art_vpath_svp.h for func definition.
|
||||
|
||||
Mon Jan 4 12:47:47 1999 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_bpath.c (art_bpath_affine_transform): Stupid misnaming
|
||||
of this function (forgot the "art_").
|
||||
|
||||
Thu Dec 31 09:04:23 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.c (art_affine_rectilinear): Added this function.
|
||||
|
||||
* art_rect.c (art_drect_affine_transform): Corrected the name (it
|
||||
was right in the .h). Also made it work with non-rectilinear
|
||||
transforms, while I was at it.
|
||||
|
||||
Thu Dec 17 11:58:24 1998 Raph Levien <raph@acm.org>
|
||||
|
||||
* art_alphagamma.h:
|
||||
* art_alphagamma.c: The real code for alphagamma.
|
||||
|
||||
Wed Dec 16 14:18:46 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_alphagamma.h:
|
||||
* art_alphagamma.c: Added. At present, it only contains a dummy
|
||||
stub. When the real code is added, it supports doing alpha
|
||||
compositing in a gamma-corrected color space (suppressing
|
||||
jaggies).
|
||||
|
||||
* art_pixbuf.h:
|
||||
* art_pixbuf.c: Added. This is a virtualization layer over
|
||||
a few different kinds of image formats.
|
||||
|
||||
* art_rgb_pixbuf_affine.h:
|
||||
* art_rgb_pixbuf_affine.c: Added. Supports compositing of
|
||||
generic images over an rgb buffer.
|
||||
|
||||
* art_affine.h:
|
||||
* art_affine.c (art_affine_expansion): Added this function,
|
||||
which reports the exact scale factor in the case of rotation,
|
||||
scaling, and transformation (an approximate number in the
|
||||
case of shearing or anamorphic distortion).
|
||||
|
||||
* art_misc.h:
|
||||
* art_misc.c (art_warn): Added.
|
||||
|
||||
* art_rgb_affine.h:
|
||||
* art_rgb_affine.c: Added alphagamma argument (not yet implemented).
|
||||
|
||||
* art_rgb_affine_private.c: Fixed typo bug that was causing
|
||||
repaint problems for nonsquare images.
|
||||
|
||||
* art_rgb_bitmap_affine.h:
|
||||
* art_rgb_bitmap_affine.c: Major speed improvement, probably fixed
|
||||
correctness while I was at it. Added alphagamma argument (not yet
|
||||
implemented).
|
||||
|
||||
* art_rgb_svp.h:
|
||||
* art_rgb_svp.c: Added alphagamma argument (only implemented
|
||||
in aa case, not yet alpha case).
|
||||
|
||||
* art_vpath.c: increased perturbation to 2e-3, because the old
|
||||
value (1e-6) was too small.
|
||||
|
||||
* testart.c: added alphagamma.
|
||||
|
||||
* Makefile.am: added new files
|
||||
|
||||
Sun Dec 27 21:45:03 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_rect.h:
|
||||
* art_rect.c: Added DRect versions of the basic ops (double
|
||||
rather than int).
|
||||
|
||||
* art_rect_svp.h:
|
||||
* art_rect_svp.c: Added. This computes the bounding box of
|
||||
an svp.
|
||||
|
||||
Wed Dec 16 14:18:46 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_alphagamma.h:
|
||||
* art_alphagamma.c: Added. At present, it only contains a dummy
|
||||
stub. When the real code is added, it supports doing alpha
|
||||
compositing in a gamma-corrected color space (suppressing
|
||||
jaggies).
|
||||
|
||||
* art_pixbuf.h:
|
||||
* art_pixbuf.c: Added. This is a virtualization layer over
|
||||
a few different kinds of image formats.
|
||||
|
||||
* art_rgb_pixbuf_affine.h:
|
||||
* art_rgb_pixbuf_affine.c: Added. Supports compositing of
|
||||
generic images over an rgb buffer.
|
||||
|
||||
* art_affine.h:
|
||||
* art_affine.c (art_affine_expansion): Added this function,
|
||||
which reports the exact scale factor in the case of rotation,
|
||||
scaling, and transformation (an approximate number in the
|
||||
case of shearing or anamorphic distortion).
|
||||
|
||||
* art_misc.h:
|
||||
* art_misc.c (art_warn): Added.
|
||||
|
||||
* art_rgb_affine.h:
|
||||
* art_rgb_affine.c: Added alphagamma argument (not yet implemented).
|
||||
|
||||
* art_rgb_affine_private.c: Fixed typo bug that was causing
|
||||
repaint problems for nonsquare images.
|
||||
|
||||
* art_rgb_bitmap_affine.h:
|
||||
* art_rgb_bitmap_affine.c: Major speed improvement, probably fixed
|
||||
correctness while I was at it. Added alphagamma argument (not yet
|
||||
implemented).
|
||||
|
||||
* art_rgb_svp.h:
|
||||
* art_rgb_svp.c: Added alphagamma argument (only implemented
|
||||
in aa case, not yet alpha case).
|
||||
|
||||
* art_vpath.c: increased perturbation to 2e-3, because the old
|
||||
value (1e-6) was too small.
|
||||
|
||||
* testart.c: added alphagamma.
|
||||
|
||||
* Makefile.am: added new files
|
||||
|
||||
Mon Dec 14 00:16:53 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.c (art_affine_to_string): re-added the "scale" method
|
||||
that was accidentally deleted before check-in.
|
||||
|
||||
* Makefile.am: added new files
|
||||
|
||||
Sun Dec 13 00:52:39 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_affine.h:
|
||||
* art_affine.c: Added. Everything you ever wanted to do with an
|
||||
affine transform. Especially check the functions that generate
|
||||
concise PostScript strings for affine transforms.
|
||||
|
||||
* art_filterlevel.h: A simple enum for selecting filtering
|
||||
style.
|
||||
|
||||
* art_rgb_affine.h:
|
||||
* art_rgb_affine.c (art_rgb_affine): Added. This function
|
||||
composites an (opaque) rgb image over an rgb pixel buffer. At
|
||||
present, it's slow and only nearest neighbor filtering is enabled.
|
||||
|
||||
* art_rgb_rgba_affine.h:
|
||||
* art_rgb_rgba_affine.c: Analogous, but for compositing rgba
|
||||
images.
|
||||
|
||||
* art_rgb_bitmap_affine.h:
|
||||
* art_rgb_bitmap_affine.c: Analogous, but for compositing bitmap
|
||||
images.
|
||||
|
||||
* art_rgb_affine_private.c (art_rgb_affine_run): Added. This is
|
||||
a common function used by all the rgb_affine modules to move
|
||||
testing for source image bbox out of the inner loop.
|
||||
|
||||
* Makefile.am: added the new files
|
||||
|
||||
* testart.c: exercise the image compositors
|
||||
|
||||
Wed Dec 9 23:36:35 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_vpath.c (art_vpath_perturb): Made it deal correctly
|
||||
with closed paths (the MOVETO and closing LINETO have to
|
||||
agree).
|
||||
|
||||
* art_svp_wind.c: Made the bbox calculations for the resulting
|
||||
svp's correct.
|
||||
|
||||
* art_svp.h:
|
||||
* art_svp.c: The art_svp_seg_compare function moved here, because
|
||||
it's required in art_svp_ops.
|
||||
|
||||
* art_svp.c (art_svp_add_segment): It now does bbox calculations.
|
||||
|
||||
* art_svp_ops.h:
|
||||
* art_svp_ops.c: Added. Populated with basic union, intersection,
|
||||
and diff functions.
|
||||
|
||||
* art_vpath_svp.h:
|
||||
* art_vpath_svp.c: Added. Populated with a function to convert
|
||||
from sorted to unsorted vector paths
|
||||
|
||||
* Makefile.am: added the new files
|
||||
|
||||
* testart.c: exercise the stroke outline and vector path
|
||||
operations.
|
||||
|
||||
1998-12-08 Herbert Valerio Riedel <hvr@hvrlab.ml.org>
|
||||
|
||||
* art_svp_wind.c: added #include <string.h> for memcpy()
|
||||
|
||||
Sun Dec 6 22:15:12 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_wind.[ch], art_svp_vpath_stroke.[ch]: Added, but it
|
||||
doesn't work yet. These will do stroke outline and basic
|
||||
vector ops like union, intersect, etc.
|
||||
|
||||
* art_svp_render_aa.c: Added a simple speedup based on bbox
|
||||
culling. I will want to do more speedups, but none of this is
|
||||
necessary for the freeze.
|
||||
|
||||
* art_svp_vpath.c: Fixed some bugs in the art_svp_from_vpath in
|
||||
cases where there is more than one subpath.
|
||||
|
||||
* art_vpath.h:
|
||||
* art_vpath.c (art_vpath_perturb): Added this function. This will
|
||||
help cheat as long as the basic vector ops have numerical
|
||||
stability problems.
|
||||
|
||||
Fri Dec 4 18:00:38 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp_render_aa.c (art_svp_render_aa): Changed the api
|
||||
slightly, to guarantee that the steps are all within the range
|
||||
from x0 (inclusive) to x1 (exclusive).
|
||||
|
||||
* art_gray_svp.c, art_gray_svp.h: Added. Populated with functions
|
||||
to render into a simple graymap.
|
||||
|
||||
* art_rgb.c, art_rgb.c: Added. Populated with fill_run and
|
||||
run_alpha methods.
|
||||
|
||||
* art_rgb_svp.c, art_rgb_svp.h: Added. Populated with functions to
|
||||
render into an RGB buffer, and to composite over an RGB buffer.
|
||||
|
||||
* Makefile.am: added art_gray_svp, art_rgb, and art_rgb_svp.
|
||||
|
||||
* testart.c: test the color and layered rendering.
|
||||
|
||||
Mon Nov 30 01:30:25 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* testart.c: added vector path rendering stuff. Some of it needs
|
||||
to go out of the test framework and into the module, but the
|
||||
api hasn't settled down entirely yet (in the real code, all
|
||||
x's in the step field are within bounds).
|
||||
|
||||
* art_svp_render_aa.c, art_svp_render_aa.c.h: added.
|
||||
|
||||
* art_svp_vpath.c, art_svp_vpath.h: added.
|
||||
|
||||
* art_pathcode.h: added ART_MOVETO_OPEN (libart uses an
|
||||
ART_MOVETO_OPEN code at the beginning to indicate an open path,
|
||||
while PostScript uses the lack of a closepath at the end).
|
||||
|
||||
* art_vpath_bpath.c, art_vpath_bpath.h: fixed it up, added
|
||||
flatness arg to api.
|
||||
|
||||
* Makefile.am: added new source files.
|
||||
|
||||
Wed Nov 25 17:19:44 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_svp.h, art_svp.c: added, basic constructors for sorted
|
||||
vector paths.
|
||||
|
||||
Sun Nov 22 23:21:09 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* Makefile.am (libart_lgplincdir): Fixed stupid bug in naming of
|
||||
the variable.
|
||||
|
||||
Sun Nov 22 21:41:13 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* art_uta_vpath.c: moved art_uta_union into art_uta_ops.
|
||||
|
||||
* art_uta_ops.[ch]: added, populated with art_uta_union.
|
||||
|
||||
Thu Nov 19 00:19:40 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* libartConf.sh.in: added
|
||||
|
||||
* Makefile.am: added creation of libartConf.sh, added -version-info
|
||||
* configure.in: added LIBART_VERSION_INFO, support for libartConf.sh
|
||||
|
||||
* libart.m4: updated version history :)
|
||||
|
||||
Wed Nov 18 18:15:20 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* configure.in (LIBART_VERSION): set this, so that libart-config
|
||||
--version now works.
|
||||
|
||||
Wed Nov 18 16:50:58 1998 Raph Levien <raph@gimp.org>
|
||||
|
||||
* libart.m4: added (just copied from esound)
|
||||
* configure.in, Makefile.am: added support for libart-config
|
||||
* libart-config.in: added (mostly copied from esound)
|
||||
|
||||
Tue Nov 10 12:43:30 1998 Raph Levien <raph@acm.org>
|
||||
|
||||
* Getting the library in shape for initial checkin to CVS.
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
noinst_PROGRAMS = testart testuta gen_art_config
|
||||
|
||||
bin_SCRIPTS = \
|
||||
libart2-config
|
||||
|
||||
BUILT_SOURCES = art_config.h
|
||||
|
||||
art_config.h: gen_art_config
|
||||
./gen_art_config > art_config.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
libart-config.in \
|
||||
libart-2.0.pc.in
|
||||
|
||||
lib_LTLIBRARIES = libart_lgpl_2.la
|
||||
|
||||
libart_lgpl_2_la_SOURCES = \
|
||||
art_affine.c \
|
||||
art_alphagamma.c \
|
||||
art_bpath.c \
|
||||
art_gray_svp.c \
|
||||
art_misc.c \
|
||||
art_pixbuf.c \
|
||||
art_rect.c \
|
||||
art_rect_svp.c \
|
||||
art_rect_uta.c \
|
||||
art_render.c \
|
||||
art_render_gradient.c \
|
||||
art_render_svp.c \
|
||||
art_rgb.c \
|
||||
art_rgb_affine.c \
|
||||
art_rgb_affine_private.c \
|
||||
art_rgb_affine_private.h \
|
||||
art_rgb_bitmap_affine.c \
|
||||
art_rgb_pixbuf_affine.c \
|
||||
art_rgb_rgba_affine.c \
|
||||
art_rgb_a_affine.c \
|
||||
art_rgba.c \
|
||||
art_rgb_svp.c \
|
||||
art_svp.c \
|
||||
art_svp_intersect.c \
|
||||
art_svp_ops.c \
|
||||
art_svp_point.c \
|
||||
art_svp_render_aa.c \
|
||||
art_svp_vpath.c \
|
||||
art_svp_vpath_stroke.c \
|
||||
art_svp_wind.c \
|
||||
art_uta.c \
|
||||
art_uta_ops.c \
|
||||
art_uta_rect.c \
|
||||
art_uta_vpath.c \
|
||||
art_uta_svp.c \
|
||||
art_vpath.c \
|
||||
art_vpath_bpath.c \
|
||||
art_vpath_dash.c \
|
||||
art_vpath_svp.c \
|
||||
libart-features.c
|
||||
|
||||
libart_lgpl_2_la_LDFLAGS = -version-info @LIBART_VERSION_INFO@
|
||||
|
||||
libart_lgplincdir = $(includedir)/libart-2.0/libart_lgpl
|
||||
libart_lgplinc_HEADERS = \
|
||||
art_affine.h \
|
||||
art_alphagamma.h \
|
||||
art_bpath.h \
|
||||
art_config.h \
|
||||
art_filterlevel.h \
|
||||
art_gray_svp.h \
|
||||
art_misc.h \
|
||||
art_pathcode.h \
|
||||
art_pixbuf.h \
|
||||
art_point.h \
|
||||
art_rect.h \
|
||||
art_rect_svp.h \
|
||||
art_rect_uta.h \
|
||||
art_render.h \
|
||||
art_render_gradient.h \
|
||||
art_render_svp.h \
|
||||
art_rgb.h \
|
||||
art_rgb_affine.h \
|
||||
art_rgb_bitmap_affine.h \
|
||||
art_rgb_pixbuf_affine.h \
|
||||
art_rgb_rgba_affine.h \
|
||||
art_rgb_a_affine.h \
|
||||
art_rgb_svp.h \
|
||||
art_rgba.h \
|
||||
art_svp.h \
|
||||
art_svp_intersect.h \
|
||||
art_svp_ops.h \
|
||||
art_svp_point.h \
|
||||
art_svp_render_aa.h \
|
||||
art_svp_vpath.h \
|
||||
art_svp_vpath_stroke.h \
|
||||
art_svp_wind.h \
|
||||
art_uta.h \
|
||||
art_uta_ops.h \
|
||||
art_uta_rect.h \
|
||||
art_uta_vpath.h \
|
||||
art_uta_svp.h \
|
||||
art_vpath.h \
|
||||
art_vpath_bpath.h \
|
||||
art_vpath_dash.h \
|
||||
art_vpath_svp.h \
|
||||
libart.h \
|
||||
libart-features.h
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_builddir) -DLIBART_COMPILATION
|
||||
|
||||
DEPS = $(top_builddir)/libart_lgpl_2.la
|
||||
LDADDS = $(top_builddir)/libart_lgpl_2.la
|
||||
|
||||
testart_SOURCES=testart.c
|
||||
testart_LDFLAGS =
|
||||
testart_DEPENDENCIES = $(DEPS)
|
||||
testart_LDADD = $(LDADDS) -lm
|
||||
|
||||
testuta_SOURCES=testuta.c
|
||||
testuta_LDFLAGS =
|
||||
testuta_DEPENDENCIES = $(DEPS)
|
||||
testuta_LDADD = $(LDADDS) -lm
|
||||
|
||||
tests: testart testuta
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libart-2.0.pc
|
||||
|
||||
libart2-config: libart-config
|
||||
cp -f libart-config libart2-config
|
|
@ -0,0 +1 @@
|
|||
Please see http://www.levien.com/libart/ for the latest news.
|
|
@ -0,0 +1,15 @@
|
|||
This is the LGPL'd component of libart. All functions needed for
|
||||
running the Gnome canvas, and for printing support, will be going in
|
||||
here. The GPL'd component will be getting various enhanced functions
|
||||
for specific applications.
|
||||
|
||||
Libart is free software. It is also for sale. For information about
|
||||
licensing libart, please contact Raph Levien
|
||||
<raph@acm.org>. Contributions to the codebase are also very welcome,
|
||||
but the copyright must be assigned in writing to preserve the
|
||||
licensing flexibility.
|
||||
|
||||
|
||||
For more information about libart, see the web page:
|
||||
|
||||
http://www.levien.com/libart/
|
|
@ -0,0 +1,14 @@
|
|||
Welcome to the libart source tree!
|
||||
|
||||
This code is being developed in a "free software for sale"
|
||||
model. Thus, it's available under a free software license (LGPL for
|
||||
this module), but I'm also requesting that for all changes to the code
|
||||
the copyright gets assigned back to me.
|
||||
|
||||
So if you want to contribute, please do, but contact me about getting
|
||||
the copyright assigned. Otherwise, I will have to back your changes
|
||||
out.
|
||||
|
||||
Thanks!
|
||||
|
||||
Raph Levien <raph@acm.org>
|
|
@ -0,0 +1,2 @@
|
|||
#undef PACKAGE
|
||||
#undef VERSION
|
|
@ -0,0 +1,457 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Simple manipulations with affine transformations */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h> /* for sprintf */
|
||||
#include <string.h> /* for strcpy */
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
|
||||
|
||||
/* According to a strict interpretation of the libart structure, this
|
||||
routine should go into its own module, art_point_affine. However,
|
||||
it's only two lines of code, and it can be argued that it is one of
|
||||
the natural basic functions of an affine transformation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* art_affine_point: Do an affine transformation of a point.
|
||||
* @dst: Where the result point is stored.
|
||||
* @src: The original point.
|
||||
@ @affine: The affine transformation.
|
||||
**/
|
||||
void
|
||||
art_affine_point (ArtPoint *dst, const ArtPoint *src,
|
||||
const double affine[6])
|
||||
{
|
||||
double x, y;
|
||||
|
||||
x = src->x;
|
||||
y = src->y;
|
||||
dst->x = x * affine[0] + y * affine[2] + affine[4];
|
||||
dst->y = x * affine[1] + y * affine[3] + affine[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_invert: Find the inverse of an affine transformation.
|
||||
* @dst: Where the resulting affine is stored.
|
||||
* @src: The original affine transformation.
|
||||
*
|
||||
* All non-degenerate affine transforms are invertible. If the original
|
||||
* affine is degenerate or nearly so, expect numerical instability and
|
||||
* very likely core dumps on Alpha and other fp-picky architectures.
|
||||
* Otherwise, @dst multiplied with @src, or @src multiplied with @dst
|
||||
* will be (to within roundoff error) the identity affine.
|
||||
**/
|
||||
void
|
||||
art_affine_invert (double dst[6], const double src[6])
|
||||
{
|
||||
double r_det;
|
||||
|
||||
r_det = 1.0 / (src[0] * src[3] - src[1] * src[2]);
|
||||
dst[0] = src[3] * r_det;
|
||||
dst[1] = -src[1] * r_det;
|
||||
dst[2] = -src[2] * r_det;
|
||||
dst[3] = src[0] * r_det;
|
||||
dst[4] = -src[4] * dst[0] - src[5] * dst[2];
|
||||
dst[5] = -src[4] * dst[1] - src[5] * dst[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_flip: Flip an affine transformation horizontally and/or vertically.
|
||||
* @dst_affine: Where the resulting affine is stored.
|
||||
* @src_affine: The original affine transformation.
|
||||
* @horiz: Whether or not to flip horizontally.
|
||||
* @vert: Whether or not to flip horizontally.
|
||||
*
|
||||
* Flips the affine transform. FALSE for both @horiz and @vert implements
|
||||
* a simple copy operation. TRUE for both @horiz and @vert is a
|
||||
* 180 degree rotation. It is ok for @src_affine and @dst_affine to
|
||||
* be equal pointers.
|
||||
**/
|
||||
void
|
||||
art_affine_flip (double dst_affine[6], const double src_affine[6], int horz, int vert)
|
||||
{
|
||||
dst_affine[0] = horz ? - src_affine[0] : src_affine[0];
|
||||
dst_affine[1] = horz ? - src_affine[1] : src_affine[1];
|
||||
dst_affine[2] = vert ? - src_affine[2] : src_affine[2];
|
||||
dst_affine[3] = vert ? - src_affine[3] : src_affine[3];
|
||||
dst_affine[4] = horz ? - src_affine[4] : src_affine[4];
|
||||
dst_affine[5] = vert ? - src_affine[5] : src_affine[5];
|
||||
}
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
/* It's ridiculous I have to write this myself. This is hardcoded to
|
||||
six digits of precision, which is good enough for PostScript.
|
||||
|
||||
The return value is the number of characters (i.e. strlen (str)).
|
||||
It is no more than 12. */
|
||||
static int
|
||||
art_ftoa (char str[80], double x)
|
||||
{
|
||||
char *p = str;
|
||||
int i, j;
|
||||
|
||||
p = str;
|
||||
if (fabs (x) < EPSILON / 2)
|
||||
{
|
||||
strcpy (str, "0");
|
||||
return 1;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
*p++ = '-';
|
||||
x = -x;
|
||||
}
|
||||
if ((int)floor ((x + EPSILON / 2) < 1))
|
||||
{
|
||||
*p++ = '0';
|
||||
*p++ = '.';
|
||||
i = sprintf (p, "%06d", (int)floor ((x + EPSILON / 2) * 1e6));
|
||||
while (i && p[i - 1] == '0')
|
||||
i--;
|
||||
if (i == 0)
|
||||
i--;
|
||||
p += i;
|
||||
}
|
||||
else if (x < 1e6)
|
||||
{
|
||||
i = sprintf (p, "%d", (int)floor (x + EPSILON / 2));
|
||||
p += i;
|
||||
if (i < 6)
|
||||
{
|
||||
int ix;
|
||||
|
||||
*p++ = '.';
|
||||
x -= floor (x + EPSILON / 2);
|
||||
for (j = i; j < 6; j++)
|
||||
x *= 10;
|
||||
ix = floor (x + 0.5);
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
ix *= 10;
|
||||
|
||||
/* A cheap hack, this routine can round wrong for fractions
|
||||
near one. */
|
||||
if (ix == 1000000)
|
||||
ix = 999999;
|
||||
|
||||
sprintf (p, "%06d", ix);
|
||||
i = 6 - i;
|
||||
while (i && p[i - 1] == '0')
|
||||
i--;
|
||||
if (i == 0)
|
||||
i--;
|
||||
p += i;
|
||||
}
|
||||
}
|
||||
else
|
||||
p += sprintf (p, "%g", x);
|
||||
|
||||
*p = '\0';
|
||||
return p - str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
/**
|
||||
* art_affine_to_string: Convert affine transformation to concise PostScript string representation.
|
||||
* @str: Where to store the resulting string.
|
||||
* @src: The affine transform.
|
||||
*
|
||||
* Converts an affine transform into a bit of PostScript code that
|
||||
* implements the transform. Special cases of scaling, rotation, and
|
||||
* translation are detected, and the corresponding PostScript
|
||||
* operators used (this greatly aids understanding the output
|
||||
* generated). The identity transform is mapped to the null string.
|
||||
**/
|
||||
void
|
||||
art_affine_to_string (char str[128], const double src[6])
|
||||
{
|
||||
char tmp[80];
|
||||
int i, ix;
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
double d = rand () * .1 / RAND_MAX;
|
||||
art_ftoa (tmp, d);
|
||||
printf ("%g %f %s\n", d, d, tmp);
|
||||
}
|
||||
#endif
|
||||
if (fabs (src[4]) < EPSILON && fabs (src[5]) < EPSILON)
|
||||
{
|
||||
/* could be scale or rotate */
|
||||
if (fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON)
|
||||
{
|
||||
/* scale */
|
||||
if (fabs (src[0] - 1) < EPSILON && fabs (src[3] - 1) < EPSILON)
|
||||
{
|
||||
/* identity transform */
|
||||
str[0] = '\0';
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix = 0;
|
||||
ix += art_ftoa (str + ix, src[0]);
|
||||
str[ix++] = ' ';
|
||||
ix += art_ftoa (str + ix, src[3]);
|
||||
strcpy (str + ix, " scale");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* could be rotate */
|
||||
if (fabs (src[0] - src[3]) < EPSILON &&
|
||||
fabs (src[1] + src[2]) < EPSILON &&
|
||||
fabs (src[0] * src[0] + src[1] * src[1] - 1) < 2 * EPSILON)
|
||||
{
|
||||
double theta;
|
||||
|
||||
theta = (180 / M_PI) * atan2 (src[1], src[0]);
|
||||
art_ftoa (tmp, theta);
|
||||
sprintf (str, "%s rotate", tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* could be translate */
|
||||
if (fabs (src[0] - 1) < EPSILON && fabs (src[1]) < EPSILON &&
|
||||
fabs (src[2]) < EPSILON && fabs (src[3] - 1) < EPSILON)
|
||||
{
|
||||
ix = 0;
|
||||
ix += art_ftoa (str + ix, src[4]);
|
||||
str[ix++] = ' ';
|
||||
ix += art_ftoa (str + ix, src[5]);
|
||||
strcpy (str + ix, " translate");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ix = 0;
|
||||
str[ix++] = '[';
|
||||
str[ix++] = ' ';
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
ix += art_ftoa (str + ix, src[i]);
|
||||
str[ix++] = ' ';
|
||||
}
|
||||
strcpy (str + ix, "] concat");
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_multiply: Multiply two affine transformation matrices.
|
||||
* @dst: Where to store the result.
|
||||
* @src1: The first affine transform to multiply.
|
||||
* @src2: The second affine transform to multiply.
|
||||
*
|
||||
* Multiplies two affine transforms together, i.e. the resulting @dst
|
||||
* is equivalent to doing first @src1 then @src2. Note that the
|
||||
* PostScript concat operator multiplies on the left, i.e. "M concat"
|
||||
* is equivalent to "CTM = multiply (M, CTM)";
|
||||
*
|
||||
* It is safe to call this function with @dst equal to @src1 or @src2.
|
||||
**/
|
||||
void
|
||||
art_affine_multiply (double dst[6], const double src1[6], const double src2[6])
|
||||
{
|
||||
double d0, d1, d2, d3, d4, d5;
|
||||
|
||||
d0 = src1[0] * src2[0] + src1[1] * src2[2];
|
||||
d1 = src1[0] * src2[1] + src1[1] * src2[3];
|
||||
d2 = src1[2] * src2[0] + src1[3] * src2[2];
|
||||
d3 = src1[2] * src2[1] + src1[3] * src2[3];
|
||||
d4 = src1[4] * src2[0] + src1[5] * src2[2] + src2[4];
|
||||
d5 = src1[4] * src2[1] + src1[5] * src2[3] + src2[5];
|
||||
dst[0] = d0;
|
||||
dst[1] = d1;
|
||||
dst[2] = d2;
|
||||
dst[3] = d3;
|
||||
dst[4] = d4;
|
||||
dst[5] = d5;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_identity: Set up the identity matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
*
|
||||
* Sets up an identity matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_identity (double dst[6])
|
||||
{
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = 1;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* art_affine_scale: Set up a scaling matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @sx: X scale factor.
|
||||
* @sy: Y scale factor.
|
||||
*
|
||||
* Sets up a scaling matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_scale (double dst[6], double sx, double sy)
|
||||
{
|
||||
dst[0] = sx;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = sy;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_rotate: Set up a rotation affine transform.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @theta: Rotation angle in degrees.
|
||||
*
|
||||
* Sets up a rotation matrix. In the standard libart coordinate
|
||||
* system, in which increasing y moves downward, this is a
|
||||
* counterclockwise rotation. In the standard PostScript coordinate
|
||||
* system, which is reversed in the y direction, it is a clockwise
|
||||
* rotation.
|
||||
**/
|
||||
void
|
||||
art_affine_rotate (double dst[6], double theta)
|
||||
{
|
||||
double s, c;
|
||||
|
||||
s = sin (theta * M_PI / 180.0);
|
||||
c = cos (theta * M_PI / 180.0);
|
||||
dst[0] = c;
|
||||
dst[1] = s;
|
||||
dst[2] = -s;
|
||||
dst[3] = c;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_shear: Set up a shearing matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @theta: Shear angle in degrees.
|
||||
*
|
||||
* Sets up a shearing matrix. In the standard libart coordinate system
|
||||
* and a small value for theta, || becomes \\. Horizontal lines remain
|
||||
* unchanged.
|
||||
**/
|
||||
void
|
||||
art_affine_shear (double dst[6], double theta)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = tan (theta * M_PI / 180.0);
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = t;
|
||||
dst[3] = 1;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_translate: Set up a translation matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @tx: X translation amount.
|
||||
* @tx: Y translation amount.
|
||||
*
|
||||
* Sets up a translation matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_translate (double dst[6], double tx, double ty)
|
||||
{
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = 1;
|
||||
dst[4] = tx;
|
||||
dst[5] = ty;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_expansion: Find the affine's expansion factor.
|
||||
* @src: The affine transformation.
|
||||
*
|
||||
* Finds the expansion factor, i.e. the square root of the factor
|
||||
* by which the affine transform affects area. In an affine transform
|
||||
* composed of scaling, rotation, shearing, and translation, returns
|
||||
* the amount of scaling.
|
||||
*
|
||||
* Return value: the expansion factor.
|
||||
**/
|
||||
double
|
||||
art_affine_expansion (const double src[6])
|
||||
{
|
||||
return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_rectilinear: Determine whether the affine transformation is rectilinear.
|
||||
* @src: The original affine transformation.
|
||||
*
|
||||
* Determines whether @src is rectilinear, i.e. grid-aligned
|
||||
* rectangles are transformed to other grid-aligned rectangles. The
|
||||
* implementation has epsilon-tolerance for roundoff errors.
|
||||
*
|
||||
* Return value: TRUE if @src is rectilinear.
|
||||
**/
|
||||
int
|
||||
art_affine_rectilinear (const double src[6])
|
||||
{
|
||||
return ((fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON) ||
|
||||
(fabs (src[0]) < EPSILON && fabs (src[3]) < EPSILON));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_equal: Determine whether two affine transformations are equal.
|
||||
* @matrix1: An affine transformation.
|
||||
* @matrix2: Another affine transformation.
|
||||
*
|
||||
* Determines whether @matrix1 and @matrix2 are equal, with
|
||||
* epsilon-tolerance for roundoff errors.
|
||||
*
|
||||
* Return value: TRUE if @matrix1 and @matrix2 are equal.
|
||||
**/
|
||||
int
|
||||
art_affine_equal (double matrix1[6], double matrix2[6])
|
||||
{
|
||||
return (fabs (matrix1[0] - matrix2[0]) < EPSILON &&
|
||||
fabs (matrix1[1] - matrix2[1]) < EPSILON &&
|
||||
fabs (matrix1[2] - matrix2[2]) < EPSILON &&
|
||||
fabs (matrix1[3] - matrix2[3]) < EPSILON &&
|
||||
fabs (matrix1[4] - matrix2[4]) < EPSILON &&
|
||||
fabs (matrix1[5] - matrix2[5]) < EPSILON);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_AFFINE_H__
|
||||
#define __ART_AFFINE_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_point.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_affine_point (ArtPoint *dst, const ArtPoint *src,
|
||||
const double affine[6]);
|
||||
|
||||
void
|
||||
art_affine_invert (double dst_affine[6], const double src_affine[6]);
|
||||
|
||||
/* flip the matrix, FALSE, FALSE is a simple copy operation, and
|
||||
TRUE, TRUE equals a rotation by 180 degrees */
|
||||
void
|
||||
art_affine_flip (double dst_affine[6], const double src_affine[6],
|
||||
int horz, int vert);
|
||||
|
||||
void
|
||||
art_affine_to_string (char str[128], const double src[6]);
|
||||
|
||||
void
|
||||
art_affine_multiply (double dst[6],
|
||||
const double src1[6], const double src2[6]);
|
||||
|
||||
/* set up the identity matrix */
|
||||
void
|
||||
art_affine_identity (double dst[6]);
|
||||
|
||||
/* set up a scaling matrix */
|
||||
void
|
||||
art_affine_scale (double dst[6], double sx, double sy);
|
||||
|
||||
/* set up a rotation matrix; theta is given in degrees */
|
||||
void
|
||||
art_affine_rotate (double dst[6], double theta);
|
||||
|
||||
/* set up a shearing matrix; theta is given in degrees */
|
||||
void
|
||||
art_affine_shear (double dst[6], double theta);
|
||||
|
||||
/* set up a translation matrix */
|
||||
void
|
||||
art_affine_translate (double dst[6], double tx, double ty);
|
||||
|
||||
|
||||
/* find the affine's "expansion factor", i.e. the scale amount */
|
||||
double
|
||||
art_affine_expansion (const double src[6]);
|
||||
|
||||
/* Determine whether the affine transformation is rectilinear,
|
||||
i.e. whether a rectangle aligned to the grid is transformed into
|
||||
another rectangle aligned to the grid. */
|
||||
int
|
||||
art_affine_rectilinear (const double src[6]);
|
||||
|
||||
/* Determine whether two affine transformations are equal within grid allignment */
|
||||
int
|
||||
art_affine_equal (double matrix1[6], double matrix2[6]);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_AFFINE_H__ */
|
|
@ -0,0 +1,85 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Some functions to build alphagamma tables */
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_alphagamma.h"
|
||||
|
||||
/**
|
||||
* art_alphagamma_new: Create a new #ArtAlphaGamma.
|
||||
* @gamma: Gamma value.
|
||||
*
|
||||
* Create a new #ArtAlphaGamma for a specific value of @gamma. When
|
||||
* correctly implemented (which is generally not the case in libart),
|
||||
* alpha compositing with an alphagamma parameter is equivalent to
|
||||
* applying the gamma transformation to source images, doing the alpha
|
||||
* compositing (in linear intensity space), then applying the inverse
|
||||
* gamma transformation, bringing it back to a gamma-adjusted
|
||||
* intensity space.
|
||||
*
|
||||
* Return value: The newly created #ArtAlphaGamma.
|
||||
**/
|
||||
ArtAlphaGamma *
|
||||
art_alphagamma_new (double gamma)
|
||||
{
|
||||
int tablesize;
|
||||
ArtAlphaGamma *alphagamma;
|
||||
int i;
|
||||
int *table;
|
||||
art_u8 *invtable;
|
||||
double s, r_gamma;
|
||||
|
||||
tablesize = ceil (gamma * 8);
|
||||
if (tablesize < 10)
|
||||
tablesize = 10;
|
||||
|
||||
alphagamma = (ArtAlphaGamma *)art_alloc (sizeof(ArtAlphaGamma) +
|
||||
((1 << tablesize) - 1) *
|
||||
sizeof(art_u8));
|
||||
alphagamma->gamma = gamma;
|
||||
alphagamma->invtable_size = tablesize;
|
||||
|
||||
table = alphagamma->table;
|
||||
for (i = 0; i < 256; i++)
|
||||
table[i] = (int)floor (((1 << tablesize) - 1) *
|
||||
pow (i * (1.0 / 255), gamma) + 0.5);
|
||||
|
||||
invtable = alphagamma->invtable;
|
||||
s = 1.0 / ((1 << tablesize) - 1);
|
||||
r_gamma = 1.0 / gamma;
|
||||
for (i = 0; i < 1 << tablesize; i++)
|
||||
invtable[i] = (int)floor (255 * pow (i * s, r_gamma) + 0.5);
|
||||
|
||||
return alphagamma;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_alphagamma_free: Free an #ArtAlphaGamma.
|
||||
* @alphagamma: An #ArtAlphaGamma.
|
||||
*
|
||||
* Frees the #ArtAlphaGamma.
|
||||
**/
|
||||
void
|
||||
art_alphagamma_free (ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
art_free (alphagamma);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_ALPHAGAMMA_H__
|
||||
#define __ART_ALPHAGAMMA_H__
|
||||
|
||||
/* Alphagamma tables */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
typedef struct _ArtAlphaGamma ArtAlphaGamma;
|
||||
|
||||
struct _ArtAlphaGamma {
|
||||
/*< private >*/
|
||||
double gamma;
|
||||
int invtable_size;
|
||||
int table[256];
|
||||
art_u8 invtable[1];
|
||||
};
|
||||
|
||||
ArtAlphaGamma *
|
||||
art_alphagamma_new (double gamma);
|
||||
|
||||
void
|
||||
art_alphagamma_free (ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
|
@ -0,0 +1,92 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for bezier paths */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_bpath.h"
|
||||
|
||||
/**
|
||||
* art_bpath_affine_transform: Affine transform an #ArtBpath.
|
||||
* @src: The source #ArtBpath.
|
||||
* @matrix: The affine transform.
|
||||
*
|
||||
* Affine transform the bezpath, returning a newly allocated #ArtBpath
|
||||
* (allocated using art_alloc()).
|
||||
*
|
||||
* Result (x', y') = (matrix[0] * x + matrix[2] * y + matrix[4],
|
||||
* matrix[1] * x + matrix[3] * y + matrix[5])
|
||||
*
|
||||
* Return value: the transformed #ArtBpath.
|
||||
**/
|
||||
ArtBpath *
|
||||
art_bpath_affine_transform (const ArtBpath *src, const double matrix[6])
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ArtBpath *new;
|
||||
ArtPathcode code;
|
||||
double x, y;
|
||||
|
||||
for (i = 0; src[i].code != ART_END; i++);
|
||||
size = i;
|
||||
|
||||
new = art_new (ArtBpath, size + 1);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
code = src[i].code;
|
||||
new[i].code = code;
|
||||
if (code == ART_CURVETO)
|
||||
{
|
||||
x = src[i].x1;
|
||||
y = src[i].y1;
|
||||
new[i].x1 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y1 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
x = src[i].x2;
|
||||
y = src[i].y2;
|
||||
new[i].x2 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y2 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
new[i].x1 = 0;
|
||||
new[i].y1 = 0;
|
||||
new[i].x2 = 0;
|
||||
new[i].y2 = 0;
|
||||
}
|
||||
x = src[i].x3;
|
||||
y = src[i].y3;
|
||||
new[i].x3 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y3 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
new[i].code = ART_END;
|
||||
new[i].x1 = 0;
|
||||
new[i].y1 = 0;
|
||||
new[i].x2 = 0;
|
||||
new[i].y2 = 0;
|
||||
new[i].x3 = 0;
|
||||
new[i].y3 = 0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_BPATH_H__
|
||||
#define __ART_BPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_point.h"
|
||||
#include "art_pathcode.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#endif
|
||||
|
||||
/* Basic data structures and constructors for bezier paths */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtBpath ArtBpath;
|
||||
|
||||
struct _ArtBpath {
|
||||
/*< public >*/
|
||||
ArtPathcode code;
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
double x3;
|
||||
double y3;
|
||||
};
|
||||
|
||||
ArtBpath *
|
||||
art_bpath_affine_transform (const ArtBpath *src, const double matrix[6]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_BPATH_H__ */
|
|
@ -0,0 +1,68 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_FILTERLEVEL_H__
|
||||
#define __ART_FILTERLEVEL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_FILTER_NEAREST,
|
||||
ART_FILTER_TILES,
|
||||
ART_FILTER_BILINEAR,
|
||||
ART_FILTER_HYPER
|
||||
} ArtFilterLevel;
|
||||
|
||||
/* NEAREST is nearest neighbor. It is the fastest and lowest quality.
|
||||
|
||||
TILES is an accurate simulation of the PostScript image operator
|
||||
without any interpolation enabled; each pixel is rendered as a tiny
|
||||
parallelogram of solid color, the edges of which are implemented
|
||||
with antialiasing. It resembles nearest neighbor for enlargement,
|
||||
and bilinear for reduction.
|
||||
|
||||
BILINEAR is bilinear interpolation. For enlargement, it is
|
||||
equivalent to point-sampling the ideal bilinear-interpolated
|
||||
image. For reduction, it is equivalent to laying down small tiles
|
||||
and integrating over the coverage area.
|
||||
|
||||
HYPER is the highest quality reconstruction function. It is derived
|
||||
from the hyperbolic filters in Wolberg's "Digital Image Warping,"
|
||||
and is formally defined as the hyperbolic-filter sampling the ideal
|
||||
hyperbolic-filter interpolated image (the filter is designed to be
|
||||
idempotent for 1:1 pixel mapping). It is the slowest and highest
|
||||
quality.
|
||||
|
||||
Note: at this stage of implementation, most filter modes are likely
|
||||
not to be implemented.
|
||||
|
||||
Note: cubic filtering is missing from this list, because there isn't
|
||||
much point - hyper is just as fast to implement and slightly better
|
||||
in quality.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_PATHCODE_H__ */
|
|
@ -0,0 +1,121 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into a graymap. */
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
#include "art_gray_svp.h"
|
||||
|
||||
typedef struct _ArtGraySVPData ArtGraySVPData;
|
||||
|
||||
struct _ArtGraySVPData {
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
static void
|
||||
art_gray_svp_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtGraySVPData *data = (ArtGraySVPData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
int running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
|
||||
#if 0
|
||||
printf ("start = %d", start);
|
||||
running_sum = start;
|
||||
for (k = 0; k < n_steps; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
printf (" %d:%d", steps[k].x, running_sum >> 16);
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
memset (linebuf, running_sum >> 16, run_x1 - x0);
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
memset (linebuf + run_x0 - x0, running_sum >> 16, run_x1 - run_x0);
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
memset (linebuf + run_x1 - x0, running_sum >> 16, x1 - run_x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (linebuf, running_sum >> 16, x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_gray_svp_aa: Render the vector path into the bytemap.
|
||||
* @svp: The SVP to render.
|
||||
* @x0: The view window's left coord.
|
||||
* @y0: The view window's top coord.
|
||||
* @x1: The view window's right coord.
|
||||
* @y1: The view window's bottom coord.
|
||||
* @buf: The buffer where the bytemap is stored.
|
||||
* @rowstride: the rowstride for @buf.
|
||||
*
|
||||
* Each pixel gets a value proportional to the area within the pixel
|
||||
* overlapping the (filled) SVP. Pixel (x, y) is stored at:
|
||||
*
|
||||
* @buf[(y - * @y0) * @rowstride + (x - @x0)]
|
||||
*
|
||||
* All pixels @x0 <= x < @x1, @y0 <= y < @y1 are generated. A
|
||||
* stored value of zero is no coverage, and a value of 255 is full
|
||||
* coverage. The area within the pixel (x, y) is the region covered
|
||||
* by [x..x+1] and [y..y+1].
|
||||
**/
|
||||
void
|
||||
art_gray_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u8 *buf, int rowstride)
|
||||
{
|
||||
ArtGraySVPData data;
|
||||
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_gray_svp_callback, &data);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into a graymap. */
|
||||
|
||||
#ifndef __ART_GRAY_SVP_H__
|
||||
#define __ART_GRAY_SVP_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_gray_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u8 *buf, int rowstride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_GRAY_SVP_H__ */
|
|
@ -0,0 +1,78 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Various utility functions RLL finds useful. */
|
||||
|
||||
#include "config.h"
|
||||
#ifdef HAVE_UINSTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "art_misc.h"
|
||||
|
||||
/**
|
||||
* art_die: Print the error message to stderr and exit with a return code of 1.
|
||||
* @fmt: The printf-style format for the error message.
|
||||
*
|
||||
* Used for dealing with severe errors.
|
||||
**/
|
||||
void
|
||||
art_die (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_warn: Print the warning message to stderr.
|
||||
* @fmt: The printf-style format for the warning message.
|
||||
*
|
||||
* Used for generating warnings.
|
||||
**/
|
||||
void
|
||||
art_warn (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_dprint: Print the debug message to stderr.
|
||||
* @fmt: The printf-style format for the debug message.
|
||||
*
|
||||
* Used for generating debug output.
|
||||
**/
|
||||
void
|
||||
art_dprint (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Simple macros to set up storage allocation and basic types for libart
|
||||
functions. */
|
||||
|
||||
#ifndef __ART_MISC_H__
|
||||
#define __ART_MISC_H__
|
||||
|
||||
#include <stdlib.h> /* for malloc, etc. */
|
||||
|
||||
/* The art_config.h file is automatically generated by
|
||||
gen_art_config.c and contains definitions of
|
||||
ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}. */
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_config.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_config.h>
|
||||
#endif
|
||||
|
||||
#define art_alloc malloc
|
||||
#define art_free free
|
||||
#define art_realloc realloc
|
||||
|
||||
/* These aren't, strictly speaking, configuration macros, but they're
|
||||
damn handy to have around, and may be worth playing with for
|
||||
debugging. */
|
||||
#define art_new(type, n) ((type *)art_alloc ((n) * sizeof(type)))
|
||||
|
||||
#define art_renew(p, type, n) ((type *)art_realloc (p, (n) * sizeof(type)))
|
||||
|
||||
/* This one must be used carefully - in particular, p and max should
|
||||
be variables. They can also be pstruct->el lvalues. */
|
||||
#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
|
||||
|
||||
typedef int art_boolean;
|
||||
#define ART_FALSE 0
|
||||
#define ART_TRUE 1
|
||||
|
||||
/* define pi */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif /* M_PI */
|
||||
|
||||
#ifndef M_SQRT2
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#endif /* M_SQRT2 */
|
||||
|
||||
/* Provide macros to feature the GCC function attribute.
|
||||
*/
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
|
||||
#define ART_GNUC_PRINTF( format_idx, arg_idx ) \
|
||||
__attribute__((format (printf, format_idx, arg_idx)))
|
||||
#define ART_GNUC_NORETURN \
|
||||
__attribute__((noreturn))
|
||||
#else /* !__GNUC__ */
|
||||
#define ART_GNUC_PRINTF( format_idx, arg_idx )
|
||||
#define ART_GNUC_NORETURN
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ART_GNUC_NORETURN
|
||||
art_die (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
void
|
||||
art_warn (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
void
|
||||
art_dprint (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ART_USE_NEW_INTERSECTOR
|
||||
|
||||
#endif /* __ART_MISC_H__ */
|
|
@ -0,0 +1,39 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_PATHCODE_H__
|
||||
#define __ART_PATHCODE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_MOVETO,
|
||||
ART_MOVETO_OPEN,
|
||||
ART_CURVETO,
|
||||
ART_LINETO,
|
||||
ART_END
|
||||
} ArtPathcode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_PATHCODE_H__ */
|
|
@ -0,0 +1,283 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_pixbuf.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgb_dnotify: Create a new RGB #ArtPixBuf with explicit destroy notification.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
* @dfunc_data: The private data passed to @dfunc.
|
||||
* @dfunc: The destroy notification function.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGB
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* @dfunc is called with @dfunc_data and @pixels as arguments when the
|
||||
* #ArtPixBuf is destroyed. Using a destroy notification function
|
||||
* allows a wide range of memory management disciplines for the pixel
|
||||
* memory. A NULL value for @dfunc is also allowed and means that no
|
||||
* special action will be taken on destruction.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc)
|
||||
{
|
||||
ArtPixBuf *pixbuf;
|
||||
|
||||
pixbuf = art_new (ArtPixBuf, 1);
|
||||
|
||||
pixbuf->format = ART_PIX_RGB;
|
||||
pixbuf->n_channels = 3;
|
||||
pixbuf->has_alpha = 0;
|
||||
pixbuf->bits_per_sample = 8;
|
||||
|
||||
pixbuf->pixels = (art_u8 *) pixels;
|
||||
pixbuf->width = width;
|
||||
pixbuf->height = height;
|
||||
pixbuf->rowstride = rowstride;
|
||||
pixbuf->destroy_data = dfunc_data;
|
||||
pixbuf->destroy = dfunc;
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgba_dnotify: Create a new RGBA #ArtPixBuf with explicit destroy notification.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
* @dfunc_data: The private data passed to @dfunc.
|
||||
* @dfunc: The destroy notification function.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGBA
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* @dfunc is called with @dfunc_data and @pixels as arguments when the
|
||||
* #ArtPixBuf is destroyed. Using a destroy notification function
|
||||
* allows a wide range of memory management disciplines for the pixel
|
||||
* memory. A NULL value for @dfunc is also allowed and means that no
|
||||
* special action will be taken on destruction.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc)
|
||||
{
|
||||
ArtPixBuf *pixbuf;
|
||||
|
||||
pixbuf = art_new (ArtPixBuf, 1);
|
||||
|
||||
pixbuf->format = ART_PIX_RGB;
|
||||
pixbuf->n_channels = 4;
|
||||
pixbuf->has_alpha = 1;
|
||||
pixbuf->bits_per_sample = 8;
|
||||
|
||||
pixbuf->pixels = (art_u8 *) pixels;
|
||||
pixbuf->width = width;
|
||||
pixbuf->height = height;
|
||||
pixbuf->rowstride = rowstride;
|
||||
pixbuf->destroy_data = dfunc_data;
|
||||
pixbuf->destroy = dfunc;
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_const_rgb: Create a new RGB #ArtPixBuf with constant pixel data.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGB
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* No action is taken when the #ArtPixBuf is destroyed. Thus, this
|
||||
* function is useful when the pixel data is constant or statically
|
||||
* allocated.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride)
|
||||
{
|
||||
return art_pixbuf_new_rgb_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_const_rgba: Create a new RGBA #ArtPixBuf with constant pixel data.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGBA
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* No action is taken when the #ArtPixBuf is destroyed. Thus, this
|
||||
* function is suitable when the pixel data is constant or statically
|
||||
* allocated.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride)
|
||||
{
|
||||
return art_pixbuf_new_rgba_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
art_pixel_destroy (void *func_data, void *data)
|
||||
{
|
||||
art_free (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgb: Create a new RGB #ArtPixBuf.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGB
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* The @pixels buffer is freed with art_free() when the #ArtPixBuf is
|
||||
* destroyed. Thus, this function is suitable when the pixel data is
|
||||
* allocated with art_alloc().
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride)
|
||||
{
|
||||
return art_pixbuf_new_rgb_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgba: Create a new RGBA #ArtPixBuf.
|
||||
* @pixels: A buffer containing the actual pixel data.
|
||||
* @width: The width of the pixbuf.
|
||||
* @height: The height of the pixbuf.
|
||||
* @rowstride: The rowstride of the pixbuf.
|
||||
*
|
||||
* Creates a generic data structure for holding a buffer of RGBA
|
||||
* pixels. It is possible to think of an #ArtPixBuf as a
|
||||
* virtualization over specific pixel buffer formats.
|
||||
*
|
||||
* The @pixels buffer is freed with art_free() when the #ArtPixBuf is
|
||||
* destroyed. Thus, this function is suitable when the pixel data is
|
||||
* allocated with art_alloc().
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride)
|
||||
{
|
||||
return art_pixbuf_new_rgba_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_free: Destroy an #ArtPixBuf.
|
||||
* @pixbuf: The #ArtPixBuf to be destroyed.
|
||||
*
|
||||
* Destroys the #ArtPixBuf, calling the destroy notification function
|
||||
* (if non-NULL) so that the memory for the pixel buffer can be
|
||||
* properly reclaimed.
|
||||
**/
|
||||
void
|
||||
art_pixbuf_free (ArtPixBuf *pixbuf)
|
||||
{
|
||||
ArtDestroyNotify destroy = pixbuf->destroy;
|
||||
void *destroy_data = pixbuf->destroy_data;
|
||||
art_u8 *pixels = pixbuf->pixels;
|
||||
|
||||
pixbuf->pixels = NULL;
|
||||
pixbuf->destroy = NULL;
|
||||
pixbuf->destroy_data = NULL;
|
||||
|
||||
if (destroy)
|
||||
destroy (destroy_data, pixels);
|
||||
|
||||
art_free (pixbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_free_shallow:
|
||||
* @pixbuf: The #ArtPixBuf to be destroyed.
|
||||
*
|
||||
* Destroys the #ArtPixBuf without calling the destroy notification function.
|
||||
*
|
||||
* This function is deprecated. Use the _dnotify variants for
|
||||
* allocation instead.
|
||||
**/
|
||||
void
|
||||
art_pixbuf_free_shallow (ArtPixBuf *pixbuf)
|
||||
{
|
||||
art_free (pixbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_duplicate: Duplicate a pixbuf.
|
||||
* @pixbuf: The #ArtPixBuf to duplicate.
|
||||
*
|
||||
* Duplicates a pixbuf, including duplicating the buffer.
|
||||
*
|
||||
* Return value: The duplicated pixbuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_duplicate (const ArtPixBuf *pixbuf)
|
||||
{
|
||||
ArtPixBuf *result;
|
||||
int size;
|
||||
|
||||
result = art_new (ArtPixBuf, 1);
|
||||
|
||||
result->format = pixbuf->format;
|
||||
result->n_channels = pixbuf->n_channels;
|
||||
result->has_alpha = pixbuf->has_alpha;
|
||||
result->bits_per_sample = pixbuf->bits_per_sample;
|
||||
|
||||
size = (pixbuf->height - 1) * pixbuf->rowstride +
|
||||
pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) >> 3);
|
||||
result->pixels = art_alloc (size);
|
||||
memcpy (result->pixels, pixbuf->pixels, size);
|
||||
|
||||
result->width = pixbuf->width;
|
||||
result->height = pixbuf->height;
|
||||
result->rowstride = pixbuf->rowstride;
|
||||
result->destroy_data = NULL;
|
||||
result->destroy = art_pixel_destroy;
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_PIXBUF_H__
|
||||
#define __ART_PIXBUF_H__
|
||||
|
||||
/* A generic data structure for holding a buffer of pixels. One way
|
||||
to think about this module is as a virtualization over specific
|
||||
pixel buffer formats. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef void (*ArtDestroyNotify) (void *func_data, void *data);
|
||||
|
||||
typedef struct _ArtPixBuf ArtPixBuf;
|
||||
|
||||
typedef enum {
|
||||
ART_PIX_RGB
|
||||
/* gray, cmyk, lab, ... ? */
|
||||
} ArtPixFormat;
|
||||
|
||||
|
||||
/* The pixel buffer consists of width * height pixels, each of which
|
||||
has n_channels samples. It is stored in simple packed format. */
|
||||
|
||||
struct _ArtPixBuf {
|
||||
/*< public >*/
|
||||
ArtPixFormat format;
|
||||
int n_channels;
|
||||
int has_alpha;
|
||||
int bits_per_sample;
|
||||
|
||||
art_u8 *pixels;
|
||||
int width;
|
||||
int height;
|
||||
int rowstride;
|
||||
void *destroy_data;
|
||||
ArtDestroyNotify destroy;
|
||||
};
|
||||
|
||||
/* allocate an ArtPixBuf from art_alloc()ed pixels (automated destruction) */
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride);
|
||||
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride);
|
||||
|
||||
/* allocate an ArtPixBuf from constant pixels (no destruction) */
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride);
|
||||
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride);
|
||||
|
||||
/* allocate an ArtPixBuf and notify creator upon destruction */
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc);
|
||||
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc);
|
||||
|
||||
/* free an ArtPixBuf with destroy notification */
|
||||
void
|
||||
art_pixbuf_free (ArtPixBuf *pixbuf);
|
||||
|
||||
/* deprecated function, use the _dnotify variants for allocation instead */
|
||||
void
|
||||
art_pixbuf_free_shallow (ArtPixBuf *pixbuf);
|
||||
|
||||
ArtPixBuf *
|
||||
art_pixbuf_duplicate (const ArtPixBuf *pixbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_POINT_H__
|
||||
#define __ART_POINT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtPoint ArtPoint;
|
||||
|
||||
struct _ArtPoint {
|
||||
/*< public >*/
|
||||
double x, y;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_POINT_H__ */
|
|
@ -0,0 +1,214 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_rect.h"
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif /* MAX */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
/* rectangle primitives stolen from gzilla */
|
||||
|
||||
/**
|
||||
* art_irect_copy: Make a copy of an integer rectangle.
|
||||
* @dest: Where the copy is stored.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Copies the rectangle.
|
||||
**/
|
||||
void
|
||||
art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
|
||||
dest->x0 = src->x0;
|
||||
dest->y0 = src->y0;
|
||||
dest->x1 = src->x1;
|
||||
dest->y1 = src->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_union: Find union of two integer rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the smallest rectangle that includes @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
|
||||
if (art_irect_empty (src1)) {
|
||||
art_irect_copy (dest, src2);
|
||||
} else if (art_irect_empty (src2)) {
|
||||
art_irect_copy (dest, src1);
|
||||
} else {
|
||||
dest->x0 = MIN (src1->x0, src2->x0);
|
||||
dest->y0 = MIN (src1->y0, src2->y0);
|
||||
dest->x1 = MAX (src1->x1, src2->x1);
|
||||
dest->y1 = MAX (src1->y1, src2->y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_intersection: Find intersection of two integer rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the intersection of @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_irect_intersect (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
|
||||
dest->x0 = MAX (src1->x0, src2->x0);
|
||||
dest->y0 = MAX (src1->y0, src2->y0);
|
||||
dest->x1 = MIN (src1->x1, src2->x1);
|
||||
dest->y1 = MIN (src1->y1, src2->y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_empty: Determine whether integer rectangle is empty.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
|
||||
**/
|
||||
int
|
||||
art_irect_empty (const ArtIRect *src) {
|
||||
return (src->x1 <= src->x0 || src->y1 <= src->y0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
gboolean irect_point_inside (ArtIRect *rect, GzwPoint *point) {
|
||||
return (point->x >= rect->x0 && point->y >= rect->y0 &&
|
||||
point->x < rect->x1 && point->y < rect->y1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_drect_copy: Make a copy of a rectangle.
|
||||
* @dest: Where the copy is stored.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Copies the rectangle.
|
||||
**/
|
||||
void
|
||||
art_drect_copy (ArtDRect *dest, const ArtDRect *src) {
|
||||
dest->x0 = src->x0;
|
||||
dest->y0 = src->y0;
|
||||
dest->x1 = src->x1;
|
||||
dest->y1 = src->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_union: Find union of two rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the smallest rectangle that includes @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
|
||||
if (art_drect_empty (src1)) {
|
||||
art_drect_copy (dest, src2);
|
||||
} else if (art_drect_empty (src2)) {
|
||||
art_drect_copy (dest, src1);
|
||||
} else {
|
||||
dest->x0 = MIN (src1->x0, src2->x0);
|
||||
dest->y0 = MIN (src1->y0, src2->y0);
|
||||
dest->x1 = MAX (src1->x1, src2->x1);
|
||||
dest->y1 = MAX (src1->y1, src2->y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_intersection: Find intersection of two rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the intersection of @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_drect_intersect (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
|
||||
dest->x0 = MAX (src1->x0, src2->x0);
|
||||
dest->y0 = MAX (src1->y0, src2->y0);
|
||||
dest->x1 = MIN (src1->x1, src2->x1);
|
||||
dest->y1 = MIN (src1->y1, src2->y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_empty: Determine whether rectangle is empty.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
|
||||
**/
|
||||
int
|
||||
art_drect_empty (const ArtDRect *src) {
|
||||
return (src->x1 <= src->x0 || src->y1 <= src->y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_affine_transform: Affine transform rectangle.
|
||||
* @dst: Where to store the result.
|
||||
* @src: The source rectangle.
|
||||
* @matrix: The affine transformation.
|
||||
*
|
||||
* Find the smallest rectangle enclosing the affine transformed @src.
|
||||
* The result is exactly the affine transformation of @src when
|
||||
* @matrix specifies a rectilinear affine transformation, otherwise it
|
||||
* is a conservative approximation.
|
||||
**/
|
||||
void
|
||||
art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src, const double matrix[6])
|
||||
{
|
||||
double x00, y00, x10, y10;
|
||||
double x01, y01, x11, y11;
|
||||
|
||||
x00 = src->x0 * matrix[0] + src->y0 * matrix[2] + matrix[4];
|
||||
y00 = src->x0 * matrix[1] + src->y0 * matrix[3] + matrix[5];
|
||||
x10 = src->x1 * matrix[0] + src->y0 * matrix[2] + matrix[4];
|
||||
y10 = src->x1 * matrix[1] + src->y0 * matrix[3] + matrix[5];
|
||||
x01 = src->x0 * matrix[0] + src->y1 * matrix[2] + matrix[4];
|
||||
y01 = src->x0 * matrix[1] + src->y1 * matrix[3] + matrix[5];
|
||||
x11 = src->x1 * matrix[0] + src->y1 * matrix[2] + matrix[4];
|
||||
y11 = src->x1 * matrix[1] + src->y1 * matrix[3] + matrix[5];
|
||||
dst->x0 = MIN (MIN (x00, x10), MIN (x01, x11));
|
||||
dst->y0 = MIN (MIN (y00, y10), MIN (y01, y11));
|
||||
dst->x1 = MAX (MAX (x00, x10), MAX (x01, x11));
|
||||
dst->y1 = MAX (MAX (y00, y10), MAX (y01, y11));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_to_irect: Convert rectangle to integer rectangle.
|
||||
* @dst: Where to store resulting integer rectangle.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Find the smallest integer rectangle that encloses @src.
|
||||
**/
|
||||
void
|
||||
art_drect_to_irect (ArtIRect *dst, ArtDRect *src)
|
||||
{
|
||||
dst->x0 = floor (src->x0);
|
||||
dst->y0 = floor (src->y0);
|
||||
dst->x1 = ceil (src->x1);
|
||||
dst->y1 = ceil (src->y1);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RECT_H__
|
||||
#define __ART_RECT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _ArtDRect ArtDRect;
|
||||
typedef struct _ArtIRect ArtIRect;
|
||||
|
||||
struct _ArtDRect {
|
||||
/*< public >*/
|
||||
double x0, y0, x1, y1;
|
||||
};
|
||||
|
||||
struct _ArtIRect {
|
||||
/*< public >*/
|
||||
int x0, y0, x1, y1;
|
||||
};
|
||||
|
||||
/* Make a copy of the rectangle. */
|
||||
void art_irect_copy (ArtIRect *dest, const ArtIRect *src);
|
||||
|
||||
/* Find the smallest rectangle that includes both source rectangles. */
|
||||
void art_irect_union (ArtIRect *dest,
|
||||
const ArtIRect *src1, const ArtIRect *src2);
|
||||
|
||||
/* Return the intersection of the two rectangles */
|
||||
void art_irect_intersect (ArtIRect *dest,
|
||||
const ArtIRect *src1, const ArtIRect *src2);
|
||||
|
||||
/* Return true if the rectangle is empty. */
|
||||
int art_irect_empty (const ArtIRect *src);
|
||||
|
||||
/* Make a copy of the rectangle. */
|
||||
void art_drect_copy (ArtDRect *dest, const ArtDRect *src);
|
||||
|
||||
/* Find the smallest rectangle that includes both source rectangles. */
|
||||
void art_drect_union (ArtDRect *dest,
|
||||
const ArtDRect *src1, const ArtDRect *src2);
|
||||
|
||||
/* Return the intersection of the two rectangles */
|
||||
void art_drect_intersect (ArtDRect *dest,
|
||||
const ArtDRect *src1, const ArtDRect *src2);
|
||||
|
||||
/* Return true if the rectangle is empty. */
|
||||
int art_drect_empty (const ArtDRect *src);
|
||||
|
||||
void
|
||||
art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src,
|
||||
const double matrix[6]);
|
||||
|
||||
void art_drect_to_irect (ArtIRect *dst, ArtDRect *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,65 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_rect.h"
|
||||
#include "art_rect_svp.h"
|
||||
|
||||
/**
|
||||
* art_drect_svp: Find the bounding box of a sorted vector path.
|
||||
* @bbox: Where to store the bounding box.
|
||||
* @svp: The SVP.
|
||||
*
|
||||
* Finds the bounding box of the SVP.
|
||||
**/
|
||||
void
|
||||
art_drect_svp (ArtDRect *bbox, const ArtSVP *svp)
|
||||
{
|
||||
int i;
|
||||
|
||||
bbox->x0 = 0;
|
||||
bbox->y0 = 0;
|
||||
bbox->x1 = 0;
|
||||
bbox->y1 = 0;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
art_drect_union (bbox, bbox, &svp->segs[i].bbox);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_svp_union: Compute the bounding box of the svp and union it in to the existing bounding box.
|
||||
* @bbox: Initial boundin box and where to store the bounding box.
|
||||
* @svp: The SVP.
|
||||
*
|
||||
* Finds the bounding box of the SVP, computing its union with an
|
||||
* existing bbox.
|
||||
**/
|
||||
void
|
||||
art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
art_drect_union (bbox, bbox, &svp->segs[i].bbox);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RECT_SVP_H__
|
||||
#define __ART_RECT_SVP_H__
|
||||
|
||||
/* Find the bounding box of a sorted vector path. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_drect_svp (ArtDRect *bbox, const ArtSVP *svp);
|
||||
|
||||
/* Compute the bounding box of the svp and union it in to the
|
||||
existing bounding box. */
|
||||
void
|
||||
art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RECT_SVP_H__ */
|
|
@ -0,0 +1,136 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_rect.h"
|
||||
#include "art_rect_uta.h"
|
||||
|
||||
/* Functions to decompose a microtile array into a list of rectangles. */
|
||||
|
||||
/**
|
||||
* art_rect_list_from_uta: Decompose uta into list of rectangles.
|
||||
* @uta: The source uta.
|
||||
* @max_width: The maximum width of the resulting rectangles.
|
||||
* @max_height: The maximum height of the resulting rectangles.
|
||||
* @p_nrects: Where to store the number of returned rectangles.
|
||||
*
|
||||
* Allocates a new list of rectangles, sets *@p_nrects to the number
|
||||
* in the list. This list should be freed with art_free().
|
||||
*
|
||||
* Each rectangle bounded in size by (@max_width, @max_height).
|
||||
* However, these bounds must be at least the size of one tile.
|
||||
*
|
||||
* This routine provides a precise implementation, i.e. the rectangles
|
||||
* cover exactly the same area as the uta. It is thus appropriate in
|
||||
* cases where the overhead per rectangle is small compared with the
|
||||
* cost of filling in extra pixels.
|
||||
*
|
||||
* Return value: An array containing the resulting rectangles.
|
||||
**/
|
||||
ArtIRect *
|
||||
art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
|
||||
int *p_nrects)
|
||||
{
|
||||
ArtIRect *rects;
|
||||
int n_rects, n_rects_max;
|
||||
int x, y;
|
||||
int width, height;
|
||||
int ix;
|
||||
int left_ix;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int x0, y0, x1, y1;
|
||||
int *glom;
|
||||
int glom_rect;
|
||||
|
||||
n_rects = 0;
|
||||
n_rects_max = 1;
|
||||
rects = art_new (ArtIRect, n_rects_max);
|
||||
|
||||
width = uta->width;
|
||||
height = uta->height;
|
||||
utiles = uta->utiles;
|
||||
|
||||
glom = art_new (int, width * height);
|
||||
for (ix = 0; ix < width * height; ix++)
|
||||
glom[ix] = -1;
|
||||
|
||||
ix = 0;
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
bb = utiles[ix];
|
||||
if (bb)
|
||||
{
|
||||
x0 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X0(bb);
|
||||
y0 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y0(bb);
|
||||
y1 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y1(bb);
|
||||
|
||||
left_ix = ix;
|
||||
/* now try to extend to the right */
|
||||
while (x != width - 1 &&
|
||||
ART_UTA_BBOX_X1(bb) == ART_UTILE_SIZE &&
|
||||
(((bb & 0xffffff) ^ utiles[ix + 1]) & 0xffff00ff) == 0 &&
|
||||
(((uta->x0 + x + 1) << ART_UTILE_SHIFT) +
|
||||
ART_UTA_BBOX_X1(utiles[ix + 1]) -
|
||||
x0) <= max_width)
|
||||
{
|
||||
bb = utiles[ix + 1];
|
||||
ix++;
|
||||
x++;
|
||||
}
|
||||
x1 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X1(bb);
|
||||
|
||||
|
||||
/* if rectangle nonempty */
|
||||
if ((x1 ^ x0) | (y1 ^ y0))
|
||||
{
|
||||
/* try to glom onto an existing rectangle */
|
||||
glom_rect = glom[left_ix];
|
||||
if (glom_rect != -1 &&
|
||||
x0 == rects[glom_rect].x0 &&
|
||||
x1 == rects[glom_rect].x1 &&
|
||||
y0 == rects[glom_rect].y1 &&
|
||||
y1 - rects[glom_rect].y0 <= max_height)
|
||||
{
|
||||
rects[glom_rect].y1 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n_rects == n_rects_max)
|
||||
art_expand (rects, ArtIRect, n_rects_max);
|
||||
rects[n_rects].x0 = x0;
|
||||
rects[n_rects].y0 = y0;
|
||||
rects[n_rects].x1 = x1;
|
||||
rects[n_rects].y1 = y1;
|
||||
glom_rect = n_rects;
|
||||
n_rects++;
|
||||
}
|
||||
if (y != height - 1)
|
||||
glom[left_ix + width] = glom_rect;
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
|
||||
art_free (glom);
|
||||
*p_nrects = n_rects;
|
||||
return rects;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RECT_UTA_H__
|
||||
#define __ART_RECT_UTA_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_uta.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtIRect *
|
||||
art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
|
||||
int *p_nrects);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RECT_UTA_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* art_render.h: Modular rendering architecture.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RENDER_H__
|
||||
#define __ART_RENDER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Render object */
|
||||
|
||||
#ifndef ART_MAX_DEPTH
|
||||
#define ART_MAX_DEPTH 16
|
||||
#endif
|
||||
|
||||
#if ART_MAX_DEPTH == 16
|
||||
typedef art_u16 ArtPixMaxDepth;
|
||||
#define ART_PIX_MAX_FROM_8(x) ((x) | ((x) << 8))
|
||||
#define ART_PIX_8_FROM_MAX(x) (((x) + 0x80 - (((x) + 0x80) >> 8)) >> 8)
|
||||
#else
|
||||
#if ART_MAX_DEPTH == 8
|
||||
typedef art_u8 ArtPixMaxDepth;
|
||||
#define ART_PIX_MAX_FROM_8(x) (x)
|
||||
#define ART_PIX_8_FROM_MAX(x) (x)
|
||||
#else
|
||||
#error ART_MAX_DEPTH must be either 8 or 16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ART_MAX_CHAN 16
|
||||
|
||||
typedef struct _ArtRender ArtRender;
|
||||
typedef struct _ArtRenderCallback ArtRenderCallback;
|
||||
typedef struct _ArtRenderMaskRun ArtRenderMaskRun;
|
||||
typedef struct _ArtImageSource ArtImageSource;
|
||||
typedef struct _ArtMaskSource ArtMaskSource;
|
||||
|
||||
typedef enum {
|
||||
ART_ALPHA_NONE = 0,
|
||||
ART_ALPHA_SEPARATE = 1,
|
||||
ART_ALPHA_PREMUL = 2
|
||||
} ArtAlphaType;
|
||||
|
||||
typedef enum {
|
||||
ART_COMPOSITE_NORMAL,
|
||||
ART_COMPOSITE_MULTIPLY,
|
||||
/* todo: more */
|
||||
ART_COMPOSITE_CUSTOM
|
||||
} ArtCompositingMode;
|
||||
|
||||
typedef enum {
|
||||
ART_IMAGE_SOURCE_CAN_CLEAR = 1,
|
||||
ART_IMAGE_SOURCE_CAN_COMPOSITE = 2
|
||||
} ArtImageSourceFlags;
|
||||
|
||||
struct _ArtRenderMaskRun {
|
||||
int x;
|
||||
int alpha;
|
||||
};
|
||||
|
||||
struct _ArtRenderCallback {
|
||||
void (*render) (ArtRenderCallback *self, ArtRender *render,
|
||||
art_u8 *dest, int y);
|
||||
void (*done) (ArtRenderCallback *self, ArtRender *render);
|
||||
};
|
||||
|
||||
struct _ArtImageSource {
|
||||
ArtRenderCallback super;
|
||||
void (*negotiate) (ArtImageSource *self, ArtRender *render,
|
||||
ArtImageSourceFlags *p_flags,
|
||||
int *p_buf_depth, ArtAlphaType *p_alpha_type);
|
||||
};
|
||||
|
||||
struct _ArtMaskSource {
|
||||
ArtRenderCallback super;
|
||||
int (*can_drive) (ArtMaskSource *self, ArtRender *render);
|
||||
/* For each mask source, ::prepare() is invoked if it is not
|
||||
a driver, or ::invoke_driver() if it is. */
|
||||
void (*invoke_driver) (ArtMaskSource *self, ArtRender *render);
|
||||
void (*prepare) (ArtMaskSource *self, ArtRender *render, art_boolean first);
|
||||
};
|
||||
|
||||
struct _ArtRender {
|
||||
/* parameters of destination image */
|
||||
int x0, y0;
|
||||
int x1, y1;
|
||||
art_u8 *pixels;
|
||||
int rowstride;
|
||||
int n_chan;
|
||||
int depth;
|
||||
ArtAlphaType alpha_type;
|
||||
|
||||
art_boolean clear;
|
||||
ArtPixMaxDepth clear_color[ART_MAX_CHAN + 1];
|
||||
art_u32 opacity; /* [0..0x10000] */
|
||||
|
||||
ArtCompositingMode compositing_mode;
|
||||
|
||||
ArtAlphaGamma *alphagamma;
|
||||
|
||||
art_u8 *alpha_buf;
|
||||
|
||||
/* parameters of intermediate buffer */
|
||||
int buf_depth;
|
||||
ArtAlphaType buf_alpha;
|
||||
art_u8 *image_buf;
|
||||
|
||||
/* driving alpha scanline data */
|
||||
/* A "run" is a contiguous sequence of x values with the same alpha value. */
|
||||
int n_run;
|
||||
ArtRenderMaskRun *run;
|
||||
|
||||
/* A "span" is a contiguous sequence of x values with non-zero alpha. */
|
||||
int n_span;
|
||||
int *span_x;
|
||||
|
||||
art_boolean need_span;
|
||||
};
|
||||
|
||||
ArtRender *
|
||||
art_render_new (int x0, int y0, int x1, int y1,
|
||||
art_u8 *pixels, int rowstride,
|
||||
int n_chan, int depth, ArtAlphaType alpha_type,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
void
|
||||
art_render_invoke (ArtRender *render);
|
||||
|
||||
void
|
||||
art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color);
|
||||
|
||||
void
|
||||
art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb);
|
||||
|
||||
void
|
||||
art_render_mask_solid (ArtRender *render, int opacity);
|
||||
|
||||
void
|
||||
art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color);
|
||||
|
||||
/* The next two functions are for custom mask sources only. */
|
||||
void
|
||||
art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source);
|
||||
|
||||
void
|
||||
art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y);
|
||||
|
||||
/* The following function is for custom image sources only. */
|
||||
void
|
||||
art_render_add_image_source (ArtRender *render, ArtImageSource *image_source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RENDER_H__ */
|
||||
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
* art_render_gradient.c: Gradient image source for modular rendering.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Raph Levien <raph@acm.org>
|
||||
* Alexander Larsson <alla@lysator.liu.se>
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_filterlevel.h"
|
||||
|
||||
#include "art_render.h"
|
||||
#include "art_render_gradient.h"
|
||||
|
||||
typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
|
||||
typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
|
||||
|
||||
struct _ArtImageSourceGradLin {
|
||||
ArtImageSource super;
|
||||
const ArtGradientLinear *gradient;
|
||||
};
|
||||
|
||||
struct _ArtImageSourceGradRad {
|
||||
ArtImageSource super;
|
||||
const ArtGradientRadial *gradient;
|
||||
double a;
|
||||
};
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
/**
|
||||
* art_render_gradient_setpix: Set a gradient pixel.
|
||||
* @render: The render object.
|
||||
* @dst: Pointer to destination (where to store pixel).
|
||||
* @n_stops: Number of stops in @stops.
|
||||
* @stops: The stops for the gradient.
|
||||
* @offset: The offset.
|
||||
*
|
||||
* @n_stops must be > 0.
|
||||
*
|
||||
* Sets a gradient pixel, storing it at @dst.
|
||||
**/
|
||||
static void
|
||||
art_render_gradient_setpix (ArtRender *render,
|
||||
art_u8 *dst,
|
||||
int n_stops, ArtGradientStop *stops,
|
||||
double offset)
|
||||
{
|
||||
int ix;
|
||||
int j;
|
||||
double off0, off1;
|
||||
int n_ch = render->n_chan + 1;
|
||||
|
||||
for (ix = 0; ix < n_stops; ix++)
|
||||
if (stops[ix].offset > offset)
|
||||
break;
|
||||
/* stops[ix - 1].offset < offset < stops[ix].offset */
|
||||
if (ix > 0 && ix < n_stops)
|
||||
{
|
||||
off0 = stops[ix - 1].offset;
|
||||
off1 = stops[ix].offset;
|
||||
if (fabs (off1 - off0) > EPSILON)
|
||||
{
|
||||
double interp;
|
||||
|
||||
interp = (offset - off0) / (off1 - off0);
|
||||
for (j = 0; j < n_ch; j++)
|
||||
{
|
||||
int z0, z1;
|
||||
int z;
|
||||
z0 = stops[ix - 1].color[j];
|
||||
z1 = stops[ix].color[j];
|
||||
z = floor (z0 + (z1 - z0) * interp + 0.5);
|
||||
if (render->buf_depth == 8)
|
||||
dst[j] = ART_PIX_8_FROM_MAX (z);
|
||||
else /* (render->buf_depth == 16) */
|
||||
((art_u16 *)dst)[j] = z;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (ix == n_stops)
|
||||
ix--;
|
||||
|
||||
for (j = 0; j < n_ch; j++)
|
||||
{
|
||||
int z;
|
||||
z = stops[ix].color[j];
|
||||
if (render->buf_depth == 8)
|
||||
dst[j] = ART_PIX_8_FROM_MAX (z);
|
||||
else /* (render->buf_depth == 16) */
|
||||
((art_u16 *)dst)[j] = z;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
|
||||
{
|
||||
art_free (self);
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
|
||||
art_u8 *dest, int y)
|
||||
{
|
||||
ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
|
||||
const ArtGradientLinear *gradient = z->gradient;
|
||||
int pixstride = (render->n_chan + 1) * (render->depth >> 3);
|
||||
int x;
|
||||
int width = render->x1 - render->x0;
|
||||
double offset, d_offset;
|
||||
double actual_offset;
|
||||
int n_stops = gradient->n_stops;
|
||||
ArtGradientStop *stops = gradient->stops;
|
||||
art_u8 *bufp = render->image_buf;
|
||||
ArtGradientSpread spread = gradient->spread;
|
||||
|
||||
offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
|
||||
d_offset = gradient->a;
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
if (spread == ART_GRADIENT_PAD)
|
||||
actual_offset = offset;
|
||||
else if (spread == ART_GRADIENT_REPEAT)
|
||||
actual_offset = offset - floor (offset);
|
||||
else /* (spread == ART_GRADIENT_REFLECT) */
|
||||
{
|
||||
double tmp;
|
||||
|
||||
tmp = offset - 2 * floor (0.5 * offset);
|
||||
actual_offset = tmp > 1 ? 2 - tmp : tmp;
|
||||
}
|
||||
art_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset);
|
||||
offset += d_offset;
|
||||
bufp += pixstride;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
|
||||
ArtImageSourceFlags *p_flags,
|
||||
int *p_buf_depth, ArtAlphaType *p_alpha)
|
||||
{
|
||||
self->super.render = art_render_gradient_linear_render;
|
||||
*p_flags = 0;
|
||||
*p_buf_depth = render->depth;
|
||||
*p_alpha = ART_ALPHA_PREMUL;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_render_gradient_linear: Add a linear gradient image source.
|
||||
* @render: The render object.
|
||||
* @gradient: The linear gradient.
|
||||
*
|
||||
* Adds the linear gradient @gradient as the image source for rendering
|
||||
* in the render object @render.
|
||||
**/
|
||||
void
|
||||
art_render_gradient_linear (ArtRender *render,
|
||||
const ArtGradientLinear *gradient,
|
||||
ArtFilterLevel level)
|
||||
{
|
||||
ArtImageSourceGradLin *image_source = art_new (ArtImageSourceGradLin, 1);
|
||||
|
||||
image_source->super.super.render = NULL;
|
||||
image_source->super.super.done = art_render_gradient_linear_done;
|
||||
image_source->super.negotiate = art_render_gradient_linear_negotiate;
|
||||
|
||||
image_source->gradient = gradient;
|
||||
|
||||
art_render_add_image_source (render, &image_source->super);
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
|
||||
{
|
||||
art_free (self);
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
|
||||
art_u8 *dest, int y)
|
||||
{
|
||||
ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
|
||||
const ArtGradientRadial *gradient = z->gradient;
|
||||
int pixstride = (render->n_chan + 1) * (render->depth >> 3);
|
||||
int x;
|
||||
int x0 = render->x0;
|
||||
int width = render->x1 - x0;
|
||||
int n_stops = gradient->n_stops;
|
||||
ArtGradientStop *stops = gradient->stops;
|
||||
art_u8 *bufp = render->image_buf;
|
||||
double fx = gradient->fx;
|
||||
double fy = gradient->fy;
|
||||
double dx, dy;
|
||||
double *affine = gradient->affine;
|
||||
double aff0 = affine[0];
|
||||
double aff1 = affine[1];
|
||||
const double a = z->a;
|
||||
const double arecip = 1.0 / a;
|
||||
double b, db;
|
||||
double c, dc, ddc;
|
||||
double b_a, db_a;
|
||||
double rad, drad, ddrad;
|
||||
|
||||
dx = x0 * aff0 + y * affine[2] + affine[4] - fx;
|
||||
dy = x0 * aff1 + y * affine[3] + affine[5] - fy;
|
||||
b = dx * fx + dy * fy;
|
||||
db = aff0 * fx + aff1 * fy;
|
||||
c = dx * dx + dy * dy;
|
||||
dc = 2 * aff0 * dx + aff0 * aff0 + 2 * aff1 * dy + aff1 * aff1;
|
||||
ddc = 2 * aff0 * aff0 + 2 * aff1 * aff1;
|
||||
|
||||
b_a = b * arecip;
|
||||
db_a = db * arecip;
|
||||
|
||||
rad = b_a * b_a + c * arecip;
|
||||
drad = 2 * b_a * db_a + db_a * db_a + dc * arecip;
|
||||
ddrad = 2 * db_a * db_a + ddc * arecip;
|
||||
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
double z;
|
||||
|
||||
if (rad > 0)
|
||||
z = b_a + sqrt (rad);
|
||||
else
|
||||
z = b_a;
|
||||
art_render_gradient_setpix (render, bufp, n_stops, stops, z);
|
||||
bufp += pixstride;
|
||||
b_a += db_a;
|
||||
rad += drad;
|
||||
drad += ddrad;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
|
||||
ArtImageSourceFlags *p_flags,
|
||||
int *p_buf_depth, ArtAlphaType *p_alpha)
|
||||
{
|
||||
self->super.render = art_render_gradient_radial_render;
|
||||
*p_flags = 0;
|
||||
*p_buf_depth = render->depth;
|
||||
*p_alpha = ART_ALPHA_PREMUL;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_render_gradient_radial: Add a radial gradient image source.
|
||||
* @render: The render object.
|
||||
* @gradient: The radial gradient.
|
||||
*
|
||||
* Adds the radial gradient @gradient as the image source for rendering
|
||||
* in the render object @render.
|
||||
**/
|
||||
void
|
||||
art_render_gradient_radial (ArtRender *render,
|
||||
const ArtGradientRadial *gradient,
|
||||
ArtFilterLevel level)
|
||||
{
|
||||
ArtImageSourceGradRad *image_source = art_new (ArtImageSourceGradRad, 1);
|
||||
double fx = gradient->fx;
|
||||
double fy = gradient->fy;
|
||||
|
||||
image_source->super.super.render = NULL;
|
||||
image_source->super.super.done = art_render_gradient_radial_done;
|
||||
image_source->super.negotiate = art_render_gradient_radial_negotiate;
|
||||
|
||||
image_source->gradient = gradient;
|
||||
/* todo: sanitycheck fx, fy? */
|
||||
image_source->a = 1 - fx * fx - fy * fy;
|
||||
|
||||
art_render_add_image_source (render, &image_source->super);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* art_render_gradient.h: Gradient image source for modular rendering.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Raph Levien <raph@acm.org>
|
||||
* Alexander Larsson <alla@lysator.liu.se>
|
||||
*/
|
||||
|
||||
#ifndef __ART_RENDER_GRADIENT_H__
|
||||
#define __ART_RENDER_GRADIENT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtGradientLinear ArtGradientLinear;
|
||||
typedef struct _ArtGradientRadial ArtGradientRadial;
|
||||
typedef struct _ArtGradientStop ArtGradientStop;
|
||||
|
||||
typedef enum {
|
||||
ART_GRADIENT_PAD,
|
||||
ART_GRADIENT_REFLECT,
|
||||
ART_GRADIENT_REPEAT
|
||||
} ArtGradientSpread;
|
||||
|
||||
struct _ArtGradientLinear {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
ArtGradientSpread spread;
|
||||
int n_stops;
|
||||
ArtGradientStop *stops;
|
||||
};
|
||||
|
||||
struct _ArtGradientRadial {
|
||||
double affine[6]; /* transforms user coordinates to unit circle */
|
||||
double fx, fy; /* focal point in unit circle coords */
|
||||
int n_stops;
|
||||
ArtGradientStop *stops;
|
||||
};
|
||||
|
||||
struct _ArtGradientStop {
|
||||
double offset;
|
||||
ArtPixMaxDepth color[ART_MAX_CHAN + 1];
|
||||
};
|
||||
|
||||
void
|
||||
art_render_gradient_linear (ArtRender *render,
|
||||
const ArtGradientLinear *gradient,
|
||||
ArtFilterLevel level);
|
||||
|
||||
void
|
||||
art_render_gradient_radial (ArtRender *render,
|
||||
const ArtGradientRadial *gradient,
|
||||
ArtFilterLevel level);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RENDER_GRADIENT_H__ */
|
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
* art_render_gradient.c: SVP mask source for modular rendering.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Raph Levien <raph@acm.org>
|
||||
*/
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
|
||||
#include "art_render.h"
|
||||
#include "art_render_svp.h"
|
||||
|
||||
typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
|
||||
|
||||
struct _ArtMaskSourceSVP {
|
||||
ArtMaskSource super;
|
||||
ArtRender *render;
|
||||
const ArtSVP *svp;
|
||||
art_u8 *dest_ptr;
|
||||
};
|
||||
|
||||
static void
|
||||
art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
|
||||
{
|
||||
art_free (self);
|
||||
}
|
||||
|
||||
static int
|
||||
art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/* The basic art_render_svp_callback function is repeated four times,
|
||||
for all combinations of non-unit opacity and generating spans. In
|
||||
general, I'd consider this bad style, but in this case I plead
|
||||
a measurable performance improvement. */
|
||||
|
||||
static void
|
||||
art_render_svp_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
|
||||
ArtRender *render = z->render;
|
||||
int n_run = 0;
|
||||
int i;
|
||||
int running_sum = start;
|
||||
int x0 = render->x0;
|
||||
int x1 = render->x1;
|
||||
int run_x0, run_x1;
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0 && running_sum > 0x80ff)
|
||||
{
|
||||
run[0].x = x0;
|
||||
run[0].alpha = running_sum;
|
||||
n_run++;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_steps - 1; i++)
|
||||
{
|
||||
running_sum += steps[i].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[i + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
run[n_run].x = run_x0;
|
||||
run[n_run].alpha = running_sum;
|
||||
n_run++;
|
||||
}
|
||||
}
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
running_sum += steps[n_steps - 1].delta;
|
||||
run[n_run].x = run_x1;
|
||||
run[n_run].alpha = running_sum;
|
||||
n_run++;
|
||||
}
|
||||
if (running_sum > 0x80ff)
|
||||
{
|
||||
run[n_run].x = x1;
|
||||
run[n_run].alpha = 0x8000;
|
||||
n_run++;
|
||||
}
|
||||
}
|
||||
|
||||
render->n_run = n_run;
|
||||
|
||||
art_render_invoke_callbacks (render, z->dest_ptr, y);
|
||||
|
||||
z->dest_ptr += render->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_svp_callback_span (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
|
||||
ArtRender *render = z->render;
|
||||
int n_run = 0;
|
||||
int n_span = 0;
|
||||
int i;
|
||||
int running_sum = start;
|
||||
int x0 = render->x0;
|
||||
int x1 = render->x1;
|
||||
int run_x0, run_x1;
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
int *span_x = render->span_x;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0 && running_sum > 0x80ff)
|
||||
{
|
||||
run[0].x = x0;
|
||||
run[0].alpha = running_sum;
|
||||
n_run++;
|
||||
span_x[0] = x0;
|
||||
n_span++;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_steps - 1; i++)
|
||||
{
|
||||
running_sum += steps[i].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[i + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
run[n_run].x = run_x0;
|
||||
run[n_run].alpha = running_sum;
|
||||
n_run++;
|
||||
if ((n_span & 1) != (running_sum > 0x80ff))
|
||||
span_x[n_span++] = run_x0;
|
||||
}
|
||||
}
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
running_sum += steps[n_steps - 1].delta;
|
||||
run[n_run].x = run_x1;
|
||||
run[n_run].alpha = running_sum;
|
||||
n_run++;
|
||||
if ((n_span & 1) != (running_sum > 0x80ff))
|
||||
span_x[n_span++] = run_x1;
|
||||
}
|
||||
if (running_sum > 0x80ff)
|
||||
{
|
||||
run[n_run].x = x1;
|
||||
run[n_run].alpha = 0x8000;
|
||||
n_run++;
|
||||
span_x[n_span++] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
render->n_run = n_run;
|
||||
render->n_span = n_span;
|
||||
|
||||
art_render_invoke_callbacks (render, z->dest_ptr, y);
|
||||
|
||||
z->dest_ptr += render->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_svp_callback_opacity (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
|
||||
ArtRender *render = z->render;
|
||||
int n_run = 0;
|
||||
int i;
|
||||
art_u32 running_sum;
|
||||
int x0 = render->x0;
|
||||
int x1 = render->x1;
|
||||
int run_x0, run_x1;
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
art_u32 opacity = render->opacity;
|
||||
art_u32 alpha;
|
||||
|
||||
running_sum = start - 0x7f80;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
|
||||
if (run_x1 > x0 && alpha > 0x80ff)
|
||||
{
|
||||
run[0].x = x0;
|
||||
run[0].alpha = alpha;
|
||||
n_run++;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_steps - 1; i++)
|
||||
{
|
||||
running_sum += steps[i].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[i + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
run[n_run].x = run_x0;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
|
||||
run[n_run].alpha = alpha;
|
||||
n_run++;
|
||||
}
|
||||
}
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
running_sum += steps[n_steps - 1].delta;
|
||||
run[n_run].x = run_x1;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
|
||||
run[n_run].alpha = alpha;
|
||||
n_run++;
|
||||
}
|
||||
if (alpha > 0x80ff)
|
||||
{
|
||||
run[n_run].x = x1;
|
||||
run[n_run].alpha = 0x8000;
|
||||
n_run++;
|
||||
}
|
||||
}
|
||||
|
||||
render->n_run = n_run;
|
||||
|
||||
art_render_invoke_callbacks (render, z->dest_ptr, y);
|
||||
|
||||
z->dest_ptr += render->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_svp_callback_opacity_span (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
|
||||
ArtRender *render = z->render;
|
||||
int n_run = 0;
|
||||
int n_span = 0;
|
||||
int i;
|
||||
art_u32 running_sum;
|
||||
int x0 = render->x0;
|
||||
int x1 = render->x1;
|
||||
int run_x0, run_x1;
|
||||
ArtRenderMaskRun *run = render->run;
|
||||
int *span_x = render->span_x;
|
||||
art_u32 opacity = render->opacity;
|
||||
art_u32 alpha;
|
||||
|
||||
running_sum = start - 0x7f80;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
|
||||
if (run_x1 > x0 && alpha > 0x80ff)
|
||||
{
|
||||
run[0].x = x0;
|
||||
run[0].alpha = alpha;
|
||||
n_run++;
|
||||
span_x[0] = x0;
|
||||
n_span++;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_steps - 1; i++)
|
||||
{
|
||||
running_sum += steps[i].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[i + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
run[n_run].x = run_x0;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
|
||||
run[n_run].alpha = alpha;
|
||||
n_run++;
|
||||
if ((n_span & 1) != (alpha > 0x80ff))
|
||||
span_x[n_span++] = run_x0;
|
||||
}
|
||||
}
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
running_sum += steps[n_steps - 1].delta;
|
||||
run[n_run].x = run_x1;
|
||||
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
|
||||
run[n_run].alpha = alpha;
|
||||
n_run++;
|
||||
if ((n_span & 1) != (alpha > 0x80ff))
|
||||
span_x[n_span++] = run_x1;
|
||||
}
|
||||
if (alpha > 0x80ff)
|
||||
{
|
||||
run[n_run].x = x1;
|
||||
run[n_run].alpha = 0x8000;
|
||||
n_run++;
|
||||
span_x[n_span++] = x1;
|
||||
}
|
||||
}
|
||||
|
||||
render->n_run = n_run;
|
||||
render->n_span = n_span;
|
||||
|
||||
art_render_invoke_callbacks (render, z->dest_ptr, y);
|
||||
|
||||
z->dest_ptr += render->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
|
||||
{
|
||||
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
|
||||
void (*callback) (void *callback_data,
|
||||
int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps);
|
||||
|
||||
z->dest_ptr = render->pixels;
|
||||
if (render->opacity == 0x10000)
|
||||
{
|
||||
if (render->need_span)
|
||||
callback = art_render_svp_callback_span;
|
||||
else
|
||||
callback = art_render_svp_callback;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (render->need_span)
|
||||
callback = art_render_svp_callback_opacity_span;
|
||||
else
|
||||
callback = art_render_svp_callback_opacity;
|
||||
}
|
||||
|
||||
art_svp_render_aa (z->svp,
|
||||
render->x0, render->y0,
|
||||
render->x1, render->y1, callback,
|
||||
self);
|
||||
art_render_svp_done (&self->super, render);
|
||||
}
|
||||
|
||||
static void
|
||||
art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
|
||||
art_boolean first)
|
||||
{
|
||||
/* todo */
|
||||
art_die ("art_render_svp non-driver mode not yet implemented.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* art_render_svp: Use an SVP as a render mask source.
|
||||
* @render: Render object.
|
||||
* @svp: SVP.
|
||||
*
|
||||
* Adds @svp to the render object as a mask. Note: @svp must remain
|
||||
* allocated until art_render_invoke() is called on @render.
|
||||
**/
|
||||
void
|
||||
art_render_svp (ArtRender *render, const ArtSVP *svp)
|
||||
{
|
||||
ArtMaskSourceSVP *mask_source;
|
||||
mask_source = art_new (ArtMaskSourceSVP, 1);
|
||||
|
||||
mask_source->super.super.render = NULL;
|
||||
mask_source->super.super.done = art_render_svp_done;
|
||||
mask_source->super.can_drive = art_render_svp_can_drive;
|
||||
mask_source->super.invoke_driver = art_render_svp_invoke_driver;
|
||||
mask_source->super.prepare = art_render_svp_prepare;
|
||||
mask_source->render = render;
|
||||
mask_source->svp = svp;
|
||||
|
||||
art_render_add_mask_source (render, &mask_source->super);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* art_render_gradient.h: SVP mask source for modular rendering.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Raph Levien <raph@acm.org>
|
||||
*/
|
||||
|
||||
#ifndef __ART_RENDER_SVP_H__
|
||||
#define __ART_RENDER_SVP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_render_svp (ArtRender *render, const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RENDER_SVP_H__ */
|
|
@ -0,0 +1,176 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
#include "art_misc.h"
|
||||
#include "art_rgb.h"
|
||||
|
||||
#include "config.h" /* for endianness */
|
||||
|
||||
/* Basic operators for manipulating 24-bit packed RGB buffers. */
|
||||
|
||||
#define COLOR_RUN_COMPLEX
|
||||
|
||||
#ifdef COLOR_RUN_SIMPLE
|
||||
/* This is really slow. Is there any way we might speed it up?
|
||||
Two ideas:
|
||||
|
||||
First, maybe we should be working at 32-bit alignment. Then,
|
||||
this can be a simple loop over word stores.
|
||||
|
||||
Second, we can keep working at 24-bit alignment, but have some
|
||||
intelligence about storing. For example, we can iterate over
|
||||
4-pixel chunks (aligned at 4 pixels), with an inner loop
|
||||
something like:
|
||||
|
||||
*buf++ = v1;
|
||||
*buf++ = v2;
|
||||
*buf++ = v3;
|
||||
|
||||
One source of extra complexity is the need to make sure linebuf is
|
||||
aligned to a 32-bit boundary.
|
||||
|
||||
This second alternative has some complexity to it, but is
|
||||
appealing because it really minimizes the memory bandwidth. */
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == g && g == b)
|
||||
{
|
||||
memset (buf, g, n + n + n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COLOR_RUN_COMPLEX
|
||||
/* This implements the second of the two ideas above. The test results
|
||||
are _very_ encouraging - it seems the speed is within 10% of
|
||||
memset, which is quite good! */
|
||||
/**
|
||||
* art_rgb_fill_run: fill a buffer a solid RGB color.
|
||||
* @buf: Buffer to fill.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @n: Number of RGB triples to fill.
|
||||
*
|
||||
* Fills a buffer with @n copies of the (@r, @g, @b) triple. Thus,
|
||||
* locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
|
||||
* written.
|
||||
*
|
||||
* The implementation of this routine is very highly optimized.
|
||||
**/
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
|
||||
{
|
||||
int i;
|
||||
unsigned int v1, v2, v3;
|
||||
|
||||
if (r == g && g == b)
|
||||
{
|
||||
memset (buf, g, n + n + n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < 8)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
} else {
|
||||
/* handle prefix up to byte alignment */
|
||||
/* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
|
||||
architectures, but it _should_ work. */
|
||||
for (i = 0; ((unsigned long)buf) & 3; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
v1 = r | (g << 8) | (b << 16) | (r << 24);
|
||||
v3 = (v1 << 8) | b;
|
||||
v2 = (v3 << 8) | g;
|
||||
#else
|
||||
v1 = (r << 24) | (g << 16) | (b << 8) | r;
|
||||
v2 = (v1 << 8) | g;
|
||||
v3 = (v2 << 8) | b;
|
||||
#endif
|
||||
for (; i < n - 3; i += 4)
|
||||
{
|
||||
((art_u32 *)buf)[0] = v1;
|
||||
((art_u32 *)buf)[1] = v2;
|
||||
((art_u32 *)buf)[2] = v3;
|
||||
buf += 12;
|
||||
}
|
||||
/* handle postfix */
|
||||
for (; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_rgb_run_alpha: Render semitransparent color over RGB buffer.
|
||||
* @buf: Buffer for rendering.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @alpha: Alpha, range 0..256.
|
||||
* @n: Number of RGB triples to render.
|
||||
*
|
||||
* Renders a sequential run of solid (@r, @g, @b) color over @buf with
|
||||
* opacity @alpha.
|
||||
**/
|
||||
void
|
||||
art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
|
||||
{
|
||||
int i;
|
||||
int v;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
v = *buf;
|
||||
*buf++ = v + (((r - v) * alpha + 0x80) >> 8);
|
||||
v = *buf;
|
||||
*buf++ = v + (((g - v) * alpha + 0x80) >> 8);
|
||||
v = *buf;
|
||||
*buf++ = v + (((b - v) * alpha + 0x80) >> 8);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_H__
|
||||
#define __ART_RGB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
|
||||
|
||||
void
|
||||
art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha,
|
||||
int n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,147 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine_private.h"
|
||||
#include "art_rgb_a_affine.h"
|
||||
|
||||
/* This module handles compositing of affine-transformed alpha only images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. */
|
||||
|
||||
/**
|
||||
* art_rgb_a_affine: Affine transform source Alpha image and composite.
|
||||
* @dst: Destination image RGB buffer.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @dst_rowstride: Rowstride of @dst buffer.
|
||||
* @src: Source image alpha buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @rgb: RGB foreground color, in 0xRRGGBB.
|
||||
* @affine: Affine transform.
|
||||
* @level: Filter level.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Affine transform the solid color rgb with alpha specified by the
|
||||
* source image stored in @src, compositing over the area of destination
|
||||
* image @dst specified by the rectangle (@x0, @y0) - (@x1, @y1).
|
||||
* As usual in libart, the left and top edges of this rectangle are
|
||||
* included, and the right and bottom edges are excluded.
|
||||
*
|
||||
* The @alphagamma parameter specifies that the alpha compositing be
|
||||
* done in a gamma-corrected color space. In the current
|
||||
* implementation, it is ignored.
|
||||
*
|
||||
* The @level parameter specifies the speed/quality tradeoff of the
|
||||
* image interpolation. Currently, only ART_FILTER_NEAREST is
|
||||
* implemented.
|
||||
**/
|
||||
void
|
||||
art_rgb_a_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
art_u32 rgb,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
/* Note: this is a slow implementation, and is missing all filter
|
||||
levels other than NEAREST. It is here for clarity of presentation
|
||||
and to establish the interface. */
|
||||
int x, y;
|
||||
double inv[6];
|
||||
art_u8 *dst_p, *dst_linestart;
|
||||
const art_u8 *src_p;
|
||||
ArtPoint pt, src_pt;
|
||||
int src_x, src_y;
|
||||
int alpha;
|
||||
art_u8 bg_r, bg_g, bg_b;
|
||||
art_u8 fg_r, fg_g, fg_b;
|
||||
int tmp;
|
||||
int run_x0, run_x1;
|
||||
art_u8 r, g, b;
|
||||
|
||||
r = (rgb>>16)&0xff;
|
||||
g = (rgb>>8)&0xff;
|
||||
b = (rgb)&0xff;
|
||||
|
||||
dst_linestart = dst;
|
||||
art_affine_invert (inv, affine);
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
pt.y = y + 0.5;
|
||||
run_x0 = x0;
|
||||
run_x1 = x1;
|
||||
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
|
||||
inv);
|
||||
dst_p = dst_linestart + (run_x0 - x0) * 3;
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
pt.x = x + 0.5;
|
||||
art_affine_point (&src_pt, &pt, inv);
|
||||
src_x = floor (src_pt.x);
|
||||
src_y = floor (src_pt.y);
|
||||
src_p = src + (src_y * src_rowstride) + src_x;
|
||||
if (src_x >= 0 && src_x < src_width &&
|
||||
src_y >= 0 && src_y < src_height)
|
||||
{
|
||||
|
||||
alpha = *src_p;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha == 255)
|
||||
{
|
||||
dst_p[0] = r;
|
||||
dst_p[1] = g;
|
||||
dst_p[2] = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
bg_r = dst_p[0];
|
||||
bg_g = dst_p[1];
|
||||
bg_b = dst_p[2];
|
||||
|
||||
tmp = (r - bg_r) * alpha;
|
||||
fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (g - bg_g) * alpha;
|
||||
fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (b - bg_b) * alpha;
|
||||
fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
|
||||
dst_p[0] = fg_r;
|
||||
dst_p[1] = fg_g;
|
||||
dst_p[2] = fg_b;
|
||||
}
|
||||
}
|
||||
} else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_A_AFFINE_H__
|
||||
#define __ART_RGB_A_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed alpha only images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_a_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
art_u32 rgb,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine.h"
|
||||
#include "art_rgb_affine_private.h"
|
||||
|
||||
/* This module handles compositing of affine-transformed rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/**
|
||||
* art_rgb_affine: Affine transform source RGB image and composite.
|
||||
* @dst: Destination image RGB buffer.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @dst_rowstride: Rowstride of @dst buffer.
|
||||
* @src: Source image RGB buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @affine: Affine transform.
|
||||
* @level: Filter level.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Affine transform the source image stored in @src, compositing over
|
||||
* the area of destination image @dst specified by the rectangle
|
||||
* (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
|
||||
* of this rectangle are included, and the right and bottom edges are
|
||||
* excluded.
|
||||
*
|
||||
* The @alphagamma parameter specifies that the alpha compositing be done
|
||||
* in a gamma-corrected color space. Since the source image is opaque RGB,
|
||||
* this argument only affects the edges. In the current implementation,
|
||||
* it is ignored.
|
||||
*
|
||||
* The @level parameter specifies the speed/quality tradeoff of the
|
||||
* image interpolation. Currently, only ART_FILTER_NEAREST is
|
||||
* implemented.
|
||||
**/
|
||||
void
|
||||
art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
/* Note: this is a slow implementation, and is missing all filter
|
||||
levels other than NEAREST. It is here for clarity of presentation
|
||||
and to establish the interface. */
|
||||
int x, y;
|
||||
double inv[6];
|
||||
art_u8 *dst_p, *dst_linestart;
|
||||
const art_u8 *src_p;
|
||||
ArtPoint pt, src_pt;
|
||||
int src_x, src_y;
|
||||
int run_x0, run_x1;
|
||||
|
||||
dst_linestart = dst;
|
||||
art_affine_invert (inv, affine);
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
pt.y = y + 0.5;
|
||||
run_x0 = x0;
|
||||
run_x1 = x1;
|
||||
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
|
||||
inv);
|
||||
dst_p = dst_linestart + (run_x0 - x0) * 3;
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
pt.x = x + 0.5;
|
||||
art_affine_point (&src_pt, &pt, inv);
|
||||
src_x = floor (src_pt.x);
|
||||
src_y = floor (src_pt.y);
|
||||
src_p = src + (src_y * src_rowstride) + src_x * 3;
|
||||
dst_p[0] = src_p[0];
|
||||
dst_p[1] = src_p[1];
|
||||
dst_p[2] = src_p[2];
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_AFFINE_H__
|
||||
#define __ART_RGB_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine_private.h"
|
||||
|
||||
/* Private functions for the rgb affine image compositors - primarily,
|
||||
the determination of runs, eliminating the need for source image
|
||||
bbox calculation in the inner loop. */
|
||||
|
||||
/* Determine a "run", such that the inverse affine of all pixels from
|
||||
(x0, y) inclusive to (x1, y) exclusive fit within the bounds
|
||||
of the source image.
|
||||
|
||||
Initial values of x0, x1, and result values stored in first two
|
||||
pointer arguments.
|
||||
*/
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
void
|
||||
art_rgb_affine_run (int *p_x0, int *p_x1, int y,
|
||||
int src_width, int src_height,
|
||||
const double affine[6])
|
||||
{
|
||||
int x0, x1;
|
||||
double z;
|
||||
double x_intercept;
|
||||
int xi;
|
||||
|
||||
x0 = *p_x0;
|
||||
x1 = *p_x1;
|
||||
|
||||
/* do left and right edges */
|
||||
if (affine[0] > EPSILON)
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
x_intercept = -z / affine[0];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = (-z + src_width) / affine[0];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else if (affine[0] < -EPSILON)
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
x_intercept = (-z + src_width) / affine[0];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = -z / affine[0];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
if (z < 0 || z >= src_width)
|
||||
{
|
||||
*p_x1 = *p_x0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* do top and bottom edges */
|
||||
if (affine[1] > EPSILON)
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
x_intercept = -z / affine[1];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = (-z + src_height) / affine[1];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else if (affine[1] < -EPSILON)
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
x_intercept = (-z + src_height) / affine[1];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = -z / affine[1];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
if (z < 0 || z >= src_height)
|
||||
{
|
||||
*p_x1 = *p_x0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*p_x0 = x0;
|
||||
*p_x1 = x1;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_AFFINE_PRIVATE_H__
|
||||
#define __ART_RGB_AFFINE_PRIVATE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_affine_run (int *p_x0, int *p_x1, int y,
|
||||
int src_width, int src_height,
|
||||
const double affine[6]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,196 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine_private.h"
|
||||
#include "art_rgb_bitmap_affine.h"
|
||||
|
||||
/* This module handles compositing of affine-transformed bitmap images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. Foreground color is given and assumed to be
|
||||
opaque, background color is assumed to be fully transparent. */
|
||||
|
||||
static void
|
||||
art_rgb_bitmap_affine_opaque (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1,
|
||||
int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
art_u32 rgb,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
/* Note: this is a slow implementation, and is missing all filter
|
||||
levels other than NEAREST. It is here for clarity of presentation
|
||||
and to establish the interface. */
|
||||
int x, y;
|
||||
double inv[6];
|
||||
art_u8 *dst_p, *dst_linestart;
|
||||
const art_u8 *src_p;
|
||||
ArtPoint pt, src_pt;
|
||||
int src_x, src_y;
|
||||
art_u8 r, g, b;
|
||||
int run_x0, run_x1;
|
||||
|
||||
r = rgb >> 16;
|
||||
g = (rgb >> 8) & 0xff;
|
||||
b = rgb & 0xff;
|
||||
dst_linestart = dst;
|
||||
art_affine_invert (inv, affine);
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
pt.y = y + 0.5;
|
||||
run_x0 = x0;
|
||||
run_x1 = x1;
|
||||
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
|
||||
inv);
|
||||
dst_p = dst_linestart + (run_x0 - x0) * 3;
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
pt.x = x + 0.5;
|
||||
art_affine_point (&src_pt, &pt, inv);
|
||||
src_x = floor (src_pt.x);
|
||||
src_y = floor (src_pt.y);
|
||||
src_p = src + (src_y * src_rowstride) + (src_x >> 3);
|
||||
if (*src_p & (128 >> (src_x & 7)))
|
||||
{
|
||||
dst_p[0] = r;
|
||||
dst_p[1] = g;
|
||||
dst_p[2] = b;
|
||||
}
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. Foreground color is given, background color is
|
||||
assumed to be fully transparent. */
|
||||
|
||||
/**
|
||||
* art_rgb_bitmap_affine: Affine transform source bitmap image and composite.
|
||||
* @dst: Destination image RGB buffer.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @dst_rowstride: Rowstride of @dst buffer.
|
||||
* @src: Source image bitmap buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @rgba: RGBA foreground color, in 0xRRGGBBAA.
|
||||
* @affine: Affine transform.
|
||||
* @level: Filter level.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Affine transform the source image stored in @src, compositing over
|
||||
* the area of destination image @dst specified by the rectangle
|
||||
* (@x0, @y0) - (@x1, @y1).
|
||||
*
|
||||
* The source bitmap stored with MSB as the leftmost pixel. Source 1
|
||||
* bits correspond to the semitransparent color @rgba, while source 0
|
||||
* bits are transparent.
|
||||
*
|
||||
* See art_rgb_affine() for a description of additional parameters.
|
||||
**/
|
||||
void
|
||||
art_rgb_bitmap_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
art_u32 rgba,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
/* Note: this is a slow implementation, and is missing all filter
|
||||
levels other than NEAREST. It is here for clarity of presentation
|
||||
and to establish the interface. */
|
||||
int x, y;
|
||||
double inv[6];
|
||||
art_u8 *dst_p, *dst_linestart;
|
||||
const art_u8 *src_p;
|
||||
ArtPoint pt, src_pt;
|
||||
int src_x, src_y;
|
||||
int alpha;
|
||||
art_u8 bg_r, bg_g, bg_b;
|
||||
art_u8 fg_r, fg_g, fg_b;
|
||||
art_u8 r, g, b;
|
||||
int run_x0, run_x1;
|
||||
|
||||
alpha = rgba & 0xff;
|
||||
if (alpha == 0xff)
|
||||
{
|
||||
art_rgb_bitmap_affine_opaque (dst, x0, y0, x1, y1, dst_rowstride,
|
||||
src,
|
||||
src_width, src_height, src_rowstride,
|
||||
rgba >> 8,
|
||||
affine,
|
||||
level,
|
||||
alphagamma);
|
||||
return;
|
||||
}
|
||||
/* alpha = (65536 * alpha) / 255; */
|
||||
alpha = (alpha << 8) + alpha + (alpha >> 7);
|
||||
r = rgba >> 24;
|
||||
g = (rgba >> 16) & 0xff;
|
||||
b = (rgba >> 8) & 0xff;
|
||||
dst_linestart = dst;
|
||||
art_affine_invert (inv, affine);
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
pt.y = y + 0.5;
|
||||
run_x0 = x0;
|
||||
run_x1 = x1;
|
||||
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
|
||||
inv);
|
||||
dst_p = dst_linestart + (run_x0 - x0) * 3;
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
pt.x = x + 0.5;
|
||||
art_affine_point (&src_pt, &pt, inv);
|
||||
src_x = floor (src_pt.x);
|
||||
src_y = floor (src_pt.y);
|
||||
src_p = src + (src_y * src_rowstride) + (src_x >> 3);
|
||||
if (*src_p & (128 >> (src_x & 7)))
|
||||
{
|
||||
bg_r = dst_p[0];
|
||||
bg_g = dst_p[1];
|
||||
bg_b = dst_p[2];
|
||||
|
||||
fg_r = bg_r + (((r - bg_r) * alpha + 0x8000) >> 16);
|
||||
fg_g = bg_g + (((g - bg_g) * alpha + 0x8000) >> 16);
|
||||
fg_b = bg_b + (((b - bg_b) * alpha + 0x8000) >> 16);
|
||||
|
||||
dst_p[0] = fg_r;
|
||||
dst_p[1] = fg_g;
|
||||
dst_p[2] = fg_b;
|
||||
}
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_BITMAP_AFFINE_H__
|
||||
#define __ART_RGB_BITMAP_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed bitmap images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_bitmap_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
art_u32 rgba,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,102 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_pixbuf.h"
|
||||
#include "art_rgb_affine.h"
|
||||
#include "art_rgb_affine.h"
|
||||
#include "art_rgb_rgba_affine.h"
|
||||
#include "art_rgb_pixbuf_affine.h"
|
||||
|
||||
/* This module handles compositing of affine-transformed generic
|
||||
pixbuf images over rgb pixel buffers. */
|
||||
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. */
|
||||
/**
|
||||
* art_rgb_pixbuf_affine: Affine transform source RGB pixbuf and composite.
|
||||
* @dst: Destination image RGB buffer.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @dst_rowstride: Rowstride of @dst buffer.
|
||||
* @pixbuf: source image pixbuf.
|
||||
* @affine: Affine transform.
|
||||
* @level: Filter level.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Affine transform the source image stored in @src, compositing over
|
||||
* the area of destination image @dst specified by the rectangle
|
||||
* (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
|
||||
* of this rectangle are included, and the right and bottom edges are
|
||||
* excluded.
|
||||
*
|
||||
* The @alphagamma parameter specifies that the alpha compositing be
|
||||
* done in a gamma-corrected color space. In the current
|
||||
* implementation, it is ignored.
|
||||
*
|
||||
* The @level parameter specifies the speed/quality tradeoff of the
|
||||
* image interpolation. Currently, only ART_FILTER_NEAREST is
|
||||
* implemented.
|
||||
**/
|
||||
void
|
||||
art_rgb_pixbuf_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const ArtPixBuf *pixbuf,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
if (pixbuf->format != ART_PIX_RGB)
|
||||
{
|
||||
art_warn ("art_rgb_pixbuf_affine: need RGB format image\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixbuf->bits_per_sample != 8)
|
||||
{
|
||||
art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixbuf->n_channels != 3 + (pixbuf->has_alpha != 0))
|
||||
{
|
||||
art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pixbuf->has_alpha)
|
||||
art_rgb_rgba_affine (dst, x0, y0, x1, y1, dst_rowstride,
|
||||
pixbuf->pixels,
|
||||
pixbuf->width, pixbuf->height, pixbuf->rowstride,
|
||||
affine,
|
||||
level,
|
||||
alphagamma);
|
||||
else
|
||||
art_rgb_affine (dst, x0, y0, x1, y1, dst_rowstride,
|
||||
pixbuf->pixels,
|
||||
pixbuf->width, pixbuf->height, pixbuf->rowstride,
|
||||
affine,
|
||||
level,
|
||||
alphagamma);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_PIXBUF_AFFINE_H__
|
||||
#define __ART_RGB_PIXBUF_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed generic
|
||||
pixbuf images over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_pixbuf.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#include <libart_lgpl/art_pixbuf.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_pixbuf_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const ArtPixBuf *pixbuf,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,140 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine_private.h"
|
||||
#include "art_rgb_rgba_affine.h"
|
||||
|
||||
/* This module handles compositing of affine-transformed rgba images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. */
|
||||
|
||||
/**
|
||||
* art_rgb_rgba_affine: Affine transform source RGBA image and composite.
|
||||
* @dst: Destination image RGB buffer.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @dst_rowstride: Rowstride of @dst buffer.
|
||||
* @src: Source image RGBA buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @affine: Affine transform.
|
||||
* @level: Filter level.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Affine transform the source image stored in @src, compositing over
|
||||
* the area of destination image @dst specified by the rectangle
|
||||
* (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
|
||||
* of this rectangle are included, and the right and bottom edges are
|
||||
* excluded.
|
||||
*
|
||||
* The @alphagamma parameter specifies that the alpha compositing be
|
||||
* done in a gamma-corrected color space. In the current
|
||||
* implementation, it is ignored.
|
||||
*
|
||||
* The @level parameter specifies the speed/quality tradeoff of the
|
||||
* image interpolation. Currently, only ART_FILTER_NEAREST is
|
||||
* implemented.
|
||||
**/
|
||||
void
|
||||
art_rgb_rgba_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
/* Note: this is a slow implementation, and is missing all filter
|
||||
levels other than NEAREST. It is here for clarity of presentation
|
||||
and to establish the interface. */
|
||||
int x, y;
|
||||
double inv[6];
|
||||
art_u8 *dst_p, *dst_linestart;
|
||||
const art_u8 *src_p;
|
||||
ArtPoint pt, src_pt;
|
||||
int src_x, src_y;
|
||||
int alpha;
|
||||
art_u8 bg_r, bg_g, bg_b;
|
||||
art_u8 fg_r, fg_g, fg_b;
|
||||
int tmp;
|
||||
int run_x0, run_x1;
|
||||
|
||||
dst_linestart = dst;
|
||||
art_affine_invert (inv, affine);
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
pt.y = y + 0.5;
|
||||
run_x0 = x0;
|
||||
run_x1 = x1;
|
||||
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
|
||||
inv);
|
||||
dst_p = dst_linestart + (run_x0 - x0) * 3;
|
||||
for (x = run_x0; x < run_x1; x++)
|
||||
{
|
||||
pt.x = x + 0.5;
|
||||
art_affine_point (&src_pt, &pt, inv);
|
||||
src_x = floor (src_pt.x);
|
||||
src_y = floor (src_pt.y);
|
||||
src_p = src + (src_y * src_rowstride) + src_x * 4;
|
||||
if (src_x >= 0 && src_x < src_width &&
|
||||
src_y >= 0 && src_y < src_height)
|
||||
{
|
||||
|
||||
alpha = src_p[3];
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha == 255)
|
||||
{
|
||||
dst_p[0] = src_p[0];
|
||||
dst_p[1] = src_p[1];
|
||||
dst_p[2] = src_p[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
bg_r = dst_p[0];
|
||||
bg_g = dst_p[1];
|
||||
bg_b = dst_p[2];
|
||||
|
||||
tmp = (src_p[0] - bg_r) * alpha;
|
||||
fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (src_p[1] - bg_g) * alpha;
|
||||
fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (src_p[2] - bg_b) * alpha;
|
||||
fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
|
||||
dst_p[0] = fg_r;
|
||||
dst_p[1] = fg_g;
|
||||
dst_p[2] = fg_b;
|
||||
}
|
||||
}
|
||||
} else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_RGBA_AFFINE_H__
|
||||
#define __ART_RGB_RGBA_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgba images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_rgba_affine (art_u8 *dst,
|
||||
int x0, int y0, int x1, int y1, int dst_rowstride,
|
||||
const art_u8 *src,
|
||||
int src_width, int src_height, int src_rowstride,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,457 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into an RGB buffer. */
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
#include "art_rgb.h"
|
||||
#include "art_rgb_svp.h"
|
||||
|
||||
typedef struct _ArtRgbSVPData ArtRgbSVPData;
|
||||
typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
|
||||
|
||||
struct _ArtRgbSVPData {
|
||||
art_u32 rgbtab[256];
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
struct _ArtRgbSVPAlphaData {
|
||||
int alphatab[256];
|
||||
art_u8 r, g, b, alpha;
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
static void
|
||||
art_rgb_svp_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
art_u32 rgb;
|
||||
int x0, x1;
|
||||
int k;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
run_x1 - x0);
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/* Render the vector path into the RGB buffer. */
|
||||
|
||||
/**
|
||||
* art_rgb_svp_aa: Render sorted vector path into RGB buffer.
|
||||
* @svp: The source sorted vector path.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @fg_color: Foreground color in 0xRRGGBB format.
|
||||
* @bg_color: Background color in 0xRRGGBB format.
|
||||
* @buf: Destination RGB buffer.
|
||||
* @rowstride: Rowstride of @buf buffer.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
|
||||
*
|
||||
* Renders the shape specified with @svp into the @buf RGB buffer.
|
||||
* @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
|
||||
* of the rectangle rendered. The new pixels are stored starting at
|
||||
* the first byte of @buf. Thus, the @x0 and @y0 parameters specify
|
||||
* an offset within @svp, and may be tweaked as a way of doing
|
||||
* integer-pixel translations without fiddling with @svp itself.
|
||||
*
|
||||
* The @fg_color and @bg_color arguments specify the opaque colors to
|
||||
* be used for rendering. For pixels of entirely 0 winding-number,
|
||||
* @bg_color is used. For pixels of entirely 1 winding number,
|
||||
* @fg_color is used. In between, the color is interpolated based on
|
||||
* the fraction of the pixel with a winding number of 1. If
|
||||
* @alphagamma is NULL, then linear interpolation (in pixel counts) is
|
||||
* the default. Otherwise, the interpolation is as specified by
|
||||
* @alphagamma.
|
||||
**/
|
||||
void
|
||||
art_rgb_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 fg_color, art_u32 bg_color,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
ArtRgbSVPData data;
|
||||
|
||||
int r_fg, g_fg, b_fg;
|
||||
int r_bg, g_bg, b_bg;
|
||||
int r, g, b;
|
||||
int dr, dg, db;
|
||||
int i;
|
||||
|
||||
if (alphagamma == NULL)
|
||||
{
|
||||
r_fg = fg_color >> 16;
|
||||
g_fg = (fg_color >> 8) & 0xff;
|
||||
b_fg = fg_color & 0xff;
|
||||
|
||||
r_bg = bg_color >> 16;
|
||||
g_bg = (bg_color >> 8) & 0xff;
|
||||
b_bg = bg_color & 0xff;
|
||||
|
||||
r = (r_bg << 16) + 0x8000;
|
||||
g = (g_bg << 16) + 0x8000;
|
||||
b = (b_bg << 16) + 0x8000;
|
||||
dr = ((r_fg - r_bg) << 16) / 255;
|
||||
dg = ((g_fg - g_bg) << 16) / 255;
|
||||
db = ((b_fg - b_bg) << 16) / 255;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int *table;
|
||||
art_u8 *invtab;
|
||||
|
||||
table = alphagamma->table;
|
||||
|
||||
r_fg = table[fg_color >> 16];
|
||||
g_fg = table[(fg_color >> 8) & 0xff];
|
||||
b_fg = table[fg_color & 0xff];
|
||||
|
||||
r_bg = table[bg_color >> 16];
|
||||
g_bg = table[(bg_color >> 8) & 0xff];
|
||||
b_bg = table[bg_color & 0xff];
|
||||
|
||||
r = (r_bg << 16) + 0x8000;
|
||||
g = (g_bg << 16) + 0x8000;
|
||||
b = (b_bg << 16) + 0x8000;
|
||||
dr = ((r_fg - r_bg) << 16) / 255;
|
||||
dg = ((g_fg - g_bg) << 16) / 255;
|
||||
db = ((b_fg - b_bg) << 16) / 255;
|
||||
|
||||
invtab = alphagamma->invtable;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.rgbtab[i] = (invtab[r >> 16] << 16) |
|
||||
(invtab[g >> 16] << 8) |
|
||||
invtab[b >> 16];
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
}
|
||||
}
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback, &data);
|
||||
}
|
||||
|
||||
static void
|
||||
art_rgb_svp_alpha_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
art_u8 r, g, b;
|
||||
int *alphatab;
|
||||
int alpha;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
r = data->r;
|
||||
g = data->g;
|
||||
b = data->b;
|
||||
alphatab = data->alphatab;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - x0);
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_rgb_svp_alpha_opaque_callback (void *callback_data, int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
art_u8 r, g, b;
|
||||
int *alphatab;
|
||||
int alpha;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
r = data->r;
|
||||
g = data->g;
|
||||
b = data->b;
|
||||
alphatab = data->alphatab;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf,
|
||||
r, g, b,
|
||||
run_x1 - x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - x0);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b,
|
||||
run_x1 - run_x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b,
|
||||
x1 - run_x1);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf,
|
||||
r, g, b,
|
||||
x1 - x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - x0);
|
||||
}
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
|
||||
* @svp: The source sorted vector path.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @rgba: Color in 0xRRGGBBAA format.
|
||||
* @buf: Destination RGB buffer.
|
||||
* @rowstride: Rowstride of @buf buffer.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Renders the shape specified with @svp over the @buf RGB buffer.
|
||||
* @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
|
||||
* of the rectangle rendered. The new pixels are stored starting at
|
||||
* the first byte of @buf. Thus, the @x0 and @y0 parameters specify
|
||||
* an offset within @svp, and may be tweaked as a way of doing
|
||||
* integer-pixel translations without fiddling with @svp itself.
|
||||
*
|
||||
* The @rgba argument specifies the color for the rendering. Pixels of
|
||||
* entirely 0 winding number are left untouched. Pixels of entirely
|
||||
* 1 winding number have the color @rgba composited over them (ie,
|
||||
* are replaced by the red, green, blue components of @rgba if the alpha
|
||||
* component is 0xff). Pixels of intermediate coverage are interpolated
|
||||
* according to the rule in @alphagamma, or default to linear if
|
||||
* @alphagamma is NULL.
|
||||
**/
|
||||
void
|
||||
art_rgb_svp_alpha (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 rgba,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
ArtRgbSVPAlphaData data;
|
||||
int r, g, b, alpha;
|
||||
int i;
|
||||
int a, da;
|
||||
|
||||
r = rgba >> 24;
|
||||
g = (rgba >> 16) & 0xff;
|
||||
b = (rgba >> 8) & 0xff;
|
||||
alpha = rgba & 0xff;
|
||||
|
||||
data.r = r;
|
||||
data.g = g;
|
||||
data.b = b;
|
||||
data.alpha = alpha;
|
||||
|
||||
a = 0x8000;
|
||||
da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.alphatab[i] = a >> 16;
|
||||
a += da;
|
||||
}
|
||||
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
if (alpha == 255)
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback,
|
||||
&data);
|
||||
else
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback, &data);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGB_SVP_H__
|
||||
#define __ART_RGB_SVP_H__
|
||||
|
||||
/* Render a sorted vector path into an RGB buffer. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_rgb_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 fg_color, art_u32 bg_color,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
void
|
||||
art_rgb_svp_alpha (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 rgba,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RGB_SVP_H__ */
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* art_rgba.c: Functions for manipulating RGBA pixel data.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_rgba.h"
|
||||
|
||||
#define ART_OPTIMIZE_SPACE
|
||||
|
||||
#ifndef ART_OPTIMIZE_SPACE
|
||||
#include "art_rgba_table.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_rgba_rgba_composite: Composite RGBA image over RGBA buffer.
|
||||
* @dst: Destination RGBA buffer.
|
||||
* @src: Source RGBA buffer.
|
||||
* @n: Number of RGBA pixels to composite.
|
||||
*
|
||||
* Composites the RGBA pixels in @dst over the @src buffer.
|
||||
**/
|
||||
void
|
||||
art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba, dst_rgba;
|
||||
#else
|
||||
art_u32 src_abgr, dst_abgr;
|
||||
#endif
|
||||
art_u8 src_alpha, dst_alpha;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = ((art_u32 *)src)[i];
|
||||
src_alpha = src_rgba & 0xff;
|
||||
#else
|
||||
src_abgr = ((art_u32 *)src)[i];
|
||||
src_alpha = (src_abgr >> 24) & 0xff;
|
||||
#endif
|
||||
if (src_alpha)
|
||||
{
|
||||
if (src_alpha == 0xff ||
|
||||
(
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_rgba = ((art_u32 *)dst)[i],
|
||||
dst_alpha = dst_rgba & 0xff,
|
||||
#else
|
||||
dst_abgr = ((art_u32 *)dst)[i],
|
||||
dst_alpha = (dst_abgr >> 24),
|
||||
#endif
|
||||
dst_alpha == 0))
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)dst)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)dst)[i] = src_abgr;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int r, g, b, a;
|
||||
int src_r, src_g, src_b;
|
||||
int dst_r, dst_g, dst_b;
|
||||
int tmp;
|
||||
int c;
|
||||
|
||||
#ifdef ART_OPTIMIZE_SPACE
|
||||
tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80;
|
||||
a = 255 - ((tmp + (tmp >> 8)) >> 8);
|
||||
c = ((src_alpha << 16) + (a >> 1)) / a;
|
||||
#else
|
||||
tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
|
||||
c = tmp & 0x1ffff;
|
||||
a = tmp >> 24;
|
||||
#endif
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_r = (src_rgba >> 24) & 0xff;
|
||||
src_g = (src_rgba >> 16) & 0xff;
|
||||
src_b = (src_rgba >> 8) & 0xff;
|
||||
dst_r = (dst_rgba >> 24) & 0xff;
|
||||
dst_g = (dst_rgba >> 16) & 0xff;
|
||||
dst_b = (dst_rgba >> 8) & 0xff;
|
||||
#else
|
||||
src_r = src_abgr & 0xff;
|
||||
src_g = (src_abgr >> 8) & 0xff;
|
||||
src_b = (src_abgr >> 16) & 0xff;
|
||||
dst_r = dst_abgr & 0xff;
|
||||
dst_g = (dst_abgr >> 8) & 0xff;
|
||||
dst_b = (dst_abgr >> 16) & 0xff;
|
||||
#endif
|
||||
r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16);
|
||||
g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16);
|
||||
b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a;
|
||||
#else
|
||||
((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* it's not clear to me this optimization really wins */
|
||||
else
|
||||
{
|
||||
/* skip over run of transparent pixels */
|
||||
for (; i < n - 1; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = ((art_u32 *)src)[i + 1];
|
||||
if (src_rgba & 0xff)
|
||||
break;
|
||||
#else
|
||||
src_abgr = ((art_u32 *)src)[i + 1];
|
||||
if (src_abgr & 0xff000000)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgba_fill_run: fill an RGBA buffer a solid RGB color.
|
||||
* @buf: Buffer to fill.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @n: Number of RGB triples to fill.
|
||||
*
|
||||
* Fills a buffer with @n copies of the (@r, @g, @b) triple, solid
|
||||
* alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
|
||||
* (exclusive) are written.
|
||||
**/
|
||||
void
|
||||
art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba;
|
||||
#else
|
||||
art_u32 src_abgr;
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
|
||||
#else
|
||||
src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = src_abgr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
|
||||
* @buf: Buffer for rendering.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @alpha: Alpha, range 0..255.
|
||||
* @n: Number of RGB triples to render.
|
||||
*
|
||||
* Renders a sequential run of solid (@r, @g, @b) color over @buf with
|
||||
* opacity @alpha. Note that the range of @alpha is 0..255, in contrast
|
||||
* to art_rgb_run_alpha, which has a range of 0..256.
|
||||
**/
|
||||
void
|
||||
art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba, dst_rgba;
|
||||
#else
|
||||
art_u32 src_abgr, dst_abgr;
|
||||
#endif
|
||||
art_u8 dst_alpha;
|
||||
int a;
|
||||
int dst_r, dst_g, dst_b;
|
||||
int tmp;
|
||||
int c;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
|
||||
#else
|
||||
src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_rgba = ((art_u32 *)buf)[i];
|
||||
dst_alpha = dst_rgba & 0xff;
|
||||
#else
|
||||
dst_abgr = ((art_u32 *)buf)[i];
|
||||
dst_alpha = (dst_abgr >> 24) & 0xff;
|
||||
#endif
|
||||
if (dst_alpha)
|
||||
{
|
||||
#ifdef ART_OPTIMIZE_SPACE
|
||||
tmp = (255 - alpha) * (255 - dst_alpha) + 0x80;
|
||||
a = 255 - ((tmp + (tmp >> 8)) >> 8);
|
||||
c = ((alpha << 16) + (a >> 1)) / a;
|
||||
#else
|
||||
tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
|
||||
c = tmp & 0x1ffff;
|
||||
a = tmp >> 24;
|
||||
#endif
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_r = (dst_rgba >> 24) & 0xff;
|
||||
dst_g = (dst_rgba >> 16) & 0xff;
|
||||
dst_b = (dst_rgba >> 8) & 0xff;
|
||||
#else
|
||||
dst_r = dst_abgr & 0xff;
|
||||
dst_g = (dst_abgr >> 8) & 0xff;
|
||||
dst_b = (dst_abgr >> 16) & 0xff;
|
||||
#endif
|
||||
dst_r += (((r - dst_r) * c + 0x8000) >> 16);
|
||||
dst_g += (((g - dst_g) * c + 0x8000) >> 16);
|
||||
dst_b += (((b - dst_b) * c + 0x8000) >> 16);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = src_abgr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* art_rgba.h: Functions for manipulating RGBA pixel data.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_RGBA_H__
|
||||
#define __ART_RGBA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n);
|
||||
|
||||
void
|
||||
art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
|
||||
|
||||
void
|
||||
art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,152 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for sorted vector paths */
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_rect.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
/* Add a new segment. The arguments can be zero and NULL if the caller
|
||||
would rather fill them in later.
|
||||
|
||||
We also realloc one auxiliary array of ints of size n_segs if
|
||||
desired.
|
||||
*/
|
||||
/**
|
||||
* art_svp_add_segment: Add a segment to an #ArtSVP structure.
|
||||
* @p_vp: Pointer to where the #ArtSVP structure is stored.
|
||||
* @pn_segs_max: Pointer to the allocated size of *@p_vp.
|
||||
* @pn_points_max: Pointer to where auxiliary array is stored.
|
||||
* @n_points: Number of points for new segment.
|
||||
* @dir: Direction for new segment; 0 is up, 1 is down.
|
||||
* @points: Points for new segment.
|
||||
* @bbox: Bounding box for new segment.
|
||||
*
|
||||
* Adds a new segment to an ArtSVP structure. This routine reallocates
|
||||
* the structure if necessary, updating *@p_vp and *@pn_segs_max as
|
||||
* necessary.
|
||||
*
|
||||
* The new segment is simply added after all other segments. Thus,
|
||||
* this routine should be called in order consistent with the #ArtSVP
|
||||
* sorting rules.
|
||||
*
|
||||
* If the @bbox argument is given, it is simply stored in the new
|
||||
* segment. Otherwise (if it is NULL), the bounding box is computed
|
||||
* from the @points given.
|
||||
**/
|
||||
int
|
||||
art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
|
||||
int **pn_points_max,
|
||||
int n_points, int dir, ArtPoint *points,
|
||||
ArtDRect *bbox)
|
||||
{
|
||||
int seg_num;
|
||||
ArtSVP *svp;
|
||||
ArtSVPSeg *seg;
|
||||
|
||||
svp = *p_vp;
|
||||
seg_num = svp->n_segs++;
|
||||
if (*pn_segs_max == seg_num)
|
||||
{
|
||||
*pn_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(*pn_segs_max - 1) * sizeof(ArtSVPSeg));
|
||||
*p_vp = svp;
|
||||
if (pn_points_max != NULL)
|
||||
*pn_points_max = art_renew (*pn_points_max, int, *pn_segs_max);
|
||||
}
|
||||
seg = &svp->segs[seg_num];
|
||||
seg->n_points = n_points;
|
||||
seg->dir = dir;
|
||||
seg->points = points;
|
||||
if (bbox)
|
||||
seg->bbox = *bbox;
|
||||
else if (points)
|
||||
{
|
||||
double x_min, x_max;
|
||||
int i;
|
||||
|
||||
x_min = x_max = points[0].x;
|
||||
for (i = 1; i < n_points; i++)
|
||||
{
|
||||
if (x_min > points[i].x)
|
||||
x_min = points[i].x;
|
||||
if (x_max < points[i].x)
|
||||
x_max = points[i].x;
|
||||
}
|
||||
seg->bbox.x0 = x_min;
|
||||
seg->bbox.y0 = points[0].y;
|
||||
|
||||
seg->bbox.x1 = x_max;
|
||||
seg->bbox.y1 = points[n_points - 1].y;
|
||||
}
|
||||
return seg_num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* art_svp_free: Free an #ArtSVP structure.
|
||||
* @svp: #ArtSVP to free.
|
||||
*
|
||||
* Frees an #ArtSVP structure and all the segments in it.
|
||||
**/
|
||||
void
|
||||
art_svp_free (ArtSVP *svp)
|
||||
{
|
||||
int n_segs = svp->n_segs;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_segs; i++)
|
||||
art_free (svp->segs[i].points);
|
||||
art_free (svp);
|
||||
}
|
||||
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#define EPSILON 0
|
||||
#else
|
||||
#define EPSILON 1e-6
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_svp_seg_compare: Compare two segments of an svp.
|
||||
* @seg1: First segment to compare.
|
||||
* @seg2: Second segment to compare.
|
||||
*
|
||||
* Compares two segments of an svp. Return 1 if @seg2 is below or to the
|
||||
* right of @seg1, -1 otherwise.
|
||||
**/
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2)
|
||||
{
|
||||
const ArtSVPSeg *seg1 = s1;
|
||||
const ArtSVPSeg *seg2 = s2;
|
||||
|
||||
if (seg1->points[0].y - EPSILON > seg2->points[0].y) return 1;
|
||||
else if (seg1->points[0].y + EPSILON < seg2->points[0].y) return -1;
|
||||
else if (seg1->points[0].x - EPSILON > seg2->points[0].x) return 1;
|
||||
else if (seg1->points[0].x + EPSILON < seg2->points[0].x) return -1;
|
||||
else if ((seg1->points[1].x - seg1->points[0].x) *
|
||||
(seg2->points[1].y - seg2->points[0].y) -
|
||||
(seg1->points[1].y - seg1->points[0].y) *
|
||||
(seg2->points[1].x - seg2->points[0].x) > 0) return 1;
|
||||
else return -1;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_H__
|
||||
#define __ART_SVP_H__
|
||||
|
||||
/* Basic data structures and constructors for sorted vector paths */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_point.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtSVP ArtSVP;
|
||||
typedef struct _ArtSVPSeg ArtSVPSeg;
|
||||
|
||||
struct _ArtSVPSeg {
|
||||
int n_points;
|
||||
int dir; /* == 0 for "up", 1 for "down" */
|
||||
ArtDRect bbox;
|
||||
ArtPoint *points;
|
||||
};
|
||||
|
||||
struct _ArtSVP {
|
||||
int n_segs;
|
||||
ArtSVPSeg segs[1];
|
||||
};
|
||||
|
||||
int
|
||||
art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
|
||||
int **pn_points_max,
|
||||
int n_points, int dir, ArtPoint *points,
|
||||
ArtDRect *bbox);
|
||||
|
||||
void
|
||||
art_svp_free (ArtSVP *svp);
|
||||
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,64 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2001 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_INTERSECT_H__
|
||||
#define __ART_SVP_INTERSECT_H__
|
||||
|
||||
/* The funky new SVP intersector. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef ART_WIND_RULE_DEFINED
|
||||
#define ART_WIND_RULE_DEFINED
|
||||
typedef enum {
|
||||
ART_WIND_RULE_NONZERO,
|
||||
ART_WIND_RULE_INTERSECT,
|
||||
ART_WIND_RULE_ODDEVEN,
|
||||
ART_WIND_RULE_POSITIVE
|
||||
} ArtWindRule;
|
||||
#endif
|
||||
|
||||
typedef struct _ArtSvpWriter ArtSvpWriter;
|
||||
|
||||
struct _ArtSvpWriter {
|
||||
int (*add_segment) (ArtSvpWriter *self, int wind_left, int delta_wind,
|
||||
double x, double y);
|
||||
void (*add_point) (ArtSvpWriter *self, int seg_id, double x, double y);
|
||||
void (*close_segment) (ArtSvpWriter *self, int seg_id);
|
||||
};
|
||||
|
||||
ArtSvpWriter *
|
||||
art_svp_writer_rewind_new (ArtWindRule rule);
|
||||
|
||||
ArtSVP *
|
||||
art_svp_writer_rewind_reap (ArtSvpWriter *self);
|
||||
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2);
|
||||
|
||||
void
|
||||
art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_INTERSECT_H__ */
|
|
@ -0,0 +1,371 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define noVERBOSE
|
||||
|
||||
/* Vector path set operations, over sorted vpaths. */
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#include "art_svp_intersect.h"
|
||||
#else
|
||||
#include "art_svp_wind.h"
|
||||
#endif
|
||||
#include "art_svp_ops.h"
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
/* Merge the segments of the two svp's. The resulting svp will share
|
||||
segments with args passed in, so be super-careful with the
|
||||
allocation. */
|
||||
/**
|
||||
* art_svp_merge: Merge the segments of two svp's.
|
||||
* @svp1: One svp to merge.
|
||||
* @svp2: The other svp to merge.
|
||||
*
|
||||
* Merges the segments of two SVP's into a new one. The resulting
|
||||
* #ArtSVP data structure will share the segments of the argument
|
||||
* svp's, so it is probably a good idea to free it shallowly,
|
||||
* especially if the arguments will be freed with art_svp_free().
|
||||
*
|
||||
* Return value: The merged #ArtSVP.
|
||||
**/
|
||||
static ArtSVP *
|
||||
art_svp_merge (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
ArtSVP *svp_new;
|
||||
int ix;
|
||||
int ix1, ix2;
|
||||
|
||||
svp_new = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
|
||||
(svp1->n_segs + svp2->n_segs - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
ix1 = 0;
|
||||
ix2 = 0;
|
||||
for (ix = 0; ix < svp1->n_segs + svp2->n_segs; ix++)
|
||||
{
|
||||
if (ix1 < svp1->n_segs &&
|
||||
(ix2 == svp2->n_segs ||
|
||||
art_svp_seg_compare (&svp1->segs[ix1], &svp2->segs[ix2]) < 1))
|
||||
svp_new->segs[ix] = svp1->segs[ix1++];
|
||||
else
|
||||
svp_new->segs[ix] = svp2->segs[ix2++];
|
||||
}
|
||||
|
||||
svp_new->n_segs = ix;
|
||||
return svp_new;
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
||||
#define XOFF 50
|
||||
#define YOFF 700
|
||||
|
||||
static void
|
||||
print_ps_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vpath[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
case ART_LINETO:
|
||||
printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ("stroke showpage\n");
|
||||
}
|
||||
|
||||
#define DELT 4
|
||||
|
||||
static void
|
||||
print_ps_svp (ArtSVP *vpath)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
printf ("%% begin\n");
|
||||
for (i = 0; i < vpath->n_segs; i++)
|
||||
{
|
||||
printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
|
||||
for (j = 0; j < vpath->segs[i].n_points; j++)
|
||||
{
|
||||
printf ("%g %g %s\n",
|
||||
XOFF + vpath->segs[i].points[j].x,
|
||||
YOFF - vpath->segs[i].points[j].y,
|
||||
j ? "lineto" : "moveto");
|
||||
}
|
||||
printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
|
||||
XOFF + vpath->segs[i].points[0].x - DELT,
|
||||
YOFF - DELT - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x - DELT,
|
||||
YOFF - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x + DELT,
|
||||
YOFF - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x + DELT,
|
||||
YOFF - DELT - vpath->segs[i].points[0].y);
|
||||
printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
|
||||
XOFF + vpath->segs[i].points[j - 1].x - DELT,
|
||||
YOFF + DELT - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x - DELT,
|
||||
YOFF - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x + DELT,
|
||||
YOFF - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x + DELT,
|
||||
YOFF + DELT - vpath->segs[i].points[j - 1].y);
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
printf ("showpage\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ART_USE_NEW_INTERSECTOR
|
||||
static ArtSVP *
|
||||
art_svp_merge_perturbed (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
ArtVpath *vpath1, *vpath2;
|
||||
ArtVpath *vpath1_p, *vpath2_p;
|
||||
ArtSVP *svp1_p, *svp2_p;
|
||||
ArtSVP *svp_new;
|
||||
|
||||
vpath1 = art_vpath_from_svp (svp1);
|
||||
vpath1_p = art_vpath_perturb (vpath1);
|
||||
art_free (vpath1);
|
||||
svp1_p = art_svp_from_vpath (vpath1_p);
|
||||
art_free (vpath1_p);
|
||||
|
||||
vpath2 = art_vpath_from_svp (svp2);
|
||||
vpath2_p = art_vpath_perturb (vpath2);
|
||||
art_free (vpath2);
|
||||
svp2_p = art_svp_from_vpath (vpath2_p);
|
||||
art_free (vpath2_p);
|
||||
|
||||
svp_new = art_svp_merge (svp1_p, svp2_p);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp1_p);
|
||||
print_ps_svp (svp2_p);
|
||||
print_ps_svp (svp_new);
|
||||
#endif
|
||||
art_free (svp1_p);
|
||||
art_free (svp2_p);
|
||||
|
||||
return svp_new;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Compute the union of two vector paths.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Seems to work.
|
||||
|
||||
Numerical stability: We cheat (adding random perturbation). Thus,
|
||||
it seems very likely that no numerical stability problems will be
|
||||
seen in practice.
|
||||
|
||||
Speed: Would be better if we didn't go to unsorted vector path
|
||||
and back to add the perturbation.
|
||||
|
||||
Precision: The perturbation fuzzes the coordinates slightly. In
|
||||
cases of butting segments, razor thin long holes may appear.
|
||||
|
||||
*/
|
||||
/**
|
||||
* art_svp_union: Compute the union of two sorted vector paths.
|
||||
* @svp1: One sorted vector path.
|
||||
* @svp2: The other sorted vector path.
|
||||
*
|
||||
* Computes the union of the two argument svp's. Given two svp's with
|
||||
* winding numbers of 0 and 1 everywhere, the resulting winding number
|
||||
* will be 1 where either (or both) of the argument svp's has a
|
||||
* winding number 1, 0 otherwise. The result is newly allocated.
|
||||
*
|
||||
* Currently, this routine has accuracy problems pending the
|
||||
* implementation of the new intersector.
|
||||
*
|
||||
* Return value: The union of @svp1 and @svp2.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
ArtSVP *svp3, *svp_new;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
svp3 = art_svp_merge (svp1, svp2);
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
|
||||
art_svp_intersector (svp3, swr);
|
||||
svp_new = art_svp_writer_rewind_reap (swr);
|
||||
art_free (svp3); /* shallow free because svp3 contains shared segments */
|
||||
|
||||
return svp_new;
|
||||
#else
|
||||
ArtSVP *svp3, *svp4, *svp_new;
|
||||
|
||||
svp3 = art_svp_merge_perturbed (svp1, svp2);
|
||||
svp4 = art_svp_uncross (svp3);
|
||||
art_svp_free (svp3);
|
||||
|
||||
svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_POSITIVE);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp4);
|
||||
print_ps_svp (svp_new);
|
||||
#endif
|
||||
art_svp_free (svp4);
|
||||
return svp_new;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Compute the intersection of two vector paths.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Seems to work.
|
||||
|
||||
Numerical stability: We cheat (adding random perturbation). Thus,
|
||||
it seems very likely that no numerical stability problems will be
|
||||
seen in practice.
|
||||
|
||||
Speed: Would be better if we didn't go to unsorted vector path
|
||||
and back to add the perturbation.
|
||||
|
||||
Precision: The perturbation fuzzes the coordinates slightly. In
|
||||
cases of butting segments, razor thin long isolated segments may
|
||||
appear.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* art_svp_intersect: Compute the intersection of two sorted vector paths.
|
||||
* @svp1: One sorted vector path.
|
||||
* @svp2: The other sorted vector path.
|
||||
*
|
||||
* Computes the intersection of the two argument svp's. Given two
|
||||
* svp's with winding numbers of 0 and 1 everywhere, the resulting
|
||||
* winding number will be 1 where both of the argument svp's has a
|
||||
* winding number 1, 0 otherwise. The result is newly allocated.
|
||||
*
|
||||
* Currently, this routine has accuracy problems pending the
|
||||
* implementation of the new intersector.
|
||||
*
|
||||
* Return value: The intersection of @svp1 and @svp2.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
ArtSVP *svp3, *svp_new;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
svp3 = art_svp_merge (svp1, svp2);
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_INTERSECT);
|
||||
art_svp_intersector (svp3, swr);
|
||||
svp_new = art_svp_writer_rewind_reap (swr);
|
||||
art_free (svp3); /* shallow free because svp3 contains shared segments */
|
||||
|
||||
return svp_new;
|
||||
#else
|
||||
ArtSVP *svp3, *svp4, *svp_new;
|
||||
|
||||
svp3 = art_svp_merge_perturbed (svp1, svp2);
|
||||
svp4 = art_svp_uncross (svp3);
|
||||
art_svp_free (svp3);
|
||||
|
||||
svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_INTERSECT);
|
||||
art_svp_free (svp4);
|
||||
return svp_new;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Compute the symmetric difference of two vector paths.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Seems to work.
|
||||
|
||||
Numerical stability: We cheat (adding random perturbation). Thus,
|
||||
it seems very likely that no numerical stability problems will be
|
||||
seen in practice.
|
||||
|
||||
Speed: We could do a lot better by scanning through the svp
|
||||
representations and culling out any segments that are exactly
|
||||
identical. It would also be better if we didn't go to unsorted
|
||||
vector path and back to add the perturbation.
|
||||
|
||||
Precision: Awful. In the case of inputs which are similar (the
|
||||
common case for canvas display), the entire outline is "hairy." In
|
||||
addition, the perturbation fuzzes the coordinates slightly. It can
|
||||
be used as a conservative approximation.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* art_svp_diff: Compute the symmetric difference of two sorted vector paths.
|
||||
* @svp1: One sorted vector path.
|
||||
* @svp2: The other sorted vector path.
|
||||
*
|
||||
* Computes the symmetric of the two argument svp's. Given two svp's
|
||||
* with winding numbers of 0 and 1 everywhere, the resulting winding
|
||||
* number will be 1 where either, but not both, of the argument svp's
|
||||
* has a winding number 1, 0 otherwise. The result is newly allocated.
|
||||
*
|
||||
* Currently, this routine has accuracy problems pending the
|
||||
* implementation of the new intersector.
|
||||
*
|
||||
* Return value: The symmetric difference of @svp1 and @svp2.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
ArtSVP *svp3, *svp_new;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
svp3 = art_svp_merge (svp1, svp2);
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
|
||||
art_svp_intersector (svp3, swr);
|
||||
svp_new = art_svp_writer_rewind_reap (swr);
|
||||
art_free (svp3); /* shallow free because svp3 contains shared segments */
|
||||
|
||||
return svp_new;
|
||||
#else
|
||||
ArtSVP *svp3, *svp4, *svp_new;
|
||||
|
||||
svp3 = art_svp_merge_perturbed (svp1, svp2);
|
||||
svp4 = art_svp_uncross (svp3);
|
||||
art_svp_free (svp3);
|
||||
|
||||
svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_ODDEVEN);
|
||||
art_svp_free (svp4);
|
||||
return svp_new;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* todo: implement minus */
|
|
@ -0,0 +1,38 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_OPS_H__
|
||||
#define __ART_SVP_OPS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Vector path set operations, over sorted vpaths. */
|
||||
|
||||
ArtSVP *art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2);
|
||||
ArtSVP *art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2);
|
||||
ArtSVP *art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2);
|
||||
ArtSVP *art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_OPS_H__ */
|
|
@ -0,0 +1,142 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_point.h"
|
||||
|
||||
/* Determine whether a point is inside, or near, an svp. */
|
||||
|
||||
/* return winding number of point wrt svp */
|
||||
/**
|
||||
* art_svp_point_wind: Determine winding number of a point with respect to svp.
|
||||
* @svp: The svp.
|
||||
* @x: The X coordinate of the point.
|
||||
* @y: The Y coordinate of the point.
|
||||
*
|
||||
* Determine the winding number of the point @x, @y with respect to @svp.
|
||||
*
|
||||
* Return value: the winding number.
|
||||
**/
|
||||
int
|
||||
art_svp_point_wind (ArtSVP *svp, double x, double y)
|
||||
{
|
||||
int i, j;
|
||||
int wind = 0;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
ArtSVPSeg *seg = &svp->segs[i];
|
||||
|
||||
if (seg->bbox.y0 > y)
|
||||
break;
|
||||
|
||||
if (seg->bbox.y1 > y)
|
||||
{
|
||||
if (seg->bbox.x1 < x)
|
||||
wind += seg->dir ? 1 : -1;
|
||||
else if (seg->bbox.x0 <= x)
|
||||
{
|
||||
double x0, y0, x1, y1, dx, dy;
|
||||
|
||||
for (j = 0; j < seg->n_points - 1; j++)
|
||||
{
|
||||
if (seg->points[j + 1].y > y)
|
||||
break;
|
||||
}
|
||||
x0 = seg->points[j].x;
|
||||
y0 = seg->points[j].y;
|
||||
x1 = seg->points[j + 1].x;
|
||||
y1 = seg->points[j + 1].y;
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
if ((x - x0) * dy > (y - y0) * dx)
|
||||
wind += seg->dir ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wind;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_point_dist: Determine distance between point and svp.
|
||||
* @svp: The svp.
|
||||
* @x: The X coordinate of the point.
|
||||
* @y: The Y coordinate of the point.
|
||||
*
|
||||
* Determines the distance of the point @x, @y to the closest edge in
|
||||
* @svp. A large number is returned if @svp is empty.
|
||||
*
|
||||
* Return value: the distance.
|
||||
**/
|
||||
double
|
||||
art_svp_point_dist (ArtSVP *svp, double x, double y)
|
||||
{
|
||||
int i, j;
|
||||
double dist_sq;
|
||||
double best_sq = -1;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
ArtSVPSeg *seg = &svp->segs[i];
|
||||
for (j = 0; j < seg->n_points - 1; j++)
|
||||
{
|
||||
double x0 = seg->points[j].x;
|
||||
double y0 = seg->points[j].y;
|
||||
double x1 = seg->points[j + 1].x;
|
||||
double y1 = seg->points[j + 1].y;
|
||||
|
||||
double dx = x1 - x0;
|
||||
double dy = y1 - y0;
|
||||
|
||||
double dxx0 = x - x0;
|
||||
double dyy0 = y - y0;
|
||||
|
||||
double dot = dxx0 * dx + dyy0 * dy;
|
||||
|
||||
if (dot < 0)
|
||||
dist_sq = dxx0 * dxx0 + dyy0 * dyy0;
|
||||
else
|
||||
{
|
||||
double rr = dx * dx + dy * dy;
|
||||
|
||||
if (dot > rr)
|
||||
dist_sq = (x - x1) * (x - x1) + (y - y1) * (y - y1);
|
||||
else
|
||||
{
|
||||
double perp = (y - y0) * dx - (x - x0) * dy;
|
||||
|
||||
dist_sq = perp * perp / rr;
|
||||
}
|
||||
}
|
||||
if (best_sq < 0 || dist_sq < best_sq)
|
||||
best_sq = dist_sq;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_sq >= 0)
|
||||
return sqrt (best_sq);
|
||||
else
|
||||
return 1e12;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_POINT_H__
|
||||
#define __ART_SVP_POINT_H__
|
||||
|
||||
/* Determine whether a point is inside, or near, an svp. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int
|
||||
art_svp_point_wind (ArtSVP *svp, double x, double y);
|
||||
|
||||
double
|
||||
art_svp_point_dist (ArtSVP *svp, double x, double y);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,461 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* The spiffy antialiased renderer for sorted vector paths. */
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_rect.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
#include "art_svp_render_aa.h"
|
||||
#include "stdio.h"
|
||||
|
||||
typedef double artfloat;
|
||||
|
||||
struct _ArtSVPRenderAAIter {
|
||||
const ArtSVP *svp;
|
||||
int x0, x1;
|
||||
int y;
|
||||
int seg_ix;
|
||||
|
||||
int *active_segs;
|
||||
int n_active_segs;
|
||||
int *cursor;
|
||||
artfloat *seg_x;
|
||||
artfloat *seg_dx;
|
||||
|
||||
ArtSVPRenderAAStep *steps;
|
||||
};
|
||||
|
||||
static void
|
||||
art_svp_render_insert_active (int i, int *active_segs, int n_active_segs,
|
||||
artfloat *seg_x, artfloat *seg_dx)
|
||||
{
|
||||
int j;
|
||||
artfloat x;
|
||||
int tmp1, tmp2;
|
||||
|
||||
/* this is a cheap hack to get ^'s sorted correctly */
|
||||
x = seg_x[i] + 0.001 * seg_dx[i];
|
||||
for (j = 0; j < n_active_segs && seg_x[active_segs[j]] < x; j++);
|
||||
|
||||
tmp1 = i;
|
||||
while (j < n_active_segs)
|
||||
{
|
||||
tmp2 = active_segs[j];
|
||||
active_segs[j] = tmp1;
|
||||
tmp1 = tmp2;
|
||||
j++;
|
||||
}
|
||||
active_segs[j] = tmp1;
|
||||
}
|
||||
|
||||
static void
|
||||
art_svp_render_delete_active (int *active_segs, int j, int n_active_segs)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = j; k < n_active_segs; k++)
|
||||
active_segs[k] = active_segs[k + 1];
|
||||
}
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
/* Render the sorted vector path in the given rectangle, antialiased.
|
||||
|
||||
This interface uses a callback for the actual pixel rendering. The
|
||||
callback is called y1 - y0 times (once for each scan line). The y
|
||||
coordinate is given as an argument for convenience (it could be
|
||||
stored in the callback's private data and incremented on each
|
||||
call).
|
||||
|
||||
The rendered polygon is represented in a semi-runlength format: a
|
||||
start value and a sequence of "steps". Each step has an x
|
||||
coordinate and a value delta. The resulting value at position x is
|
||||
equal to the sum of the start value and all step delta values for
|
||||
which the step x coordinate is less than or equal to x. An
|
||||
efficient algorithm will traverse the steps left to right, keeping
|
||||
a running sum.
|
||||
|
||||
All x coordinates in the steps are guaranteed to be x0 <= x < x1.
|
||||
(This guarantee is a change from the gfonted vpaar renderer, and is
|
||||
designed to simplify the callback).
|
||||
|
||||
There is now a further guarantee that no two steps will have the
|
||||
same x value. This may allow for further speedup and simplification
|
||||
of renderers.
|
||||
|
||||
The value 0x8000 represents 0% coverage by the polygon, while
|
||||
0xff8000 represents 100% coverage. This format is designed so that
|
||||
>> 16 results in a standard 0x00..0xff value range, with nice
|
||||
rounding.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: OK
|
||||
|
||||
Numerical stability: pretty good, although probably not
|
||||
bulletproof.
|
||||
|
||||
Speed: Needs more aggressive culling of bounding boxes. Can
|
||||
probably speed up the [x0,x1) clipping of step values. Can do more
|
||||
of the step calculation in fixed point.
|
||||
|
||||
Precision: No known problems, although it should be tested
|
||||
thoroughly, especially for symmetry.
|
||||
|
||||
*/
|
||||
|
||||
ArtSVPRenderAAIter *
|
||||
art_svp_render_aa_iter (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1)
|
||||
{
|
||||
ArtSVPRenderAAIter *iter = art_new (ArtSVPRenderAAIter, 1);
|
||||
|
||||
iter->svp = svp;
|
||||
iter->y = y0;
|
||||
iter->x0 = x0;
|
||||
iter->x1 = x1;
|
||||
iter->seg_ix = 0;
|
||||
|
||||
iter->active_segs = art_new (int, svp->n_segs);
|
||||
iter->cursor = art_new (int, svp->n_segs);
|
||||
iter->seg_x = art_new (artfloat, svp->n_segs);
|
||||
iter->seg_dx = art_new (artfloat, svp->n_segs);
|
||||
iter->steps = art_new (ArtSVPRenderAAStep, x1 - x0);
|
||||
iter->n_active_segs = 0;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
#define ADD_STEP(xpos, xdelta) \
|
||||
/* stereotype code fragment for adding a step */ \
|
||||
if (n_steps == 0 || steps[n_steps - 1].x < xpos) \
|
||||
{ \
|
||||
sx = n_steps; \
|
||||
steps[sx].x = xpos; \
|
||||
steps[sx].delta = xdelta; \
|
||||
n_steps++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
for (sx = n_steps; sx > 0; sx--) \
|
||||
{ \
|
||||
if (steps[sx - 1].x == xpos) \
|
||||
{ \
|
||||
steps[sx - 1].delta += xdelta; \
|
||||
sx = n_steps; \
|
||||
break; \
|
||||
} \
|
||||
else if (steps[sx - 1].x < xpos) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (sx < n_steps) \
|
||||
{ \
|
||||
memmove (&steps[sx + 1], &steps[sx], \
|
||||
(n_steps - sx) * sizeof(steps[0])); \
|
||||
steps[sx].x = xpos; \
|
||||
steps[sx].delta = xdelta; \
|
||||
n_steps++; \
|
||||
} \
|
||||
}
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
|
||||
ArtSVPRenderAAStep **p_steps, int *p_n_steps)
|
||||
{
|
||||
const ArtSVP *svp = iter->svp;
|
||||
int *active_segs = iter->active_segs;
|
||||
int n_active_segs = iter->n_active_segs;
|
||||
int *cursor = iter->cursor;
|
||||
artfloat *seg_x = iter->seg_x;
|
||||
artfloat *seg_dx = iter->seg_dx;
|
||||
int i = iter->seg_ix;
|
||||
int j;
|
||||
int x0 = iter->x0;
|
||||
int x1 = iter->x1;
|
||||
int y = iter->y;
|
||||
int seg_index;
|
||||
|
||||
int x;
|
||||
ArtSVPRenderAAStep *steps = iter->steps;
|
||||
int n_steps;
|
||||
artfloat y_top, y_bot;
|
||||
artfloat x_top, x_bot;
|
||||
artfloat x_min, x_max;
|
||||
int ix_min, ix_max;
|
||||
artfloat delta; /* delta should be int too? */
|
||||
int last, this;
|
||||
int xdelta;
|
||||
artfloat rslope, drslope;
|
||||
int start;
|
||||
const ArtSVPSeg *seg;
|
||||
int curs;
|
||||
artfloat dy;
|
||||
|
||||
int sx;
|
||||
|
||||
/* insert new active segments */
|
||||
for (; i < svp->n_segs && svp->segs[i].bbox.y0 < y + 1; i++)
|
||||
{
|
||||
if (svp->segs[i].bbox.y1 > y &&
|
||||
svp->segs[i].bbox.x0 < x1)
|
||||
{
|
||||
seg = &svp->segs[i];
|
||||
/* move cursor to topmost vector which overlaps [y,y+1) */
|
||||
for (curs = 0; seg->points[curs + 1].y < y; curs++);
|
||||
cursor[i] = curs;
|
||||
dy = seg->points[curs + 1].y - seg->points[curs].y;
|
||||
if (fabs (dy) >= EPSILON)
|
||||
seg_dx[i] = (seg->points[curs + 1].x - seg->points[curs].x) /
|
||||
dy;
|
||||
else
|
||||
seg_dx[i] = 1e12;
|
||||
seg_x[i] = seg->points[curs].x +
|
||||
(y - seg->points[curs].y) * seg_dx[i];
|
||||
art_svp_render_insert_active (i, active_segs, n_active_segs++,
|
||||
seg_x, seg_dx);
|
||||
}
|
||||
}
|
||||
|
||||
n_steps = 0;
|
||||
|
||||
/* render the runlengths, advancing and deleting as we go */
|
||||
start = 0x8000;
|
||||
|
||||
for (j = 0; j < n_active_segs; j++)
|
||||
{
|
||||
seg_index = active_segs[j];
|
||||
seg = &svp->segs[seg_index];
|
||||
curs = cursor[seg_index];
|
||||
while (curs != seg->n_points - 1 &&
|
||||
seg->points[curs].y < y + 1)
|
||||
{
|
||||
y_top = y;
|
||||
if (y_top < seg->points[curs].y)
|
||||
y_top = seg->points[curs].y;
|
||||
y_bot = y + 1;
|
||||
if (y_bot > seg->points[curs + 1].y)
|
||||
y_bot = seg->points[curs + 1].y;
|
||||
if (y_top != y_bot) {
|
||||
delta = (seg->dir ? 16711680.0 : -16711680.0) *
|
||||
(y_bot - y_top);
|
||||
x_top = seg_x[seg_index] + (y_top - y) * seg_dx[seg_index];
|
||||
x_bot = seg_x[seg_index] + (y_bot - y) * seg_dx[seg_index];
|
||||
if (x_top < x_bot)
|
||||
{
|
||||
x_min = x_top;
|
||||
x_max = x_bot;
|
||||
}
|
||||
else
|
||||
{
|
||||
x_min = x_bot;
|
||||
x_max = x_top;
|
||||
}
|
||||
ix_min = floor (x_min);
|
||||
ix_max = floor (x_max);
|
||||
if (ix_min >= x1)
|
||||
{
|
||||
/* skip; it starts to the right of the render region */
|
||||
}
|
||||
else if (ix_max < x0)
|
||||
/* it ends to the left of the render region */
|
||||
start += delta;
|
||||
else if (ix_min == ix_max)
|
||||
{
|
||||
/* case 1, antialias a single pixel */
|
||||
xdelta = (ix_min + 1 - (x_min + x_max) * 0.5) * delta;
|
||||
|
||||
ADD_STEP(ix_min, xdelta)
|
||||
|
||||
if (ix_min + 1 < x1)
|
||||
{
|
||||
xdelta = delta - xdelta;
|
||||
|
||||
ADD_STEP(ix_min + 1, xdelta)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* case 2, antialias a run */
|
||||
rslope = 1.0 / fabs (seg_dx[seg_index]);
|
||||
drslope = delta * rslope;
|
||||
last =
|
||||
drslope * 0.5 *
|
||||
(ix_min + 1 - x_min) * (ix_min + 1 - x_min);
|
||||
xdelta = last;
|
||||
if (ix_min >= x0)
|
||||
{
|
||||
ADD_STEP(ix_min, xdelta)
|
||||
|
||||
x = ix_min + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start += last;
|
||||
x = x0;
|
||||
}
|
||||
if (ix_max > x1)
|
||||
ix_max = x1;
|
||||
for (; x < ix_max; x++)
|
||||
{
|
||||
this = (seg->dir ? 16711680.0 : -16711680.0) * rslope *
|
||||
(x + 0.5 - x_min);
|
||||
xdelta = this - last;
|
||||
last = this;
|
||||
|
||||
ADD_STEP(x, xdelta)
|
||||
}
|
||||
if (x < x1)
|
||||
{
|
||||
this =
|
||||
delta * (1 - 0.5 *
|
||||
(x_max - ix_max) * (x_max - ix_max) *
|
||||
rslope);
|
||||
xdelta = this - last;
|
||||
last = this;
|
||||
|
||||
ADD_STEP(x, xdelta)
|
||||
|
||||
if (x + 1 < x1)
|
||||
{
|
||||
xdelta = delta - last;
|
||||
|
||||
ADD_STEP(x + 1, xdelta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
curs++;
|
||||
if (curs != seg->n_points - 1 &&
|
||||
seg->points[curs].y < y + 1)
|
||||
{
|
||||
dy = seg->points[curs + 1].y - seg->points[curs].y;
|
||||
if (fabs (dy) >= EPSILON)
|
||||
seg_dx[seg_index] = (seg->points[curs + 1].x -
|
||||
seg->points[curs].x) / dy;
|
||||
else
|
||||
seg_dx[seg_index] = 1e12;
|
||||
seg_x[seg_index] = seg->points[curs].x +
|
||||
(y - seg->points[curs].y) * seg_dx[seg_index];
|
||||
}
|
||||
/* break here, instead of duplicating predicate in while? */
|
||||
}
|
||||
if (seg->points[curs].y >= y + 1)
|
||||
{
|
||||
curs--;
|
||||
cursor[seg_index] = curs;
|
||||
seg_x[seg_index] += seg_dx[seg_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
art_svp_render_delete_active (active_segs, j--,
|
||||
--n_active_segs);
|
||||
}
|
||||
}
|
||||
|
||||
*p_start = start;
|
||||
*p_steps = steps;
|
||||
*p_n_steps = n_steps;
|
||||
|
||||
iter->seg_ix = i;
|
||||
iter->n_active_segs = n_active_segs;
|
||||
iter->y++;
|
||||
}
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter)
|
||||
{
|
||||
art_free (iter->steps);
|
||||
|
||||
art_free (iter->seg_dx);
|
||||
art_free (iter->seg_x);
|
||||
art_free (iter->cursor);
|
||||
art_free (iter->active_segs);
|
||||
art_free (iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_render_aa: Render SVP antialiased.
|
||||
* @svp: The #ArtSVP to render.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @callback: The callback which actually paints the pixels.
|
||||
* @callback_data: Private data for @callback.
|
||||
*
|
||||
* Renders the sorted vector path in the given rectangle, antialiased.
|
||||
*
|
||||
* This interface uses a callback for the actual pixel rendering. The
|
||||
* callback is called @y1 - @y0 times (once for each scan line). The y
|
||||
* coordinate is given as an argument for convenience (it could be
|
||||
* stored in the callback's private data and incremented on each
|
||||
* call).
|
||||
*
|
||||
* The rendered polygon is represented in a semi-runlength format: a
|
||||
* start value and a sequence of "steps". Each step has an x
|
||||
* coordinate and a value delta. The resulting value at position x is
|
||||
* equal to the sum of the start value and all step delta values for
|
||||
* which the step x coordinate is less than or equal to x. An
|
||||
* efficient algorithm will traverse the steps left to right, keeping
|
||||
* a running sum.
|
||||
*
|
||||
* All x coordinates in the steps are guaranteed to be @x0 <= x < @x1.
|
||||
* (This guarantee is a change from the gfonted vpaar renderer from
|
||||
* which this routine is derived, and is designed to simplify the
|
||||
* callback).
|
||||
*
|
||||
* The value 0x8000 represents 0% coverage by the polygon, while
|
||||
* 0xff8000 represents 100% coverage. This format is designed so that
|
||||
* >> 16 results in a standard 0x00..0xff value range, with nice
|
||||
* rounding.
|
||||
*
|
||||
**/
|
||||
void
|
||||
art_svp_render_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
void (*callback) (void *callback_data,
|
||||
int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps),
|
||||
void *callback_data)
|
||||
{
|
||||
ArtSVPRenderAAIter *iter;
|
||||
int y;
|
||||
int start;
|
||||
ArtSVPRenderAAStep *steps;
|
||||
int n_steps;
|
||||
|
||||
iter = art_svp_render_aa_iter (svp, x0, y0, x1, y1);
|
||||
|
||||
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
art_svp_render_aa_iter_step (iter, &start, &steps, &n_steps);
|
||||
(*callback) (callback_data, y, start, steps, n_steps);
|
||||
}
|
||||
|
||||
art_svp_render_aa_iter_done (iter);
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_RENDER_AA_H__
|
||||
#define __ART_SVP_RENDER_AA_H__
|
||||
|
||||
/* The spiffy antialiased renderer for sorted vector paths. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
|
||||
typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
|
||||
|
||||
struct _ArtSVPRenderAAStep {
|
||||
int x;
|
||||
int delta; /* stored with 16 fractional bits */
|
||||
};
|
||||
|
||||
ArtSVPRenderAAIter *
|
||||
art_svp_render_aa_iter (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1);
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
|
||||
ArtSVPRenderAAStep **p_steps, int *p_n_steps);
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter);
|
||||
|
||||
void
|
||||
art_svp_render_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
void (*callback) (void *callback_data,
|
||||
int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps),
|
||||
void *callback_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_RENDER_AA_H__ */
|
|
@ -0,0 +1,213 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Sort vector paths into sorted vector paths */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_vpath.h"
|
||||
|
||||
|
||||
/* reverse a list of points in place */
|
||||
static void
|
||||
reverse_points (ArtPoint *points, int n_points)
|
||||
{
|
||||
int i;
|
||||
ArtPoint tmp_p;
|
||||
|
||||
for (i = 0; i < (n_points >> 1); i++)
|
||||
{
|
||||
tmp_p = points[i];
|
||||
points[i] = points[n_points - (i + 1)];
|
||||
points[n_points - (i + 1)] = tmp_p;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_from_vpath: Convert a vpath to a sorted vector path.
|
||||
* @vpath: #ArtVPath to convert.
|
||||
*
|
||||
* Converts a vector path into sorted vector path form. The svp form is
|
||||
* more efficient for rendering and other vector operations.
|
||||
*
|
||||
* Basically, the implementation is to traverse the vector path,
|
||||
* generating a new segment for each "run" of points in the vector
|
||||
* path with monotonically increasing Y values. All the resulting
|
||||
* values are then sorted.
|
||||
*
|
||||
* Note: I'm not sure that the sorting rule is correct with respect
|
||||
* to numerical stability issues.
|
||||
*
|
||||
* Return value: Resulting sorted vector path.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_from_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int n_segs, n_segs_max;
|
||||
ArtSVP *svp;
|
||||
int dir;
|
||||
int new_dir;
|
||||
int i;
|
||||
ArtPoint *points;
|
||||
int n_points, n_points_max;
|
||||
double x, y;
|
||||
double x_min, x_max;
|
||||
|
||||
n_segs = 0;
|
||||
n_segs_max = 16;
|
||||
svp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) * sizeof(ArtSVPSeg));
|
||||
|
||||
dir = 0;
|
||||
n_points = 0;
|
||||
n_points_max = 0;
|
||||
points = NULL;
|
||||
i = 0;
|
||||
|
||||
x = y = 0; /* unnecessary, given "first code must not be LINETO" invariant,
|
||||
but it makes gcc -Wall -ansi -pedantic happier */
|
||||
x_min = x_max = 0; /* same */
|
||||
|
||||
while (vpath[i].code != ART_END) {
|
||||
if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
|
||||
{
|
||||
if (points != NULL && n_points >= 2)
|
||||
{
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
points = NULL;
|
||||
}
|
||||
|
||||
if (points == NULL)
|
||||
{
|
||||
n_points_max = 4;
|
||||
points = art_new (ArtPoint, n_points_max);
|
||||
}
|
||||
|
||||
n_points = 1;
|
||||
points[0].x = x = vpath[i].x;
|
||||
points[0].y = y = vpath[i].y;
|
||||
x_min = x;
|
||||
x_max = x;
|
||||
dir = 0;
|
||||
}
|
||||
else /* must be LINETO */
|
||||
{
|
||||
new_dir = (vpath[i].y > y ||
|
||||
(vpath[i].y == y && vpath[i].x > x)) ? 1 : -1;
|
||||
if (dir && dir != new_dir)
|
||||
{
|
||||
/* new segment */
|
||||
x = points[n_points - 1].x;
|
||||
y = points[n_points - 1].y;
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
|
||||
n_points = 1;
|
||||
n_points_max = 4;
|
||||
points = art_new (ArtPoint, n_points_max);
|
||||
points[0].x = x;
|
||||
points[0].y = y;
|
||||
x_min = x;
|
||||
x_max = x;
|
||||
}
|
||||
|
||||
if (points != NULL)
|
||||
{
|
||||
if (n_points == n_points_max)
|
||||
art_expand (points, ArtPoint, n_points_max);
|
||||
points[n_points].x = x = vpath[i].x;
|
||||
points[n_points].y = y = vpath[i].y;
|
||||
if (x < x_min) x_min = x;
|
||||
else if (x > x_max) x_max = x;
|
||||
n_points++;
|
||||
}
|
||||
dir = new_dir;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (points != NULL)
|
||||
{
|
||||
if (n_points >= 2)
|
||||
{
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
}
|
||||
else
|
||||
art_free (points);
|
||||
}
|
||||
|
||||
svp->n_segs = n_segs;
|
||||
|
||||
qsort (&svp->segs, n_segs, sizeof (ArtSVPSeg), art_svp_seg_compare);
|
||||
|
||||
return svp;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_VPATH_H__
|
||||
#define __ART_SVP_VPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
/* Sort vector paths into sorted vector paths. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtSVP *
|
||||
art_svp_from_vpath (ArtVpath *vpath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_VPATH_H__ */
|
|
@ -0,0 +1,729 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#include "art_svp_intersect.h"
|
||||
#else
|
||||
#include "art_svp_wind.h"
|
||||
#endif
|
||||
#include "art_svp_vpath.h"
|
||||
#include "art_svp_vpath_stroke.h"
|
||||
|
||||
#define EPSILON 1e-6
|
||||
#define EPSILON_2 1e-12
|
||||
|
||||
#define yes_OPTIMIZE_INNER
|
||||
|
||||
/* Render an arc segment starting at (xc + x0, yc + y0) to (xc + x1,
|
||||
yc + y1), centered at (xc, yc), and with given radius. Both x0^2 +
|
||||
y0^2 and x1^2 + y1^2 should be equal to radius^2.
|
||||
|
||||
A positive value of radius means curve to the left, negative means
|
||||
curve to the right.
|
||||
*/
|
||||
static void
|
||||
art_svp_vpath_stroke_arc (ArtVpath **p_vpath, int *pn, int *pn_max,
|
||||
double xc, double yc,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double radius,
|
||||
double flatness)
|
||||
{
|
||||
double theta;
|
||||
double th_0, th_1;
|
||||
int n_pts;
|
||||
int i;
|
||||
double aradius;
|
||||
|
||||
aradius = fabs (radius);
|
||||
theta = 2 * M_SQRT2 * sqrt (flatness / aradius);
|
||||
th_0 = atan2 (y0, x0);
|
||||
th_1 = atan2 (y1, x1);
|
||||
if (radius > 0)
|
||||
{
|
||||
/* curve to the left */
|
||||
if (th_0 < th_1) th_0 += M_PI * 2;
|
||||
n_pts = ceil ((th_0 - th_1) / theta);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* curve to the right */
|
||||
if (th_1 < th_0) th_1 += M_PI * 2;
|
||||
n_pts = ceil ((th_1 - th_0) / theta);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
printf ("start %f %f; th_0 = %f, th_1 = %f, r = %f, theta = %f\n", x0, y0, th_0, th_1, radius, theta);
|
||||
#endif
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + x0, yc + y0);
|
||||
for (i = 1; i < n_pts; i++)
|
||||
{
|
||||
theta = th_0 + (th_1 - th_0) * i / n_pts;
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + cos (theta) * aradius,
|
||||
yc + sin (theta) * aradius);
|
||||
#ifdef VERBOSE
|
||||
printf ("mid %f %f\n", cos (theta) * radius, sin (theta) * radius);
|
||||
#endif
|
||||
}
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + x1, yc + y1);
|
||||
#ifdef VERBOSE
|
||||
printf ("end %f %f\n", x1, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Assume that forw and rev are at point i0. Bring them to i1,
|
||||
joining with the vector i1 - i2.
|
||||
|
||||
This used to be true, but isn't now that the stroke_raw code is
|
||||
filtering out (near)zero length vectors: {It so happens that all
|
||||
invocations of this function maintain the precondition i1 = i0 + 1,
|
||||
so we could decrease the number of arguments by one. We haven't
|
||||
done that here, though.}
|
||||
|
||||
forw is to the line's right and rev is to its left.
|
||||
|
||||
Precondition: no zero-length vectors, otherwise a divide by
|
||||
zero will happen. */
|
||||
static void
|
||||
render_seg (ArtVpath **p_forw, int *pn_forw, int *pn_forw_max,
|
||||
ArtVpath **p_rev, int *pn_rev, int *pn_rev_max,
|
||||
ArtVpath *vpath, int i0, int i1, int i2,
|
||||
ArtPathStrokeJoinType join,
|
||||
double line_width, double miter_limit, double flatness)
|
||||
{
|
||||
double dx0, dy0;
|
||||
double dx1, dy1;
|
||||
double dlx0, dly0;
|
||||
double dlx1, dly1;
|
||||
double dmx, dmy;
|
||||
double dmr2;
|
||||
double scale;
|
||||
double cross;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("join style = %d\n", join);
|
||||
#endif
|
||||
|
||||
/* The vectors of the lines from i0 to i1 and i1 to i2. */
|
||||
dx0 = vpath[i1].x - vpath[i0].x;
|
||||
dy0 = vpath[i1].y - vpath[i0].y;
|
||||
|
||||
dx1 = vpath[i2].x - vpath[i1].x;
|
||||
dy1 = vpath[i2].y - vpath[i1].y;
|
||||
|
||||
/* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
|
||||
dlx0 = dy0 * scale;
|
||||
dly0 = -dx0 * scale;
|
||||
|
||||
/* Set dl[xy]1 to the vector from i1 to i2, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx1 * dx1 + dy1 * dy1);
|
||||
dlx1 = dy1 * scale;
|
||||
dly1 = -dx1 * scale;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: (%g, %g) - (%g, %g) - (%g, %g)\n",
|
||||
vpath[i0].x, vpath[i0].y,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
vpath[i2].x, vpath[i2].y);
|
||||
|
||||
printf ("%% render_seg: d[xy]0 = (%g, %g), dl[xy]0 = (%g, %g)\n",
|
||||
dx0, dy0, dlx0, dly0);
|
||||
|
||||
printf ("%% render_seg: d[xy]1 = (%g, %g), dl[xy]1 = (%g, %g)\n",
|
||||
dx1, dy1, dlx1, dly1);
|
||||
#endif
|
||||
|
||||
/* now, forw's last point is expected to be colinear along d[xy]0
|
||||
to point i0 - dl[xy]0, and rev with i0 + dl[xy]0. */
|
||||
|
||||
/* positive for positive area (i.e. left turn) */
|
||||
cross = dx1 * dy0 - dx0 * dy1;
|
||||
|
||||
dmx = (dlx0 + dlx1) * 0.5;
|
||||
dmy = (dly0 + dly1) * 0.5;
|
||||
dmr2 = dmx * dmx + dmy * dmy;
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_MITER &&
|
||||
dmr2 * miter_limit * miter_limit < line_width * line_width)
|
||||
join = ART_PATH_STROKE_JOIN_BEVEL;
|
||||
|
||||
/* the case when dmr2 is zero or very small bothers me
|
||||
(i.e. near a 180 degree angle) */
|
||||
scale = line_width * line_width / dmr2;
|
||||
dmx *= scale;
|
||||
dmy *= scale;
|
||||
|
||||
if (cross * cross < EPSILON_2 && dx0 * dx1 + dy0 * dy1 >= 0)
|
||||
{
|
||||
/* going straight */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: straight\n");
|
||||
#endif
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
}
|
||||
else if (cross > 0)
|
||||
{
|
||||
/* left turn, forw is outside and rev is inside */
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: left\n");
|
||||
#endif
|
||||
if (
|
||||
#ifdef NO_OPTIMIZE_INNER
|
||||
0 &&
|
||||
#endif
|
||||
/* check that i1 + dm[xy] is inside i0-i1 rectangle */
|
||||
(dx0 + dmx) * dx0 + (dy0 + dmy) * dy0 > 0 &&
|
||||
/* and that i1 + dm[xy] is inside i1-i2 rectangle */
|
||||
((dx1 - dmx) * dx1 + (dy1 - dmy) * dy1 > 0)
|
||||
#ifdef PEDANTIC_INNER
|
||||
&&
|
||||
/* check that i1 + dl[xy]1 is inside i0-i1 rectangle */
|
||||
(dx0 + dlx1) * dx0 + (dy0 + dly1) * dy0 > 0 &&
|
||||
/* and that i1 + dl[xy]0 is inside i1-i2 rectangle */
|
||||
((dx1 - dlx0) * dx1 + (dy1 - dly0) * dy1 > 0)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* can safely add single intersection point */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* need to loop-de-loop the inside */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x, vpath[i1].y);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
|
||||
}
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_BEVEL)
|
||||
{
|
||||
/* bevel */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_MITER)
|
||||
{
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_ROUND)
|
||||
art_svp_vpath_stroke_arc (p_forw, pn_forw, pn_forw_max,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
-dlx0, -dly0,
|
||||
-dlx1, -dly1,
|
||||
line_width,
|
||||
flatness);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* right turn, rev is outside and forw is inside */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: right\n");
|
||||
#endif
|
||||
|
||||
if (
|
||||
#ifdef NO_OPTIMIZE_INNER
|
||||
0 &&
|
||||
#endif
|
||||
/* check that i1 - dm[xy] is inside i0-i1 rectangle */
|
||||
(dx0 - dmx) * dx0 + (dy0 - dmy) * dy0 > 0 &&
|
||||
/* and that i1 - dm[xy] is inside i1-i2 rectangle */
|
||||
((dx1 + dmx) * dx1 + (dy1 + dmy) * dy1 > 0)
|
||||
#ifdef PEDANTIC_INNER
|
||||
&&
|
||||
/* check that i1 - dl[xy]1 is inside i0-i1 rectangle */
|
||||
(dx0 - dlx1) * dx0 + (dy0 - dly1) * dy0 > 0 &&
|
||||
/* and that i1 - dl[xy]0 is inside i1-i2 rectangle */
|
||||
((dx1 + dlx0) * dx1 + (dy1 + dly0) * dy1 > 0)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* can safely add single intersection point */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* need to loop-de-loop the inside */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x, vpath[i1].y);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
|
||||
}
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_BEVEL)
|
||||
{
|
||||
/* bevel */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_MITER)
|
||||
{
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_ROUND)
|
||||
art_svp_vpath_stroke_arc (p_rev, pn_rev, pn_rev_max,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
dlx0, dly0,
|
||||
dlx1, dly1,
|
||||
-line_width,
|
||||
flatness);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* caps i1, under the assumption of a vector from i0 */
|
||||
static void
|
||||
render_cap (ArtVpath **p_result, int *pn_result, int *pn_result_max,
|
||||
ArtVpath *vpath, int i0, int i1,
|
||||
ArtPathStrokeCapType cap, double line_width, double flatness)
|
||||
{
|
||||
double dx0, dy0;
|
||||
double dlx0, dly0;
|
||||
double scale;
|
||||
int n_pts;
|
||||
int i;
|
||||
|
||||
dx0 = vpath[i1].x - vpath[i0].x;
|
||||
dy0 = vpath[i1].y - vpath[i0].y;
|
||||
|
||||
/* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
|
||||
dlx0 = dy0 * scale;
|
||||
dly0 = -dx0 * scale;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("cap style = %d\n", cap);
|
||||
#endif
|
||||
|
||||
switch (cap)
|
||||
{
|
||||
case ART_PATH_STROKE_CAP_BUTT:
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
break;
|
||||
case ART_PATH_STROKE_CAP_ROUND:
|
||||
n_pts = ceil (M_PI / (2.0 * M_SQRT2 * sqrt (flatness / line_width)));
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
for (i = 1; i < n_pts; i++)
|
||||
{
|
||||
double theta, c_th, s_th;
|
||||
|
||||
theta = M_PI * i / n_pts;
|
||||
c_th = cos (theta);
|
||||
s_th = sin (theta);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x - dlx0 * c_th - dly0 * s_th,
|
||||
vpath[i1].y - dly0 * c_th + dlx0 * s_th);
|
||||
}
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
break;
|
||||
case ART_PATH_STROKE_CAP_SQUARE:
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x - dlx0 - dly0,
|
||||
vpath[i1].y - dly0 + dlx0);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x + dlx0 - dly0,
|
||||
vpath[i1].y + dly0 + dlx0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_from_vpath_raw: Stroke a vector path, raw version
|
||||
* @vpath: #ArtVPath to stroke.
|
||||
* @join: Join style.
|
||||
* @cap: Cap style.
|
||||
* @line_width: Width of stroke.
|
||||
* @miter_limit: Miter limit.
|
||||
* @flatness: Flatness.
|
||||
*
|
||||
* Exactly the same as art_svp_vpath_stroke(), except that the resulting
|
||||
* stroke outline may self-intersect and have regions of winding number
|
||||
* greater than 1.
|
||||
*
|
||||
* Return value: Resulting raw stroked outline in svp format.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_svp_vpath_stroke_raw (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness)
|
||||
{
|
||||
int begin_idx, end_idx;
|
||||
int i;
|
||||
ArtVpath *forw, *rev;
|
||||
int n_forw, n_rev;
|
||||
int n_forw_max, n_rev_max;
|
||||
ArtVpath *result;
|
||||
int n_result, n_result_max;
|
||||
double half_lw = 0.5 * line_width;
|
||||
int closed;
|
||||
int last, this, next, second;
|
||||
double dx, dy;
|
||||
|
||||
n_forw_max = 16;
|
||||
forw = art_new (ArtVpath, n_forw_max);
|
||||
|
||||
n_rev_max = 16;
|
||||
rev = art_new (ArtVpath, n_rev_max);
|
||||
|
||||
n_result = 0;
|
||||
n_result_max = 16;
|
||||
result = art_new (ArtVpath, n_result_max);
|
||||
|
||||
for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx)
|
||||
{
|
||||
n_forw = 0;
|
||||
n_rev = 0;
|
||||
|
||||
closed = (vpath[begin_idx].code == ART_MOVETO);
|
||||
|
||||
/* we don't know what the first point joins with until we get to the
|
||||
last point and see if it's closed. So we start with the second
|
||||
line in the path.
|
||||
|
||||
Note: this is not strictly true (we now know it's closed from
|
||||
the opening pathcode), but why fix code that isn't broken?
|
||||
*/
|
||||
|
||||
this = begin_idx;
|
||||
/* skip over identical points at the beginning of the subpath */
|
||||
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
|
||||
{
|
||||
dx = vpath[i].x - vpath[this].x;
|
||||
dy = vpath[i].y - vpath[this].y;
|
||||
if (dx * dx + dy * dy > EPSILON_2)
|
||||
break;
|
||||
}
|
||||
next = i;
|
||||
second = next;
|
||||
|
||||
/* invariant: this doesn't coincide with next */
|
||||
while (vpath[next].code == ART_LINETO)
|
||||
{
|
||||
last = this;
|
||||
this = next;
|
||||
/* skip over identical points after the beginning of the subpath */
|
||||
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
|
||||
{
|
||||
dx = vpath[i].x - vpath[this].x;
|
||||
dy = vpath[i].y - vpath[this].y;
|
||||
if (dx * dx + dy * dy > EPSILON_2)
|
||||
break;
|
||||
}
|
||||
next = i;
|
||||
if (vpath[next].code != ART_LINETO)
|
||||
{
|
||||
/* reached end of path */
|
||||
/* make "closed" detection conform to PostScript
|
||||
semantics (i.e. explicit closepath code rather than
|
||||
just the fact that end of the path is the beginning) */
|
||||
if (closed &&
|
||||
vpath[this].x == vpath[begin_idx].x &&
|
||||
vpath[this].y == vpath[begin_idx].y)
|
||||
{
|
||||
int j;
|
||||
|
||||
/* path is closed, render join to beginning */
|
||||
render_seg (&forw, &n_forw, &n_forw_max,
|
||||
&rev, &n_rev, &n_rev_max,
|
||||
vpath, last, this, second,
|
||||
join, half_lw, miter_limit, flatness);
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% forw %d, rev %d\n", n_forw, n_rev);
|
||||
#endif
|
||||
/* do forward path */
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, forw[n_forw - 1].x,
|
||||
forw[n_forw - 1].y);
|
||||
for (j = 0; j < n_forw; j++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[j].x,
|
||||
forw[j].y);
|
||||
|
||||
/* do reverse path, reversed */
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, rev[0].x,
|
||||
rev[0].y);
|
||||
for (j = n_rev - 1; j >= 0; j--)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, rev[j].x,
|
||||
rev[j].y);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* path is open */
|
||||
int j;
|
||||
|
||||
/* add to forw rather than result to ensure that
|
||||
forw has at least one point. */
|
||||
render_cap (&forw, &n_forw, &n_forw_max,
|
||||
vpath, last, this,
|
||||
cap, half_lw, flatness);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, forw[0].x,
|
||||
forw[0].y);
|
||||
for (j = 1; j < n_forw; j++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[j].x,
|
||||
forw[j].y);
|
||||
for (j = n_rev - 1; j >= 0; j--)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, rev[j].x,
|
||||
rev[j].y);
|
||||
render_cap (&result, &n_result, &n_result_max,
|
||||
vpath, second, begin_idx,
|
||||
cap, half_lw, flatness);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[0].x,
|
||||
forw[0].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
render_seg (&forw, &n_forw, &n_forw_max,
|
||||
&rev, &n_rev, &n_rev_max,
|
||||
vpath, last, this, next,
|
||||
join, half_lw, miter_limit, flatness);
|
||||
}
|
||||
end_idx = next;
|
||||
}
|
||||
|
||||
art_free (forw);
|
||||
art_free (rev);
|
||||
#ifdef VERBOSE
|
||||
printf ("%% n_result = %d\n", n_result);
|
||||
#endif
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max, ART_END, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define noVERBOSE
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
||||
#define XOFF 50
|
||||
#define YOFF 700
|
||||
|
||||
static void
|
||||
print_ps_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vpath[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
case ART_LINETO:
|
||||
printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ("stroke showpage\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_ps_svp (ArtSVP *vpath)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
printf ("%% begin\n");
|
||||
for (i = 0; i < vpath->n_segs; i++)
|
||||
{
|
||||
printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
|
||||
for (j = 0; j < vpath->segs[i].n_points; j++)
|
||||
{
|
||||
printf ("%g %g %s\n",
|
||||
XOFF + vpath->segs[i].points[j].x,
|
||||
YOFF - vpath->segs[i].points[j].y,
|
||||
j ? "lineto" : "moveto");
|
||||
}
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
printf ("showpage\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Render a vector path into a stroked outline.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Only miter and bevel line joins are implemented,
|
||||
and only butt line caps. Otherwise, seems to be fine.
|
||||
|
||||
Numerical stability: We cheat (adding random perturbation). Thus,
|
||||
it seems very likely that no numerical stability problems will be
|
||||
seen in practice.
|
||||
|
||||
Speed: Should be pretty good.
|
||||
|
||||
Precision: The perturbation fuzzes the coordinates slightly,
|
||||
but not enough to be visible. */
|
||||
/**
|
||||
* art_svp_vpath_stroke: Stroke a vector path.
|
||||
* @vpath: #ArtVPath to stroke.
|
||||
* @join: Join style.
|
||||
* @cap: Cap style.
|
||||
* @line_width: Width of stroke.
|
||||
* @miter_limit: Miter limit.
|
||||
* @flatness: Flatness.
|
||||
*
|
||||
* Computes an svp representing the stroked outline of @vpath. The
|
||||
* width of the stroked line is @line_width.
|
||||
*
|
||||
* Lines are joined according to the @join rule. Possible values are
|
||||
* ART_PATH_STROKE_JOIN_MITER (for mitered joins),
|
||||
* ART_PATH_STROKE_JOIN_ROUND (for round joins), and
|
||||
* ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join
|
||||
* is converted to a bevelled join if the miter would extend to a
|
||||
* distance of more than @miter_limit * @line_width from the actual
|
||||
* join point.
|
||||
*
|
||||
* If there are open subpaths, the ends of these subpaths are capped
|
||||
* according to the @cap rule. Possible values are
|
||||
* ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end
|
||||
* point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at
|
||||
* the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap,
|
||||
* extending half @line_width past the end point).
|
||||
*
|
||||
* The @flatness parameter controls the accuracy of the rendering. It
|
||||
* is most important for determining the number of points to use to
|
||||
* approximate circular arcs for round lines and joins. In general, the
|
||||
* resulting vector path will be within @flatness pixels of the "ideal"
|
||||
* path containing actual circular arcs. I reserve the right to use
|
||||
* the @flatness parameter to convert bevelled joins to miters for very
|
||||
* small turn angles, as this would reduce the number of points in the
|
||||
* resulting outline path.
|
||||
*
|
||||
* The resulting path is "clean" with respect to self-intersections, i.e.
|
||||
* the winding number is 0 or 1 at each point.
|
||||
*
|
||||
* Return value: Resulting stroked outline in svp format.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_vpath_stroke (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness)
|
||||
{
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
ArtVpath *vpath_stroke;
|
||||
ArtSVP *svp, *svp2;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
|
||||
line_width, miter_limit, flatness);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath_stroke);
|
||||
#endif
|
||||
svp = art_svp_from_vpath (vpath_stroke);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp);
|
||||
#endif
|
||||
art_free (vpath_stroke);
|
||||
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
|
||||
art_svp_intersector (svp, swr);
|
||||
|
||||
svp2 = art_svp_writer_rewind_reap (swr);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp2);
|
||||
#endif
|
||||
art_svp_free (svp);
|
||||
return svp2;
|
||||
#else
|
||||
ArtVpath *vpath_stroke, *vpath2;
|
||||
ArtSVP *svp, *svp2, *svp3;
|
||||
|
||||
vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
|
||||
line_width, miter_limit, flatness);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath_stroke);
|
||||
#endif
|
||||
vpath2 = art_vpath_perturb (vpath_stroke);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath2);
|
||||
#endif
|
||||
art_free (vpath_stroke);
|
||||
svp = art_svp_from_vpath (vpath2);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp);
|
||||
#endif
|
||||
art_free (vpath2);
|
||||
svp2 = art_svp_uncross (svp);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp2);
|
||||
#endif
|
||||
art_svp_free (svp);
|
||||
svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_NONZERO);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp3);
|
||||
#endif
|
||||
art_svp_free (svp2);
|
||||
|
||||
return svp3;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_VPATH_STROKE_H__
|
||||
#define __ART_SVP_VPATH_STROKE_H__
|
||||
|
||||
/* Sort vector paths into sorted vector paths. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_PATH_STROKE_JOIN_MITER,
|
||||
ART_PATH_STROKE_JOIN_ROUND,
|
||||
ART_PATH_STROKE_JOIN_BEVEL
|
||||
} ArtPathStrokeJoinType;
|
||||
|
||||
typedef enum {
|
||||
ART_PATH_STROKE_CAP_BUTT,
|
||||
ART_PATH_STROKE_CAP_ROUND,
|
||||
ART_PATH_STROKE_CAP_SQUARE
|
||||
} ArtPathStrokeCapType;
|
||||
|
||||
ArtSVP *
|
||||
art_svp_vpath_stroke (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness);
|
||||
|
||||
/* This version may have winding numbers exceeding 1. */
|
||||
ArtVpath *
|
||||
art_svp_vpath_stroke_raw (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_VPATH_STROKE_H__ */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,51 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_SVP_WIND_H__
|
||||
#define __ART_SVP_WIND_H__
|
||||
|
||||
/* Primitive intersection and winding number operations on sorted
|
||||
vector paths. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef ART_WIND_RULE_DEFINED
|
||||
#define ART_WIND_RULE_DEFINED
|
||||
typedef enum {
|
||||
ART_WIND_RULE_NONZERO,
|
||||
ART_WIND_RULE_INTERSECT,
|
||||
ART_WIND_RULE_ODDEVEN,
|
||||
ART_WIND_RULE_POSITIVE
|
||||
} ArtWindRule;
|
||||
#endif
|
||||
|
||||
ArtSVP *
|
||||
art_svp_uncross (ArtSVP *vp);
|
||||
|
||||
ArtSVP *
|
||||
art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_WIND_H__ */
|
|
@ -0,0 +1,86 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
|
||||
/**
|
||||
* art_uta_new: Allocate a new uta.
|
||||
* @x0: Left coordinate of uta.
|
||||
* @y0: Top coordinate of uta.
|
||||
* @x1: Right coordinate of uta.
|
||||
* @y1: Bottom coordinate of uta.
|
||||
*
|
||||
* Allocates a new microtile array. The arguments are in units of
|
||||
* tiles, not pixels.
|
||||
*
|
||||
* Returns: the newly allocated #ArtUta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_new (int x0, int y0, int x1, int y1)
|
||||
{
|
||||
ArtUta *uta;
|
||||
|
||||
uta = art_new (ArtUta, 1);
|
||||
uta->x0 = x0;
|
||||
uta->y0 = y0;
|
||||
uta->width = x1 - x0;
|
||||
uta->height = y1 - y0;
|
||||
|
||||
uta->utiles = art_new (ArtUtaBbox, uta->width * uta->height);
|
||||
|
||||
memset (uta->utiles, 0, uta->width * uta->height * sizeof(ArtUtaBbox));
|
||||
return uta;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_new_coords: Allocate a new uta, based on pixel coordinates.
|
||||
* @x0: Left coordinate of uta.
|
||||
* @y0: Top coordinate of uta.
|
||||
* @x1: Right coordinate of uta.
|
||||
* @y1: Bottom coordinate of uta.
|
||||
*
|
||||
* Allocates a new microtile array. The arguments are in pixels
|
||||
*
|
||||
* Returns: the newly allocated #ArtUta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_new_coords (int x0, int y0, int x1, int y1)
|
||||
{
|
||||
return art_uta_new (x0 >> ART_UTILE_SHIFT, y0 >> ART_UTILE_SHIFT,
|
||||
1 + (x1 >> ART_UTILE_SHIFT),
|
||||
1 + (y1 >> ART_UTILE_SHIFT));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_free: Free a uta.
|
||||
* @uta: The uta to free.
|
||||
*
|
||||
* Frees the microtile array structure, including the actual microtile
|
||||
* data.
|
||||
**/
|
||||
void
|
||||
art_uta_free (ArtUta *uta)
|
||||
{
|
||||
art_free (uta->utiles);
|
||||
art_free (uta);
|
||||
}
|
||||
|
||||
/* User to Aardvark! */
|
|
@ -0,0 +1,66 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_UTA_H__
|
||||
#define __ART_UTA_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef art_u32 ArtUtaBbox;
|
||||
typedef struct _ArtUta ArtUta;
|
||||
|
||||
#define ART_UTA_BBOX_CONS(x0, y0, x1, y1) (((x0) << 24) | ((y0) << 16) | \
|
||||
((x1) << 8) | (y1))
|
||||
|
||||
#define ART_UTA_BBOX_X0(ub) ((ub) >> 24)
|
||||
#define ART_UTA_BBOX_Y0(ub) (((ub) >> 16) & 0xff)
|
||||
#define ART_UTA_BBOX_X1(ub) (((ub) >> 8) & 0xff)
|
||||
#define ART_UTA_BBOX_Y1(ub) ((ub) & 0xff)
|
||||
|
||||
#define ART_UTILE_SHIFT 5
|
||||
#define ART_UTILE_SIZE (1 << ART_UTILE_SHIFT)
|
||||
|
||||
/* Coordinates are shifted right by ART_UTILE_SHIFT wrt the real
|
||||
coordinates. */
|
||||
struct _ArtUta {
|
||||
int x0;
|
||||
int y0;
|
||||
int width;
|
||||
int height;
|
||||
ArtUtaBbox *utiles;
|
||||
};
|
||||
|
||||
ArtUta *
|
||||
art_uta_new (int x0, int y0, int x1, int y1);
|
||||
|
||||
ArtUta *
|
||||
art_uta_new_coords (int x0, int y0, int x1, int y1);
|
||||
|
||||
void
|
||||
art_uta_free (ArtUta *uta);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_H__ */
|
|
@ -0,0 +1,110 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_uta_ops.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_uta_union: Compute union of two uta's.
|
||||
* @uta1: One uta.
|
||||
* @uta2: The other uta.
|
||||
*
|
||||
* Computes the union of @uta1 and @uta2. The union is approximate,
|
||||
* but coverage is guaranteed over all pixels included in either of
|
||||
* the arguments, ie more pixels may be covered than the "exact"
|
||||
* union.
|
||||
*
|
||||
* Note: this routine is used in the Gnome Canvas to accumulate the
|
||||
* region that needs to be repainted. However, since it copies over
|
||||
* the entire uta (which might be largish) even when the update may be
|
||||
* small, it can be a performance bottleneck. There are two approaches
|
||||
* to this problem, both of which are probably worthwhile. First, the
|
||||
* generated uta's should always be limited to the visible window,
|
||||
* thus guaranteeing that uta's never become large. Second, there
|
||||
* should be a new, destructive union operation that only touches a
|
||||
* small part of the uta when the update is small.
|
||||
*
|
||||
* Return value: The new union uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_union (ArtUta *uta1, ArtUta *uta2)
|
||||
{
|
||||
ArtUta *uta;
|
||||
int x0, y0, x1, y1;
|
||||
int x, y;
|
||||
int ix, ix1, ix2;
|
||||
ArtUtaBbox bb, bb1, bb2;
|
||||
|
||||
x0 = MIN(uta1->x0, uta2->x0);
|
||||
y0 = MIN(uta1->y0, uta2->y0);
|
||||
x1 = MAX(uta1->x0 + uta1->width, uta2->x0 + uta2->width);
|
||||
y1 = MAX(uta1->y0 + uta1->height, uta2->y0 + uta2->height);
|
||||
uta = art_uta_new (x0, y0, x1, y1);
|
||||
|
||||
/* could move the first two if/else statements out of the loop */
|
||||
ix = 0;
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
ix1 = (y - uta1->y0) * uta1->width + x0 - uta1->x0;
|
||||
ix2 = (y - uta2->y0) * uta2->width + x0 - uta2->x0;
|
||||
for (x = x0; x < x1; x++)
|
||||
{
|
||||
if (x < uta1->x0 || y < uta1->y0 ||
|
||||
x >= uta1->x0 + uta1->width || y >= uta1->y0 + uta1->height)
|
||||
bb1 = 0;
|
||||
else
|
||||
bb1 = uta1->utiles[ix1];
|
||||
|
||||
if (x < uta2->x0 || y < uta2->y0 ||
|
||||
x >= uta2->x0 + uta2->width || y >= uta2->y0 + uta2->height)
|
||||
bb2 = 0;
|
||||
else
|
||||
bb2 = uta2->utiles[ix2];
|
||||
|
||||
if (bb1 == 0)
|
||||
bb = bb2;
|
||||
else if (bb2 == 0)
|
||||
bb = bb1;
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb1),
|
||||
ART_UTA_BBOX_X0(bb2)),
|
||||
MIN(ART_UTA_BBOX_Y0(bb1),
|
||||
ART_UTA_BBOX_Y0(bb2)),
|
||||
MAX(ART_UTA_BBOX_X1(bb1),
|
||||
ART_UTA_BBOX_X1(bb2)),
|
||||
MAX(ART_UTA_BBOX_Y1(bb1),
|
||||
ART_UTA_BBOX_Y1(bb2)));
|
||||
uta->utiles[ix] = bb;
|
||||
ix++;
|
||||
ix1++;
|
||||
ix2++;
|
||||
}
|
||||
}
|
||||
return uta;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_UTA_OPS_H__
|
||||
#define __ART_UTA_OPS_H__
|
||||
|
||||
/* Basic operations on microtile arrays */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_union (ArtUta *uta1, ArtUta *uta2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_OPS_H__ */
|
|
@ -0,0 +1,109 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_rect.h"
|
||||
#include "art_uta_rect.h"
|
||||
|
||||
/**
|
||||
* art_uta_from_irect: Generate uta covering a rectangle.
|
||||
* @bbox: The source rectangle.
|
||||
*
|
||||
* Generates a uta exactly covering @bbox. Please do not call this
|
||||
* function with a @bbox with zero height or width.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_irect (ArtIRect *bbox)
|
||||
{
|
||||
ArtUta *uta;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int width, height;
|
||||
int x, y;
|
||||
int xf0, yf0, xf1, yf1;
|
||||
int ix;
|
||||
|
||||
uta = art_new (ArtUta, 1);
|
||||
uta->x0 = bbox->x0 >> ART_UTILE_SHIFT;
|
||||
uta->y0 = bbox->y0 >> ART_UTILE_SHIFT;
|
||||
width = ((bbox->x1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->x0;
|
||||
height = ((bbox->y1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->y0;
|
||||
utiles = art_new (ArtUtaBbox, width * height);
|
||||
|
||||
uta->width = width;
|
||||
uta->height = height;
|
||||
uta->utiles = utiles;
|
||||
|
||||
xf0 = bbox->x0 & (ART_UTILE_SIZE - 1);
|
||||
yf0 = bbox->y0 & (ART_UTILE_SIZE - 1);
|
||||
xf1 = ((bbox->x1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
|
||||
yf1 = ((bbox->y1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
|
||||
if (height == 1)
|
||||
{
|
||||
if (width == 1)
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, yf1);
|
||||
else
|
||||
{
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, yf1);
|
||||
bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, yf1);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[x] = bb;
|
||||
utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, yf1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (xf0, 0, xf1, ART_UTILE_SIZE);
|
||||
for (y = 1; y < height - 1; y++)
|
||||
utiles[y] = bb;
|
||||
utiles[y] = ART_UTA_BBOX_CONS (xf0, 0, xf1, yf1);
|
||||
}
|
||||
else
|
||||
{
|
||||
utiles[0] =
|
||||
ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[x] = bb;
|
||||
utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, ART_UTILE_SIZE);
|
||||
ix = width;
|
||||
for (y = 1; y < height - 1; y++)
|
||||
{
|
||||
utiles[ix++] =
|
||||
ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[ix++] = bb;
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, ART_UTILE_SIZE);
|
||||
}
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, yf1);
|
||||
bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, yf1);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[ix++] = bb;
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, yf1);
|
||||
}
|
||||
}
|
||||
return uta;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_UTA_RECT_H__
|
||||
#define __ART_UTA_RECT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_irect (ArtIRect *bbox);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_RECT_H__ */
|
|
@ -0,0 +1,52 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* LGPL Copyright 1998 Raph Levien <raph@acm.org> */
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_uta_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_uta_svp.h"
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
/**
|
||||
* art_uta_from_svp: Generate uta covering an svp.
|
||||
* @svp: The source svp.
|
||||
*
|
||||
* Generates a uta covering @svp. The resulting uta is of course
|
||||
* approximate, ie it may cover more pixels than covered by @svp.
|
||||
*
|
||||
* Note: I will want to replace this with a more direct
|
||||
* implementation. But this gets the api in place.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_svp (const ArtSVP *svp)
|
||||
{
|
||||
ArtVpath *vpath;
|
||||
ArtUta *uta;
|
||||
|
||||
vpath = art_vpath_from_svp (svp);
|
||||
uta = art_uta_from_vpath (vpath);
|
||||
art_free (vpath);
|
||||
return uta;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_UTA_SVP_H__
|
||||
#define __ART_UTA_SVP_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_svp (const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_SVP_H__ */
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* LGPL Copyright 1998 Raph Levien <raph@acm.org> */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_uta_vpath.h"
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif /* MAX */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
/**
|
||||
* art_uta_add_line: Add a line to the uta.
|
||||
* @uta: The uta to modify.
|
||||
* @x0: X coordinate of line start point.
|
||||
* @y0: Y coordinate of line start point.
|
||||
* @x1: X coordinate of line end point.
|
||||
* @y1: Y coordinate of line end point.
|
||||
* @rbuf: Buffer containing first difference of winding number.
|
||||
* @rbuf_rowstride: Rowstride of @rbuf.
|
||||
*
|
||||
* Add the line (@x0, @y0) - (@x1, @y1) to @uta, and also update the
|
||||
* winding number buffer used for rendering the interior. @rbuf
|
||||
* contains the first partial difference (in the X direction) of the
|
||||
* winding number, measured in grid cells. Thus, each time that a line
|
||||
* crosses a horizontal uta grid line, an entry of @rbuf is
|
||||
* incremented if @y1 > @y0, decremented otherwise.
|
||||
*
|
||||
* Note that edge handling is fairly delicate. Please rtfs for
|
||||
* details.
|
||||
**/
|
||||
void
|
||||
art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
|
||||
int *rbuf, int rbuf_rowstride)
|
||||
{
|
||||
int xmin, ymin;
|
||||
double xmax, ymax;
|
||||
int xmaxf, ymaxf;
|
||||
int xmaxc, ymaxc;
|
||||
int xt0, yt0;
|
||||
int xt1, yt1;
|
||||
int xf0, yf0;
|
||||
int xf1, yf1;
|
||||
int ix, ix1;
|
||||
ArtUtaBbox bb;
|
||||
|
||||
xmin = floor (MIN(x0, x1));
|
||||
xmax = MAX(x0, x1);
|
||||
xmaxf = floor (xmax);
|
||||
xmaxc = ceil (xmax);
|
||||
ymin = floor (MIN(y0, y1));
|
||||
ymax = MAX(y0, y1);
|
||||
ymaxf = floor (ymax);
|
||||
ymaxc = ceil (ymax);
|
||||
xt0 = (xmin >> ART_UTILE_SHIFT) - uta->x0;
|
||||
yt0 = (ymin >> ART_UTILE_SHIFT) - uta->y0;
|
||||
xt1 = (xmaxf >> ART_UTILE_SHIFT) - uta->x0;
|
||||
yt1 = (ymaxf >> ART_UTILE_SHIFT) - uta->y0;
|
||||
if (xt0 == xt1 && yt0 == yt1)
|
||||
{
|
||||
/* entirely inside a microtile, this is easy! */
|
||||
xf0 = xmin & (ART_UTILE_SIZE - 1);
|
||||
yf0 = ymin & (ART_UTILE_SIZE - 1);
|
||||
xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx, dy;
|
||||
int sx, sy;
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
sx = dx > 0 ? 1 : dx < 0 ? -1 : 0;
|
||||
sy = dy > 0 ? 1 : dy < 0 ? -1 : 0;
|
||||
if (ymin == ymaxf)
|
||||
{
|
||||
/* special case horizontal (dx/dy slope would be infinite) */
|
||||
xf0 = xmin & (ART_UTILE_SIZE - 1);
|
||||
yf0 = ymin & (ART_UTILE_SIZE - 1);
|
||||
xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
ix1 = yt0 * uta->width + xt1;
|
||||
while (ix != ix1)
|
||||
{
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, ART_UTILE_SIZE, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
ART_UTILE_SIZE,
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
xf0 = 0;
|
||||
ix++;
|
||||
}
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(0,
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do a Bresenham-style traversal of the line */
|
||||
double dx_dy;
|
||||
double x, y;
|
||||
double xn, yn;
|
||||
|
||||
/* normalize coordinates to uta origin */
|
||||
x0 -= uta->x0 << ART_UTILE_SHIFT;
|
||||
y0 -= uta->y0 << ART_UTILE_SHIFT;
|
||||
x1 -= uta->x0 << ART_UTILE_SHIFT;
|
||||
y1 -= uta->y0 << ART_UTILE_SHIFT;
|
||||
if (dy < 0)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
tmp = x0;
|
||||
x0 = x1;
|
||||
x1 = tmp;
|
||||
|
||||
tmp = y0;
|
||||
y0 = y1;
|
||||
y1 = tmp;
|
||||
|
||||
dx = -dx;
|
||||
sx = -sx;
|
||||
dy = -dy;
|
||||
/* we leave sy alone, because it would always be 1,
|
||||
and we need it for the rbuf stuff. */
|
||||
}
|
||||
xt0 = ((int)floor (x0) >> ART_UTILE_SHIFT);
|
||||
xt1 = ((int)floor (x1) >> ART_UTILE_SHIFT);
|
||||
/* now [xy]0 is above [xy]1 */
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
ix1 = yt1 * uta->width + xt1;
|
||||
#ifdef VERBOSE
|
||||
printf ("%% ix = %d,%d; ix1 = %d,%d\n", xt0, yt0, xt1, yt1);
|
||||
#endif
|
||||
|
||||
dx_dy = dx / dy;
|
||||
x = x0;
|
||||
y = y0;
|
||||
while (ix != ix1)
|
||||
{
|
||||
int dix;
|
||||
|
||||
/* figure out whether next crossing is horizontal or vertical */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% %d,%d\n", xt0, yt0);
|
||||
#endif
|
||||
yn = (yt0 + 1) << ART_UTILE_SHIFT;
|
||||
xn = x0 + dx_dy * (yn - y0);
|
||||
if (xt0 != (int)floor (xn) >> ART_UTILE_SHIFT)
|
||||
{
|
||||
/* horizontal crossing */
|
||||
xt0 += sx;
|
||||
dix = sx;
|
||||
if (dx > 0)
|
||||
{
|
||||
xn = xt0 << ART_UTILE_SHIFT;
|
||||
yn = y0 + (xn - x0) / dx_dy;
|
||||
|
||||
xf0 = (int)floor (x) & (ART_UTILE_SIZE - 1);
|
||||
xf1 = ART_UTILE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xn = (xt0 + 1) << ART_UTILE_SHIFT;
|
||||
yn = y0 + (xn - x0) / dx_dy;
|
||||
|
||||
xf0 = 0;
|
||||
xmaxc = (int)ceil (x);
|
||||
xf1 = xmaxc - ((xt0 + 1) << ART_UTILE_SHIFT);
|
||||
}
|
||||
ymaxf = (int)floor (yn);
|
||||
ymaxc = (int)ceil (yn);
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* vertical crossing */
|
||||
dix = uta->width;
|
||||
xf0 = (int)floor (MIN(x, xn)) & (ART_UTILE_SIZE - 1);
|
||||
xmax = MAX(x, xn);
|
||||
xmaxc = (int)ceil (xmax);
|
||||
xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
|
||||
yf1 = ART_UTILE_SIZE;
|
||||
|
||||
if (rbuf != NULL)
|
||||
rbuf[yt0 * rbuf_rowstride + xt0] += sy;
|
||||
|
||||
yt0++;
|
||||
}
|
||||
yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
|
||||
x = xn;
|
||||
y = yn;
|
||||
ix += dix;
|
||||
}
|
||||
xmax = MAX(x, x1);
|
||||
xmaxc = ceil (xmax);
|
||||
ymaxc = ceil (y1);
|
||||
xf0 = (int)floor (MIN(x1, x)) & (ART_UTILE_SIZE - 1);
|
||||
yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
|
||||
xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
|
||||
yf1 = ymaxc - (yt0 << ART_UTILE_SHIFT);
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_from_vpath: Generate uta covering a vpath.
|
||||
* @vec: The source vpath.
|
||||
*
|
||||
* Generates a uta covering @vec. The resulting uta is of course
|
||||
* approximate, ie it may cover more pixels than covered by @vec.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_vpath (const ArtVpath *vec)
|
||||
{
|
||||
ArtUta *uta;
|
||||
ArtIRect bbox;
|
||||
int *rbuf;
|
||||
int i;
|
||||
double x, y;
|
||||
int sum;
|
||||
int xt, yt;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int width;
|
||||
int height;
|
||||
int ix;
|
||||
|
||||
art_vpath_bbox_irect (vec, &bbox);
|
||||
|
||||
uta = art_uta_new_coords (bbox.x0, bbox.y0, bbox.x1, bbox.y1);
|
||||
|
||||
width = uta->width;
|
||||
height = uta->height;
|
||||
utiles = uta->utiles;
|
||||
|
||||
rbuf = art_new (int, width * height);
|
||||
for (i = 0; i < width * height; i++)
|
||||
rbuf[i] = 0;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (i = 0; vec[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vec[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
x = vec[i].x;
|
||||
y = vec[i].y;
|
||||
break;
|
||||
case ART_LINETO:
|
||||
art_uta_add_line (uta, vec[i].x, vec[i].y, x, y, rbuf, width);
|
||||
x = vec[i].x;
|
||||
y = vec[i].y;
|
||||
break;
|
||||
default:
|
||||
/* this shouldn't happen */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* now add in the filling from rbuf */
|
||||
ix = 0;
|
||||
for (yt = 0; yt < height; yt++)
|
||||
{
|
||||
sum = 0;
|
||||
for (xt = 0; xt < width; xt++)
|
||||
{
|
||||
sum += rbuf[ix];
|
||||
/* Nonzero winding rule - others are possible, but hardly
|
||||
worth it. */
|
||||
if (sum != 0)
|
||||
{
|
||||
bb = utiles[ix];
|
||||
bb &= 0xffff0000;
|
||||
bb |= (ART_UTILE_SIZE << 8) | ART_UTILE_SIZE;
|
||||
utiles[ix] = bb;
|
||||
if (xt != width - 1)
|
||||
{
|
||||
bb = utiles[ix + 1];
|
||||
bb &= 0xffff00;
|
||||
bb |= ART_UTILE_SIZE;
|
||||
utiles[ix + 1] = bb;
|
||||
}
|
||||
if (yt != height - 1)
|
||||
{
|
||||
bb = utiles[ix + width];
|
||||
bb &= 0xff0000ff;
|
||||
bb |= ART_UTILE_SIZE << 8;
|
||||
utiles[ix + width] = bb;
|
||||
if (xt != width - 1)
|
||||
{
|
||||
utiles[ix + width + 1] &= 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
|
||||
art_free (rbuf);
|
||||
|
||||
return uta;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_UTA_VPATH_H__
|
||||
#define __ART_UTA_VPATH_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_vpath (const ArtVpath *vec);
|
||||
|
||||
/* This is a private function: */
|
||||
void
|
||||
art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
|
||||
int *rbuf, int rbuf_rowstride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_VPATH_H__ */
|
||||
|
|
@ -0,0 +1,239 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for vector paths */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_rect.h"
|
||||
#include "art_vpath.h"
|
||||
|
||||
/**
|
||||
* art_vpath_add_point: Add point to vpath.
|
||||
* @p_vpath: Where the pointer to the #ArtVpath structure is stored.
|
||||
* @pn_points: Pointer to the number of points in *@p_vpath.
|
||||
* @pn_points_max: Pointer to the number of points allocated.
|
||||
* @code: The pathcode for the new point.
|
||||
* @x: The X coordinate of the new point.
|
||||
* @y: The Y coordinate of the new point.
|
||||
*
|
||||
* Adds a new point to *@p_vpath, reallocating and updating *@p_vpath
|
||||
* and *@pn_points_max as necessary. *@pn_points is incremented.
|
||||
*
|
||||
* This routine always adds the point after all points already in the
|
||||
* vpath. Thus, it should be called in the order the points are
|
||||
* desired.
|
||||
**/
|
||||
void
|
||||
art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
|
||||
ArtPathcode code, double x, double y)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (*pn_points)++;
|
||||
if (i == *pn_points_max)
|
||||
art_expand (*p_vpath, ArtVpath, *pn_points_max);
|
||||
(*p_vpath)[i].code = code;
|
||||
(*p_vpath)[i].x = x;
|
||||
(*p_vpath)[i].y = y;
|
||||
}
|
||||
|
||||
/* number of steps should really depend on radius. */
|
||||
#define CIRCLE_STEPS 128
|
||||
|
||||
/**
|
||||
* art_vpath_new_circle: Create a new circle.
|
||||
* @x: X coordinate of center.
|
||||
* @y: Y coordinate of center.
|
||||
* @r: radius.
|
||||
*
|
||||
* Creates a new polygon closely approximating a circle with center
|
||||
* (@x, @y) and radius @r. Currently, the number of points used in the
|
||||
* approximation is fixed, but that will probably change.
|
||||
*
|
||||
* Return value: The newly created #ArtVpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_new_circle (double x, double y, double r)
|
||||
{
|
||||
int i;
|
||||
ArtVpath *vec;
|
||||
double theta;
|
||||
|
||||
vec = art_new (ArtVpath, CIRCLE_STEPS + 2);
|
||||
|
||||
for (i = 0; i < CIRCLE_STEPS + 1; i++)
|
||||
{
|
||||
vec[i].code = i ? ART_LINETO : ART_MOVETO;
|
||||
theta = (i & (CIRCLE_STEPS - 1)) * (M_PI * 2.0 / CIRCLE_STEPS);
|
||||
vec[i].x = x + r * cos (theta);
|
||||
vec[i].y = y - r * sin (theta);
|
||||
}
|
||||
vec[i].code = ART_END;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_affine_transform: Affine transform a vpath.
|
||||
* @src: Source vpath to transform.
|
||||
* @matrix: Affine transform.
|
||||
*
|
||||
* Computes the affine transform of the vpath, using @matrix as the
|
||||
* transform. @matrix is stored in the same format as PostScript, ie.
|
||||
* x' = @matrix[0] * x + @matrix[2] * y + @matrix[4]
|
||||
* y' = @matrix[1] * x + @matrix[3] * y + @matrix[5]
|
||||
*
|
||||
* Return value: the newly allocated vpath resulting from the transform.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_affine_transform (const ArtVpath *src, const double matrix[6])
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ArtVpath *new;
|
||||
double x, y;
|
||||
|
||||
for (i = 0; src[i].code != ART_END; i++);
|
||||
size = i;
|
||||
|
||||
new = art_new (ArtVpath, size + 1);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
new[i].code = src[i].code;
|
||||
x = src[i].x;
|
||||
y = src[i].y;
|
||||
new[i].x = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
new[i].code = ART_END;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_bbox_drect: Determine bounding box of vpath.
|
||||
* @vec: Source vpath.
|
||||
* @drect: Where to store bounding box.
|
||||
*
|
||||
* Determines bounding box of @vec, and stores it in @drect.
|
||||
**/
|
||||
void
|
||||
art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect)
|
||||
{
|
||||
int i;
|
||||
double x0, y0, x1, y1;
|
||||
|
||||
if (vec[0].code == ART_END)
|
||||
{
|
||||
x0 = y0 = x1 = y1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = x1 = vec[0].x;
|
||||
y0 = y1 = vec[0].y;
|
||||
for (i = 1; vec[i].code != ART_END; i++)
|
||||
{
|
||||
if (vec[i].x < x0) x0 = vec[i].x;
|
||||
if (vec[i].x > x1) x1 = vec[i].x;
|
||||
if (vec[i].y < y0) y0 = vec[i].y;
|
||||
if (vec[i].y > y1) y1 = vec[i].y;
|
||||
}
|
||||
}
|
||||
drect->x0 = x0;
|
||||
drect->y0 = y0;
|
||||
drect->x1 = x1;
|
||||
drect->y1 = y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_bbox_irect: Determine integer bounding box of vpath.
|
||||
* @vec: Source vpath.
|
||||
* idrect: Where to store bounding box.
|
||||
*
|
||||
* Determines integer bounding box of @vec, and stores it in @irect.
|
||||
**/
|
||||
void
|
||||
art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect)
|
||||
{
|
||||
ArtDRect drect;
|
||||
|
||||
art_vpath_bbox_drect (vec, &drect);
|
||||
art_drect_to_irect (irect, &drect);
|
||||
}
|
||||
|
||||
#define PERTURBATION 2e-3
|
||||
|
||||
/**
|
||||
* art_vpath_perturb: Perturb each point in vpath by small random amount.
|
||||
* @src: Source vpath.
|
||||
*
|
||||
* Perturbs each of the points by a small random amount. This is
|
||||
* helpful for cheating in cases when algorithms haven't attained
|
||||
* numerical stability yet.
|
||||
*
|
||||
* Return value: Newly allocated vpath containing perturbed @src.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_perturb (ArtVpath *src)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ArtVpath *new;
|
||||
double x, y;
|
||||
double x_start, y_start;
|
||||
int open;
|
||||
|
||||
for (i = 0; src[i].code != ART_END; i++);
|
||||
size = i;
|
||||
|
||||
new = art_new (ArtVpath, size + 1);
|
||||
|
||||
x_start = 0;
|
||||
y_start = 0;
|
||||
open = 0;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
new[i].code = src[i].code;
|
||||
x = src[i].x + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
|
||||
y = src[i].y + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
|
||||
if (src[i].code == ART_MOVETO)
|
||||
{
|
||||
x_start = x;
|
||||
y_start = y;
|
||||
open = 0;
|
||||
}
|
||||
else if (src[i].code == ART_MOVETO_OPEN)
|
||||
open = 1;
|
||||
if (!open && (i + 1 == size || src[i + 1].code != ART_LINETO))
|
||||
{
|
||||
x = x_start;
|
||||
y = y_start;
|
||||
}
|
||||
new[i].x = x;
|
||||
new[i].y = y;
|
||||
}
|
||||
new[i].code = ART_END;
|
||||
|
||||
return new;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_VPATH_H__
|
||||
#define __ART_VPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_pathcode.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#endif
|
||||
|
||||
/* Basic data structures and constructors for simple vector paths */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtVpath ArtVpath;
|
||||
|
||||
/* CURVETO is not allowed! */
|
||||
struct _ArtVpath {
|
||||
ArtPathcode code;
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
/* Some of the functions need to go into their own modules */
|
||||
|
||||
void
|
||||
art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
|
||||
ArtPathcode code, double x, double y);
|
||||
|
||||
ArtVpath *
|
||||
art_vpath_new_circle (double x, double y, double r);
|
||||
|
||||
ArtVpath *
|
||||
art_vpath_affine_transform (const ArtVpath *src, const double matrix[6]);
|
||||
|
||||
void
|
||||
art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect);
|
||||
|
||||
void
|
||||
art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect);
|
||||
|
||||
ArtVpath *
|
||||
art_vpath_perturb (ArtVpath *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_H__ */
|
|
@ -0,0 +1,315 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for bezier paths */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_bpath.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_vpath_bpath.h"
|
||||
|
||||
/* p must be allocated 2^level points. */
|
||||
|
||||
/* level must be >= 1 */
|
||||
ArtPoint *
|
||||
art_bezier_to_vec (double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
ArtPoint *p,
|
||||
int level)
|
||||
{
|
||||
double x_m, y_m;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("bezier_to_vec: %g,%g %g,%g %g,%g %g,%g %d\n",
|
||||
x0, y0, x1, y1, x2, y2, x3, y3, level);
|
||||
#endif
|
||||
if (level == 1) {
|
||||
x_m = (x0 + 3 * (x1 + x2) + x3) * 0.125;
|
||||
y_m = (y0 + 3 * (y1 + y2) + y3) * 0.125;
|
||||
p->x = x_m;
|
||||
p->y = y_m;
|
||||
p++;
|
||||
p->x = x3;
|
||||
p->y = y3;
|
||||
p++;
|
||||
#ifdef VERBOSE
|
||||
printf ("-> (%g, %g) -> (%g, %g)\n", x_m, y_m, x3, y3);
|
||||
#endif
|
||||
} else {
|
||||
double xa1, ya1;
|
||||
double xa2, ya2;
|
||||
double xb1, yb1;
|
||||
double xb2, yb2;
|
||||
|
||||
xa1 = (x0 + x1) * 0.5;
|
||||
ya1 = (y0 + y1) * 0.5;
|
||||
xa2 = (x0 + 2 * x1 + x2) * 0.25;
|
||||
ya2 = (y0 + 2 * y1 + y2) * 0.25;
|
||||
xb1 = (x1 + 2 * x2 + x3) * 0.25;
|
||||
yb1 = (y1 + 2 * y2 + y3) * 0.25;
|
||||
xb2 = (x2 + x3) * 0.5;
|
||||
yb2 = (y2 + y3) * 0.5;
|
||||
x_m = (xa2 + xb1) * 0.5;
|
||||
y_m = (ya2 + yb1) * 0.5;
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
|
||||
xb1, yb1, xb2, yb2);
|
||||
#endif
|
||||
p = art_bezier_to_vec (x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, p, level - 1);
|
||||
p = art_bezier_to_vec (x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, p, level - 1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#define RENDER_LEVEL 4
|
||||
#define RENDER_SIZE (1 << (RENDER_LEVEL))
|
||||
|
||||
/**
|
||||
* art_vpath_render_bez: Render a bezier segment into the vpath.
|
||||
* @p_vpath: Where the pointer to the #ArtVpath structure is stored.
|
||||
* @pn_points: Pointer to the number of points in *@p_vpath.
|
||||
* @pn_points_max: Pointer to the number of points allocated.
|
||||
* @x0: X coordinate of starting bezier point.
|
||||
* @y0: Y coordinate of starting bezier point.
|
||||
* @x1: X coordinate of first bezier control point.
|
||||
* @y1: Y coordinate of first bezier control point.
|
||||
* @x2: X coordinate of second bezier control point.
|
||||
* @y2: Y coordinate of second bezier control point.
|
||||
* @x3: X coordinate of ending bezier point.
|
||||
* @y3: Y coordinate of ending bezier point.
|
||||
* @flatness: Flatness control.
|
||||
*
|
||||
* Renders a bezier segment into the vector path, reallocating and
|
||||
* updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
|
||||
* incremented by the number of vector points added.
|
||||
*
|
||||
* This step includes (@x0, @y0) but not (@x3, @y3).
|
||||
*
|
||||
* The @flatness argument guides the amount of subdivision. The Adobe
|
||||
* PostScript reference manual defines flatness as the maximum
|
||||
* deviation between the any point on the vpath approximation and the
|
||||
* corresponding point on the "true" curve, and we follow this
|
||||
* definition here. A value of 0.25 should ensure high quality for aa
|
||||
* rendering.
|
||||
**/
|
||||
static void
|
||||
art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double flatness)
|
||||
{
|
||||
double x3_0, y3_0;
|
||||
double z3_0_dot;
|
||||
double z1_dot, z2_dot;
|
||||
double z1_perp, z2_perp;
|
||||
double max_perp_sq;
|
||||
|
||||
double x_m, y_m;
|
||||
double xa1, ya1;
|
||||
double xa2, ya2;
|
||||
double xb1, yb1;
|
||||
double xb2, yb2;
|
||||
|
||||
/* It's possible to optimize this routine a fair amount.
|
||||
|
||||
First, once the _dot conditions are met, they will also be met in
|
||||
all further subdivisions. So we might recurse to a different
|
||||
routine that only checks the _perp conditions.
|
||||
|
||||
Second, the distance _should_ decrease according to fairly
|
||||
predictable rules (a factor of 4 with each subdivision). So it might
|
||||
be possible to note that the distance is within a factor of 4 of
|
||||
acceptable, and subdivide once. But proving this might be hard.
|
||||
|
||||
Third, at the last subdivision, x_m and y_m can be computed more
|
||||
expeditiously (as in the routine above).
|
||||
|
||||
Finally, if we were able to subdivide by, say 2 or 3, this would
|
||||
allow considerably finer-grain control, i.e. fewer points for the
|
||||
same flatness tolerance. This would speed things up downstream.
|
||||
|
||||
In any case, this routine is unlikely to be the bottleneck. It's
|
||||
just that I have this undying quest for more speed...
|
||||
|
||||
*/
|
||||
|
||||
x3_0 = x3 - x0;
|
||||
y3_0 = y3 - y0;
|
||||
|
||||
/* z3_0_dot is dist z0-z3 squared */
|
||||
z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
|
||||
|
||||
/* todo: this test is far from satisfactory. */
|
||||
if (z3_0_dot < 0.001)
|
||||
goto nosubdivide;
|
||||
|
||||
/* we can avoid subdivision if:
|
||||
|
||||
z1 has distance no more than flatness from the z0-z3 line
|
||||
|
||||
z1 is no more z0'ward than flatness past z0-z3
|
||||
|
||||
z1 is more z0'ward than z3'ward on the line traversing z0-z3
|
||||
|
||||
and correspondingly for z2 */
|
||||
|
||||
/* perp is distance from line, multiplied by dist z0-z3 */
|
||||
max_perp_sq = flatness * flatness * z3_0_dot;
|
||||
|
||||
z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
|
||||
if (z1_perp * z1_perp > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
|
||||
if (z2_perp * z2_perp > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
|
||||
if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
|
||||
if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
if (z1_dot + z1_dot > z3_0_dot)
|
||||
goto subdivide;
|
||||
|
||||
if (z2_dot + z2_dot > z3_0_dot)
|
||||
goto subdivide;
|
||||
|
||||
nosubdivide:
|
||||
/* don't subdivide */
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, x3, y3);
|
||||
return;
|
||||
|
||||
subdivide:
|
||||
|
||||
xa1 = (x0 + x1) * 0.5;
|
||||
ya1 = (y0 + y1) * 0.5;
|
||||
xa2 = (x0 + 2 * x1 + x2) * 0.25;
|
||||
ya2 = (y0 + 2 * y1 + y2) * 0.25;
|
||||
xb1 = (x1 + 2 * x2 + x3) * 0.25;
|
||||
yb1 = (y1 + 2 * y2 + y3) * 0.25;
|
||||
xb2 = (x2 + x3) * 0.5;
|
||||
yb2 = (y2 + y3) * 0.5;
|
||||
x_m = (xa2 + xb1) * 0.5;
|
||||
y_m = (ya2 + yb1) * 0.5;
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
|
||||
xb1, yb1, xb2, yb2);
|
||||
#endif
|
||||
art_vpath_render_bez (p_vpath, pn, pn_max,
|
||||
x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
|
||||
art_vpath_render_bez (p_vpath, pn, pn_max,
|
||||
x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_bez_path_to_vec: Create vpath from bezier path.
|
||||
* @bez: Bezier path.
|
||||
* @flatness: Flatness control.
|
||||
*
|
||||
* Creates a vector path closely approximating the bezier path defined by
|
||||
* @bez. The @flatness argument controls the amount of subdivision. In
|
||||
* general, the resulting vpath deviates by at most @flatness pixels
|
||||
* from the "ideal" path described by @bez.
|
||||
*
|
||||
* Return value: Newly allocated vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_bez_path_to_vec (const ArtBpath *bez, double flatness)
|
||||
{
|
||||
ArtVpath *vec;
|
||||
int vec_n, vec_n_max;
|
||||
int bez_index;
|
||||
double x, y;
|
||||
|
||||
vec_n = 0;
|
||||
vec_n_max = RENDER_SIZE;
|
||||
vec = art_new (ArtVpath, vec_n_max);
|
||||
|
||||
/* Initialization is unnecessary because of the precondition that the
|
||||
bezier path does not begin with LINETO or CURVETO, but is here
|
||||
to make the code warning-free. */
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
bez_index = 0;
|
||||
do
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
printf ("%s %g %g\n",
|
||||
bez[bez_index].code == ART_CURVETO ? "curveto" :
|
||||
bez[bez_index].code == ART_LINETO ? "lineto" :
|
||||
bez[bez_index].code == ART_MOVETO ? "moveto" :
|
||||
bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
|
||||
"end", bez[bez_index].x3, bez[bez_index].y3);
|
||||
#endif
|
||||
/* make sure space for at least one more code */
|
||||
if (vec_n >= vec_n_max)
|
||||
art_expand (vec, ArtVpath, vec_n_max);
|
||||
switch (bez[bez_index].code)
|
||||
{
|
||||
case ART_MOVETO_OPEN:
|
||||
case ART_MOVETO:
|
||||
case ART_LINETO:
|
||||
x = bez[bez_index].x3;
|
||||
y = bez[bez_index].y3;
|
||||
vec[vec_n].code = bez[bez_index].code;
|
||||
vec[vec_n].x = x;
|
||||
vec[vec_n].y = y;
|
||||
vec_n++;
|
||||
break;
|
||||
case ART_END:
|
||||
vec[vec_n].code = bez[bez_index].code;
|
||||
vec[vec_n].x = 0;
|
||||
vec[vec_n].y = 0;
|
||||
vec_n++;
|
||||
break;
|
||||
case ART_CURVETO:
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
|
||||
bez[bez_index].x1, bez[bez_index].y1,
|
||||
bez[bez_index].x2, bez[bez_index].y2,
|
||||
bez[bez_index].x3, bez[bez_index].y3);
|
||||
#endif
|
||||
art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
|
||||
x, y,
|
||||
bez[bez_index].x1, bez[bez_index].y1,
|
||||
bez[bez_index].x2, bez[bez_index].y2,
|
||||
bez[bez_index].x3, bez[bez_index].y3,
|
||||
flatness);
|
||||
x = bez[bez_index].x3;
|
||||
y = bez[bez_index].y3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (bez[bez_index++].code != ART_END);
|
||||
return vec;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_VPATH_BPATH_H__
|
||||
#define __ART_VPATH_BPATH_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtPoint *art_bezier_to_vec (double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
ArtPoint *p,
|
||||
int level);
|
||||
|
||||
ArtVpath *art_bez_path_to_vec (const ArtBpath *bez, double flatness);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_BPATH_H__ */
|
|
@ -0,0 +1,198 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Apply a dash style to a vector path. */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_vpath_dash.h"
|
||||
|
||||
|
||||
/* Return the length of the largest subpath within vpath */
|
||||
static int
|
||||
art_vpath_dash_max_subpath (const ArtVpath *vpath)
|
||||
{
|
||||
int max_subpath;
|
||||
int i;
|
||||
int start;
|
||||
|
||||
max_subpath = 0;
|
||||
start = 0;
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
|
||||
{
|
||||
if (i - start > max_subpath)
|
||||
max_subpath = i - start;
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (i - start > max_subpath)
|
||||
max_subpath = i - start;
|
||||
|
||||
return max_subpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_dash: Add dash style to vpath.
|
||||
* @vpath: Original vpath.
|
||||
* @dash: Dash style.
|
||||
*
|
||||
* Creates a new vpath that is the result of applying dash style @dash
|
||||
* to @vpath.
|
||||
*
|
||||
* This implementation has two known flaws:
|
||||
*
|
||||
* First, it adds a spurious break at the beginning of the vpath. The
|
||||
* only way I see to resolve this flaw is to run the state forward one
|
||||
* dash break at the beginning, and fix up by looping back to the
|
||||
* first dash break at the end. This is doable but of course adds some
|
||||
* complexity.
|
||||
*
|
||||
* Second, it does not suppress output points that are within epsilon
|
||||
* of each other.
|
||||
*
|
||||
* Return value: Newly created vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash)
|
||||
{
|
||||
int max_subpath;
|
||||
double *dists;
|
||||
ArtVpath *result;
|
||||
int n_result, n_result_max;
|
||||
int start, end;
|
||||
int i;
|
||||
double total_dist;
|
||||
|
||||
/* state while traversing dasharray - offset is offset of current dash
|
||||
value, toggle is 0 for "off" and 1 for "on", and phase is the distance
|
||||
in, >= 0, < dash->dash[offset]. */
|
||||
int offset, toggle;
|
||||
double phase;
|
||||
|
||||
/* initial values */
|
||||
int offset_init, toggle_init;
|
||||
double phase_init;
|
||||
|
||||
max_subpath = art_vpath_dash_max_subpath (vpath);
|
||||
dists = art_new (double, max_subpath);
|
||||
|
||||
n_result = 0;
|
||||
n_result_max = 16;
|
||||
result = art_new (ArtVpath, n_result_max);
|
||||
|
||||
/* determine initial values of dash state */
|
||||
toggle_init = 1;
|
||||
offset_init = 0;
|
||||
phase_init = dash->offset;
|
||||
while (phase_init >= dash->dash[offset_init])
|
||||
{
|
||||
toggle_init = !toggle_init;
|
||||
phase_init -= dash->dash[offset_init];
|
||||
offset_init++;
|
||||
if (offset_init == dash->n_dash)
|
||||
offset_init = 0;
|
||||
}
|
||||
|
||||
for (start = 0; vpath[start].code != ART_END; start = end)
|
||||
{
|
||||
for (end = start + 1; vpath[end].code == ART_LINETO; end++);
|
||||
/* subpath is [start..end) */
|
||||
total_dist = 0;
|
||||
for (i = start; i < end - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
dx = vpath[i + 1].x - vpath[i].x;
|
||||
dy = vpath[i + 1].y - vpath[i].y;
|
||||
dists[i - start] = sqrt (dx * dx + dy * dy);
|
||||
total_dist += dists[i - start];
|
||||
}
|
||||
if (total_dist <= dash->dash[offset_init] - phase_init)
|
||||
{
|
||||
/* subpath fits entirely within first dash */
|
||||
if (toggle_init)
|
||||
{
|
||||
for (i = start; i < end; i++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
vpath[i].code, vpath[i].x, vpath[i].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* subpath is composed of at least one dash - thus all
|
||||
generated pieces are open */
|
||||
double dist;
|
||||
|
||||
phase = phase_init;
|
||||
offset = offset_init;
|
||||
toggle = toggle_init;
|
||||
dist = 0;
|
||||
i = start;
|
||||
if (toggle)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO_OPEN, vpath[i].x, vpath[i].y);
|
||||
while (i != end - 1)
|
||||
{
|
||||
if (dists[i - start] - dist > dash->dash[offset] - phase)
|
||||
{
|
||||
/* dash boundary is next */
|
||||
double a;
|
||||
double x, y;
|
||||
|
||||
dist += dash->dash[offset] - phase;
|
||||
a = dist / dists[i - start];
|
||||
x = vpath[i].x + a * (vpath[i + 1].x - vpath[i].x);
|
||||
y = vpath[i].y + a * (vpath[i + 1].y - vpath[i].y);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
toggle ? ART_LINETO : ART_MOVETO_OPEN,
|
||||
x, y);
|
||||
/* advance to next dash */
|
||||
toggle = !toggle;
|
||||
phase = 0;
|
||||
offset++;
|
||||
if (offset == dash->n_dash)
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* end of line in vpath is next */
|
||||
phase += dists[i - start] - dist;
|
||||
i++;
|
||||
dist = 0;
|
||||
if (toggle)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, vpath[i].x, vpath[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_END, 0, 0);
|
||||
|
||||
art_free (dists);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_VPATH_DASH_H__
|
||||
#define __ART_VPATH_DASH_H__
|
||||
|
||||
/* Apply a dash style to a vector path. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtVpathDash ArtVpathDash;
|
||||
|
||||
struct _ArtVpathDash {
|
||||
double offset;
|
||||
int n_dash;
|
||||
double *dash;
|
||||
};
|
||||
|
||||
ArtVpath *
|
||||
art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_DASH_H__ */
|
|
@ -0,0 +1,194 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998-2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* "Unsort" a sorted vector path into an ordinary vector path. */
|
||||
|
||||
#include <stdio.h> /* for printf - debugging */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
typedef struct _ArtVpathSVPEnd ArtVpathSVPEnd;
|
||||
|
||||
struct _ArtVpathSVPEnd {
|
||||
int seg_num;
|
||||
int which; /* 0 = top, 1 = bottom */
|
||||
double x, y;
|
||||
};
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
static int
|
||||
art_vpath_svp_point_compare (double x1, double y1, double x2, double y2)
|
||||
{
|
||||
if (y1 - EPSILON > y2) return 1;
|
||||
if (y1 + EPSILON < y2) return -1;
|
||||
if (x1 - EPSILON > x2) return 1;
|
||||
if (x1 + EPSILON < x2) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
art_vpath_svp_compare (const void *s1, const void *s2)
|
||||
{
|
||||
const ArtVpathSVPEnd *e1 = s1;
|
||||
const ArtVpathSVPEnd *e2 = s2;
|
||||
|
||||
return art_vpath_svp_point_compare (e1->x, e1->y, e2->x, e2->y);
|
||||
}
|
||||
|
||||
/* Convert from sorted vector path representation into regular
|
||||
vector path representation.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Only works with closed paths.
|
||||
|
||||
Numerical stability: Not known to work when more than two segments
|
||||
meet at a point.
|
||||
|
||||
Speed: Should be pretty good.
|
||||
|
||||
Precision: Does not degrade precision.
|
||||
|
||||
*/
|
||||
/**
|
||||
* art_vpath_from_svp: Convert from svp to vpath form.
|
||||
* @svp: Original #ArtSVP.
|
||||
*
|
||||
* Converts the sorted vector path @svp into standard vpath form.
|
||||
*
|
||||
* Return value: the newly allocated vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_from_svp (const ArtSVP *svp)
|
||||
{
|
||||
int n_segs = svp->n_segs;
|
||||
ArtVpathSVPEnd *ends;
|
||||
ArtVpath *new;
|
||||
int *visited;
|
||||
int n_new, n_new_max;
|
||||
int i, k;
|
||||
int j = 0; /* Quiet compiler */
|
||||
int seg_num;
|
||||
int first;
|
||||
double last_x, last_y;
|
||||
int n_points;
|
||||
int pt_num;
|
||||
|
||||
last_x = 0; /* to eliminate "uninitialized" warning */
|
||||
last_y = 0;
|
||||
|
||||
ends = art_new (ArtVpathSVPEnd, n_segs * 2);
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
int lastpt;
|
||||
|
||||
ends[i * 2].seg_num = i;
|
||||
ends[i * 2].which = 0;
|
||||
ends[i * 2].x = svp->segs[i].points[0].x;
|
||||
ends[i * 2].y = svp->segs[i].points[0].y;
|
||||
|
||||
lastpt = svp->segs[i].n_points - 1;
|
||||
ends[i * 2 + 1].seg_num = i;
|
||||
ends[i * 2 + 1].which = 1;
|
||||
ends[i * 2 + 1].x = svp->segs[i].points[lastpt].x;
|
||||
ends[i * 2 + 1].y = svp->segs[i].points[lastpt].y;
|
||||
}
|
||||
qsort (ends, n_segs * 2, sizeof (ArtVpathSVPEnd), art_vpath_svp_compare);
|
||||
|
||||
n_new = 0;
|
||||
n_new_max = 16; /* I suppose we _could_ estimate this from traversing
|
||||
the svp, so we don't have to reallocate */
|
||||
new = art_new (ArtVpath, n_new_max);
|
||||
|
||||
visited = art_new (int, n_segs);
|
||||
for (i = 0; i < n_segs; i++)
|
||||
visited[i] = 0;
|
||||
|
||||
first = 1;
|
||||
for (i = 0; i < n_segs; i++)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
/* search for the continuation of the existing subpath */
|
||||
/* This could be a binary search (which is why we sorted, above) */
|
||||
for (j = 0; j < n_segs * 2; j++)
|
||||
{
|
||||
if (!visited[ends[j].seg_num] &&
|
||||
art_vpath_svp_point_compare (last_x, last_y,
|
||||
ends[j].x, ends[j].y) == 0)
|
||||
break;
|
||||
}
|
||||
if (j == n_segs * 2)
|
||||
first = 1;
|
||||
}
|
||||
if (first)
|
||||
{
|
||||
/* start a new subpath */
|
||||
for (j = 0; j < n_segs * 2; j++)
|
||||
if (!visited[ends[j].seg_num])
|
||||
break;
|
||||
}
|
||||
if (j == n_segs * 2)
|
||||
{
|
||||
printf ("failure\n");
|
||||
}
|
||||
seg_num = ends[j].seg_num;
|
||||
n_points = svp->segs[seg_num].n_points;
|
||||
for (k = 0; k < n_points; k++)
|
||||
{
|
||||
pt_num = svp->segs[seg_num].dir ? k : n_points - (1 + k);
|
||||
if (k == 0)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_MOVETO,
|
||||
svp->segs[seg_num].points[pt_num].x,
|
||||
svp->segs[seg_num].points[pt_num].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_LINETO,
|
||||
svp->segs[seg_num].points[pt_num].x,
|
||||
svp->segs[seg_num].points[pt_num].y);
|
||||
if (k == n_points - 1)
|
||||
{
|
||||
last_x = svp->segs[seg_num].points[pt_num].x;
|
||||
last_y = svp->segs[seg_num].points[pt_num].y;
|
||||
/* to make more robust, check for meeting first_[xy],
|
||||
set first if so */
|
||||
}
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
visited[seg_num] = 1;
|
||||
}
|
||||
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_END, 0, 0);
|
||||
art_free (visited);
|
||||
art_free (ends);
|
||||
return new;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ART_VPATH_SVP_H__
|
||||
#define __ART_VPATH_SVP_H__
|
||||
|
||||
/* "Unsort" a sorted vector path into an ordinary vector path. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_point.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtVpath *art_vpath_from_svp (const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_SVP_H__ */
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
# This was lifted from the Gimp, and adapted slightly by
|
||||
# Raph Levien <raph@acm.org>.
|
||||
|
||||
DIE=0
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PROJECT=LibArt_LGPL
|
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have autoconf installed to compile $PROJECT."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
# Do we really need libtool?
|
||||
(libtool --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have libtool installed to compile $PROJECT."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.2.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have automake installed to compile $PROJECT."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/automake-1.3.tar.gz"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if test "$DIE" -eq 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$*"; then
|
||||
echo "I am going to run ./configure with no arguments - if you wish "
|
||||
echo "to pass any to it, please specify them on the $0 command line."
|
||||
fi
|
||||
|
||||
case $CC in
|
||||
xlc )
|
||||
am_opt=--include-deps;;
|
||||
esac
|
||||
|
||||
for dir in $srcdir
|
||||
do
|
||||
echo processing $dir
|
||||
(cd $dir; \
|
||||
aclocalinclude="$ACLOCAL_FLAGS"; \
|
||||
aclocal $aclocalinclude; \
|
||||
autoheader; automake --add-missing --gnu $am_opt; autoconf)
|
||||
done
|
||||
|
||||
$srcdir/configure "$@"
|
||||
|
||||
echo
|
||||
echo "Now type 'make' to compile $PROJECT."
|
|
@ -0,0 +1,69 @@
|
|||
AC_INIT(art_misc.h)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
LIBART_MAJOR_VERSION=2
|
||||
LIBART_MINOR_VERSION=3
|
||||
LIBART_MICRO_VERSION=7
|
||||
LIBART_VERSION=$LIBART_MAJOR_VERSION.$LIBART_MINOR_VERSION.$LIBART_MICRO_VERSION
|
||||
LIBART_VERSION_INFO=`expr $LIBART_MAJOR_VERSION + $LIBART_MINOR_VERSION`:$LIBART_MICRO_VERSION:$LIBART_MINOR_VERSION
|
||||
|
||||
AC_SUBST(LIBART_MAJOR_VERSION)
|
||||
AC_SUBST(LIBART_MINOR_VERSION)
|
||||
AC_SUBST(LIBART_MICRO_VERSION)
|
||||
AC_SUBST(LIBART_VERSION)
|
||||
AC_SUBST(LIBART_VERSION_INFO)
|
||||
|
||||
VERSION=$LIBART_VERSION
|
||||
|
||||
AM_INIT_AUTOMAKE(libart_lgpl, $VERSION)
|
||||
|
||||
AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]],
|
||||
, enable_ansi=no)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
changequote(,)dnl
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-ansi[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -ansi" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-pedantic[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -pedantic" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
LIBART_LIBDIR='-L${libdir}'
|
||||
LIBART_INCLUDEDIR='-I${includedir}'
|
||||
LIBART_LIBS='-lart_lgpl'
|
||||
|
||||
AC_SUBST(LIBART_LIBDIR)
|
||||
AC_SUBST(LIBART_INCLUDEDIR)
|
||||
AC_SUBST(LIBART_LIBS)
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
AC_OUTPUT([
|
||||
libart-features.h
|
||||
Makefile
|
||||
libart-config
|
||||
libart-2.0.pc], [case "$CONFIG_FILES" in *libart-config*) chmod +x libart-config;; esac])
|
|
@ -0,0 +1,52 @@
|
|||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* A little utility function to generate header info.
|
||||
*
|
||||
* Yes, it would be possible to do this using more "native" autoconf
|
||||
* features, but I personally find this approach to be cleaner.
|
||||
*
|
||||
* The output of this program is generally written to art_config.h,
|
||||
* which is installed in libart's include dir.
|
||||
**/
|
||||
|
||||
static void
|
||||
die (char *why)
|
||||
{
|
||||
fprintf (stderr, "gen_art_config: %s\n", why);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
printf ("/* Automatically generated by gen_art_config.c */\n"
|
||||
"\n"
|
||||
"#define ART_SIZEOF_CHAR %d\n"
|
||||
"#define ART_SIZEOF_SHORT %d\n"
|
||||
"#define ART_SIZEOF_INT %d\n"
|
||||
"#define ART_SIZEOF_LONG %d\n"
|
||||
"\n",
|
||||
(int)sizeof(char), (int)sizeof(short), (int)sizeof(int), (int)sizeof(long));
|
||||
|
||||
if (sizeof(char) == 1)
|
||||
printf ("typedef unsigned char art_u8;\n");
|
||||
else
|
||||
die ("sizeof(char) != 1");
|
||||
|
||||
if (sizeof(short) == 2)
|
||||
printf ("typedef unsigned short art_u16;\n");
|
||||
else
|
||||
die ("sizeof(short) != 2");
|
||||
|
||||
if (sizeof(int) == 4)
|
||||
printf ("typedef unsigned int art_u32;\n");
|
||||
else if (sizeof(long) == 4)
|
||||
printf ("typedef unsigned long art_u32;\n");
|
||||
else
|
||||
die ("sizeof(int) != 4 and sizeof(long) != 4");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libart
|
||||
Description: LGPL version of the libart library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lart_lgpl_2
|
||||
Cflags: -I${includedir}/libart-2.0
|
|
@ -0,0 +1,56 @@
|
|||
#!/bin/sh
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
exec_prefix_set=no
|
||||
|
||||
usage="\
|
||||
Usage: libart-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) optarg= ;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--prefix=*)
|
||||
prefix=$optarg
|
||||
if test $exec_prefix_set = no ; then
|
||||
exec_prefix=$optarg
|
||||
fi
|
||||
;;
|
||||
--prefix)
|
||||
echo $prefix
|
||||
;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=$optarg
|
||||
exec_prefix_set=yes
|
||||
;;
|
||||
--exec-prefix)
|
||||
echo $exec_prefix
|
||||
;;
|
||||
--version)
|
||||
echo @LIBART_VERSION@
|
||||
;;
|
||||
--cflags)
|
||||
includes=-I@includedir@/libart-2.0
|
||||
echo $includes
|
||||
;;
|
||||
--libs)
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lart_lgpl_2 -lm
|
||||
;;
|
||||
*)
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#include "libart-features.h"
|
||||
|
||||
/* General initialization hooks */
|
||||
const unsigned int libart_major_version=LIBART_MAJOR_VERSION,
|
||||
libart_minor_version=LIBART_MINOR_VERSION,
|
||||
libart_micro_version=LIBART_MICRO_VERSION;
|
||||
|
||||
const char *libart_version = LIBART_VERSION;
|
||||
|
||||
void
|
||||
libart_preinit(void *app, void *modinfo)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
libart_postinit(void *app, void *modinfo)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef LIBART_FEATURES_H
|
||||
#define LIBART_FEATURES_H 1
|
||||
|
||||
#define LIBART_MAJOR_VERSION (@LIBART_MAJOR_VERSION@)
|
||||
#define LIBART_MINOR_VERSION (@LIBART_MINOR_VERSION@)
|
||||
#define LIBART_MICRO_VERSION (@LIBART_MICRO_VERSION@)
|
||||
#define LIBART_VERSION "@LIBART_VERSION@"
|
||||
|
||||
extern const unsigned int libart_major_version, libart_minor_version, libart_micro_version;
|
||||
extern const char *libart_version;
|
||||
|
||||
void libart_preinit(void *app, void *modinfo);
|
||||
void libart_postinit(void *app, void *modinfo);
|
||||
#endif
|
|
@ -0,0 +1,93 @@
|
|||
; libart.def : Declares the funcion exports of the DLL.
|
||||
|
||||
LIBRARY "libart"
|
||||
DESCRIPTION 'libart Windows Dynamic Link Library'
|
||||
|
||||
EXPORTS
|
||||
art_affine_equal
|
||||
art_affine_expansion
|
||||
art_affine_flip
|
||||
art_affine_identity
|
||||
art_affine_invert
|
||||
art_affine_multiply
|
||||
art_affine_point
|
||||
art_affine_rectilinear
|
||||
art_affine_rotate
|
||||
art_affine_scale
|
||||
art_affine_shear
|
||||
art_affine_to_string
|
||||
art_affine_translate
|
||||
art_alphagamma_free
|
||||
art_alphagamma_new
|
||||
art_bez_path_to_vec
|
||||
art_bezier_to_vec
|
||||
art_bpath_affine_transform
|
||||
art_die
|
||||
art_drect_affine_transform
|
||||
art_drect_copy
|
||||
art_drect_empty
|
||||
art_drect_intersect
|
||||
art_drect_svp
|
||||
art_drect_svp_union
|
||||
art_drect_to_irect
|
||||
art_drect_union
|
||||
art_gray_svp_aa
|
||||
art_irect_copy
|
||||
art_irect_empty
|
||||
art_irect_intersect
|
||||
art_irect_union
|
||||
art_pixbuf_duplicate
|
||||
art_pixbuf_free
|
||||
art_pixbuf_free_shallow
|
||||
art_pixbuf_new_const_rgb
|
||||
art_pixbuf_new_const_rgba
|
||||
art_pixbuf_new_rgb
|
||||
art_pixbuf_new_rgb_dnotify
|
||||
art_pixbuf_new_rgba
|
||||
art_pixbuf_new_rgba_dnotify
|
||||
art_rect_list_from_uta
|
||||
art_rgba_rgba_composite
|
||||
art_rgba_fill_run
|
||||
art_rgba_run_alpha
|
||||
art_rgb_affine
|
||||
art_rgb_affine_run
|
||||
art_rgb_bitmap_affine
|
||||
art_rgb_fill_run
|
||||
art_rgb_pixbuf_affine
|
||||
art_rgb_rgba_affine
|
||||
art_rgb_run_alpha
|
||||
art_rgb_svp_aa
|
||||
art_rgb_svp_alpha
|
||||
art_svp_add_segment
|
||||
art_svp_diff
|
||||
art_svp_free
|
||||
art_svp_from_vpath
|
||||
art_svp_intersect
|
||||
art_svp_point_dist
|
||||
art_svp_point_wind
|
||||
art_svp_render_aa
|
||||
art_svp_rewind_uncrossed
|
||||
art_svp_seg_compare
|
||||
art_svp_uncross
|
||||
art_svp_union
|
||||
art_svp_vpath_stroke
|
||||
art_svp_vpath_stroke_raw
|
||||
art_uta_add_line
|
||||
art_uta_free
|
||||
art_uta_from_irect
|
||||
art_uta_from_svp
|
||||
art_uta_from_vpath
|
||||
art_uta_new
|
||||
art_uta_new_coords
|
||||
art_uta_union
|
||||
art_vpath_add_point
|
||||
art_vpath_affine_transform
|
||||
art_vpath_bbox_drect
|
||||
art_vpath_bbox_irect
|
||||
art_vpath_dash
|
||||
art_vpath_from_svp
|
||||
art_vpath_new_circle
|
||||
art_vpath_perturb
|
||||
art_warn
|
||||
; trap_epsilon
|
||||
; traverse
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef LIBART_H
|
||||
#define LIBART_H 1
|
||||
|
||||
#include <libart_lgpl/art_affine.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#include <libart_lgpl/art_bpath.h>
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_gray_svp.h>
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#include <libart_lgpl/art_pixbuf.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_rect_svp.h>
|
||||
#include <libart_lgpl/art_rect_uta.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
#include <libart_lgpl/art_rgb_affine.h>
|
||||
#include <libart_lgpl/art_rgb_bitmap_affine.h>
|
||||
#include <libart_lgpl/art_rgb_pixbuf_affine.h>
|
||||
#include <libart_lgpl/art_rgb_rgba_affine.h>
|
||||
#include <libart_lgpl/art_rgb_svp.h>
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_svp_ops.h>
|
||||
#include <libart_lgpl/art_svp_point.h>
|
||||
#include <libart_lgpl/art_svp_render_aa.h>
|
||||
#include <libart_lgpl/art_svp_vpath.h>
|
||||
#include <libart_lgpl/art_svp_vpath_stroke.h>
|
||||
#include <libart_lgpl/art_svp_wind.h>
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#include <libart_lgpl/art_uta_ops.h>
|
||||
#include <libart_lgpl/art_uta_rect.h>
|
||||
#include <libart_lgpl/art_uta_svp.h>
|
||||
#include <libart_lgpl/art_uta_vpath.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#include <libart_lgpl/art_vpath_bpath.h>
|
||||
#include <libart_lgpl/art_vpath_dash.h>
|
||||
#include <libart_lgpl/art_vpath_svp.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,165 @@
|
|||
# Configure paths for LIBART
|
||||
# Raph Levien 98-11-18
|
||||
# stolen from Manish Singh 98-9-30
|
||||
# stolen back from Frank Belew
|
||||
# stolen from Manish Singh
|
||||
# Shamelessly stolen from Owen Taylor
|
||||
|
||||
dnl AM_PATH_LIBART([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl Test for LIBART, and define LIBART_CFLAGS and LIBART_LIBS
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_LIBART,
|
||||
[dnl
|
||||
dnl Get the cflags and libraries from the libart-config script
|
||||
dnl
|
||||
AC_ARG_WITH(libart-prefix,[ --with-libart-prefix=PFX Prefix where LIBART is installed (optional)],
|
||||
libart_prefix="$withval", libart_prefix="")
|
||||
AC_ARG_WITH(libart-exec-prefix,[ --with-libart-exec-prefix=PFX Exec prefix where LIBART is installed (optional)],
|
||||
libart_exec_prefix="$withval", libart_exec_prefix="")
|
||||
AC_ARG_ENABLE(libarttest, [ --disable-libarttest Do not try to compile and run a test LIBART program],
|
||||
, enable_libarttest=yes)
|
||||
|
||||
if test x$libart_exec_prefix != x ; then
|
||||
libart_args="$libart_args --exec-prefix=$libart_exec_prefix"
|
||||
if test x${LIBART_CONFIG+set} != xset ; then
|
||||
LIBART_CONFIG=$libart_exec_prefix/bin/libart-config
|
||||
fi
|
||||
fi
|
||||
if test x$libart_prefix != x ; then
|
||||
libart_args="$libart_args --prefix=$libart_prefix"
|
||||
if test x${LIBART_CONFIG+set} != xset ; then
|
||||
LIBART_CONFIG=$libart_prefix/bin/libart-config
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(LIBART_CONFIG, libart-config, no)
|
||||
min_libart_version=ifelse([$1], ,0.2.5,$1)
|
||||
AC_MSG_CHECKING(for LIBART - version >= $min_libart_version)
|
||||
no_libart=""
|
||||
if test "$LIBART_CONFIG" = "no" ; then
|
||||
no_libart=yes
|
||||
else
|
||||
LIBART_CFLAGS=`$LIBART_CONFIG $libartconf_args --cflags`
|
||||
LIBART_LIBS=`$LIBART_CONFIG $libartconf_args --libs`
|
||||
|
||||
libart_major_version=`$LIBART_CONFIG $libart_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
|
||||
libart_minor_version=`$LIBART_CONFIG $libart_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
|
||||
libart_micro_version=`$LIBART_CONFIG $libart_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
|
||||
if test "x$enable_libarttest" = "xyes" ; then
|
||||
ac_save_CFLAGS="$CFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $LIBART_CFLAGS"
|
||||
LIBS="$LIBS $LIBART_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed LIBART is sufficiently new. (Also sanity
|
||||
dnl checks the results of libart-config to some extent
|
||||
dnl
|
||||
rm -f conf.libarttest
|
||||
AC_TRY_RUN([
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libart_lgpl/libart.h>
|
||||
|
||||
char*
|
||||
my_strdup (char *str)
|
||||
{
|
||||
char *new_str;
|
||||
|
||||
if (str)
|
||||
{
|
||||
new_str = malloc ((strlen (str) + 1) * sizeof(char));
|
||||
strcpy (new_str, str);
|
||||
}
|
||||
else
|
||||
new_str = NULL;
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
int major, minor, micro;
|
||||
char *tmp_version;
|
||||
|
||||
system ("touch conf.libarttest");
|
||||
|
||||
/* HP/UX 9 (%@#!) writes to sscanf strings */
|
||||
tmp_version = my_strdup("$min_libart_version");
|
||||
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) {
|
||||
printf("%s, bad version string\n", "$min_libart_version");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (($libart_major_version > major) ||
|
||||
(($libart_major_version == major) && ($libart_minor_version > minor)) ||
|
||||
(($libart_major_version == major) && ($libart_minor_version == minor) && ($libart_micro_version >= micro)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n*** 'libart-config --version' returned %d.%d.%d, but the minimum version\n", $libart_major_version, $libart_minor_version, $libart_micro_version);
|
||||
printf("*** of LIBART required is %d.%d.%d. If libart-config is correct, then it is\n", major, minor, micro);
|
||||
printf("*** best to upgrade to the required version.\n");
|
||||
printf("*** If libart-config was wrong, set the environment variable LIBART_CONFIG\n");
|
||||
printf("*** to point to the correct copy of libart-config, and remove the file\n");
|
||||
printf("*** config.cache before re-running configure\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
],, no_libart=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
fi
|
||||
if test "x$no_libart" = x ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test "$LIBART_CONFIG" = "no" ; then
|
||||
echo "*** The libart-config script installed by LIBART could not be found"
|
||||
echo "*** If LIBART was installed in PREFIX, make sure PREFIX/bin is in"
|
||||
echo "*** your path, or set the LIBART_CONFIG environment variable to the"
|
||||
echo "*** full path to libart-config."
|
||||
else
|
||||
if test -f conf.libarttest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run LIBART test program, checking why..."
|
||||
CFLAGS="$CFLAGS $LIBART_CFLAGS"
|
||||
LIBS="$LIBS $LIBART_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <stdio.h>
|
||||
#include <libart_lgpl/libart.h>
|
||||
], [ return 0; ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding LIBART or finding the wrong"
|
||||
echo "*** version of LIBART. If it is not finding LIBART, you'll need to set your"
|
||||
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
|
||||
echo "*** to the installed location Also, make sure you have run ldconfig if that"
|
||||
echo "*** is required on your system"
|
||||
echo "***"
|
||||
echo "*** If you have an old version installed, it is best to remove it, although"
|
||||
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
|
||||
[ echo "*** The test program failed to compile or link. See the file config.log for the"
|
||||
echo "*** exact error that occured. This usually means LIBART was incorrectly installed"
|
||||
echo "*** or that you have moved LIBART since it was installed. In the latter case, you"
|
||||
echo "*** may want to edit the libart-config script: $LIBART_CONFIG" ])
|
||||
CFLAGS="$ac_save_CFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
fi
|
||||
LIBART_CFLAGS=""
|
||||
LIBART_LIBS=""
|
||||
ifelse([$3], , :, [$3])
|
||||
fi
|
||||
AC_SUBST(LIBART_CFLAGS)
|
||||
AC_SUBST(LIBART_LIBS)
|
||||
rm -f conf.libarttest
|
||||
])
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Configuration file for using the LIBART library in GNOME applications
|
||||
#
|
||||
LIBART_LIBDIR="@LIBART_LIBDIR@"
|
||||
LIBART_LIBS="@LIBART_LIBS@"
|
||||
LIBART_INCLUDEDIR="@LIBART_INCLUDEDIR@"
|
|
@ -0,0 +1,98 @@
|
|||
PACKAGE = libart
|
||||
PKG_CFLAGS = -I.. -DLIBART_COMPILATION
|
||||
|
||||
OBJECTS = \
|
||||
art_affine.obj \
|
||||
art_alphagamma.obj \
|
||||
art_bpath.obj \
|
||||
art_gray_svp.obj \
|
||||
art_misc.obj \
|
||||
art_pixbuf.obj \
|
||||
art_rect.obj \
|
||||
art_rect_svp.obj \
|
||||
art_rect_uta.obj \
|
||||
art_rgb.obj \
|
||||
art_rgba.obj \
|
||||
art_rgb_affine.obj \
|
||||
art_rgb_affine_private.obj \
|
||||
art_rgb_bitmap_affine.obj \
|
||||
art_rgb_pixbuf_affine.obj \
|
||||
art_rgb_rgba_affine.obj \
|
||||
art_rgb_svp.obj \
|
||||
art_svp.obj \
|
||||
art_svp_ops.obj \
|
||||
art_svp_point.obj \
|
||||
art_svp_render_aa.obj \
|
||||
art_svp_vpath.obj \
|
||||
art_svp_vpath_stroke.obj \
|
||||
art_svp_wind.obj \
|
||||
art_uta.obj \
|
||||
art_uta_ops.obj \
|
||||
art_uta_rect.obj \
|
||||
art_uta_svp.obj \
|
||||
art_uta_vpath.obj \
|
||||
art_vpath.obj \
|
||||
art_vpath_bpath.obj \
|
||||
art_vpath_dash.obj \
|
||||
art_vpath_svp.obj \
|
||||
|
||||
testOBJECTS = \
|
||||
testart.obj \
|
||||
testuta.obj \
|
||||
|
||||
## common stuff
|
||||
## compiler and linker switches
|
||||
!IFNDEF DEBUG
|
||||
# Full optimization:
|
||||
OPTIMIZE = -Ox -MD
|
||||
LINKDEBUG =
|
||||
!ELSE
|
||||
# Debugging:
|
||||
OPTIMIZE = -Zi -MDd
|
||||
LINKDEBUG = /debug
|
||||
!ENDIF
|
||||
|
||||
# cl -? describes the options
|
||||
CC = cl -G5 -GF $(OPTIMIZE) -W3 -nologo
|
||||
|
||||
# No general LDFLAGS needed
|
||||
LDFLAGS = /link $(LINKDEBUG)
|
||||
INSTALL = copy
|
||||
|
||||
CFLAGS = -I. -DHAVE_CONFIG_H
|
||||
|
||||
## targets
|
||||
all : \
|
||||
config.h \
|
||||
art_config.h \
|
||||
$(PACKAGE).dll
|
||||
|
||||
$(PACKAGE).dll : $(OBJECTS) $(PACKAGE).def
|
||||
$(CC) $(CFLAGS) -LD -Fe$(PACKAGE).dll $(OBJECTS) user32.lib advapi32.lib wsock32.lib $(LDFLAGS) /def:$(PACKAGE).def
|
||||
|
||||
config.h: config.h.win32
|
||||
copy config.h.win32 config.h
|
||||
|
||||
art_config.h : gen_art_config.exe
|
||||
gen_art_config.exe > art_config.h
|
||||
|
||||
gen_art_config.exe : gen_art_config.obj
|
||||
$(CC) $(CFLAGS) -Fegen_art_config.exe gen_art_config.obj user32.lib
|
||||
|
||||
.c.obj :
|
||||
$(CC) $(CFLAGS) -GD -c $(PKG_CFLAGS) $<
|
||||
|
||||
clean:
|
||||
del config.h
|
||||
del *.exe
|
||||
del *.obj
|
||||
del *.dll
|
||||
del *.lib
|
||||
del *.err
|
||||
del *.map
|
||||
del *.sym
|
||||
del *.exp
|
||||
del *.lk1
|
||||
del *.mk1
|
||||
del *.pdb
|
||||
del *.ilk
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче