1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-02-02 22:25:48 +01:00

Initial revision

This commit is contained in:
scottc
1998-09-29 22:36:29 +00:00
commit 9d2e6ef9f1
527 changed files with 138651 additions and 0 deletions

0
wrlib/AUTHORS Normal file
View File

481
wrlib/COPYING Normal file
View File

@@ -0,0 +1,481 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, 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
Appendix: 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., 675 Mass Ave, Cambridge, MA 02139, 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!

7
wrlib/ChangeLog Normal file
View File

@@ -0,0 +1,7 @@
- added RMakeCenteredImage()
- Added code to draw pixels and lines. Both writing absolute values, or
offseting existing pixels with delta values are supported.
- Remade the beveling code to be simpler, using the RAlterLine() functions.
- Fixed some pixels in the bevels.
- Changed RAlter* functions to more generic ROperate*

5
wrlib/INSTALL Normal file
View File

@@ -0,0 +1,5 @@
./configure
make
make install

56
wrlib/Makefile.am Normal file
View File

@@ -0,0 +1,56 @@
## automake input file for wrlib
AUTOMAKE_OPTIONS = no-dependencies
lib_LIBRARIES = libwraster.a
noinst_PROGRAMS = test testgrad testdraw view
EXTRA_DIST = test.png tile.xpm ballot_box.xpm ballot_box.tiff
include_HEADERS = wraster.h
libwraster_a_SOURCES = \
raster.c \
draw.c \
color.c \
load.c \
gradient.c \
xpixmap.c \
convert.c \
context.c \
misc.c \
scale.c \
convolve.c \
nxpm.c \
xpm.c \
xutil.c \
ppm.c \
png.c \
jpeg.c \
tiff.c \
gif.c
INCLUDES = @DFLAGS@ @XCFLAGS@ @GFXFLAGS@ @XSHM@
view_SOURCES= view.c
view_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
test_SOURCES = test.c
test_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
testgrad_SOURCES = testgrad.c
testgrad_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
testdraw_SOURCES = testdraw.c
testdraw_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
libwraster_a_LIBADD = @ALLOCA@

406
wrlib/Makefile.in Normal file
View File

@@ -0,0 +1,406 @@
# Makefile.in generated automatically by automake 1.3 from Makefile.am
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = /bin/sh
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DISTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
CC = @CC@
CPP_PATH = @CPP_PATH@
DFLAGS = @DFLAGS@
GFXFLAGS = @GFXFLAGS@
GFXLIBS = @GFXLIBS@
I18N = @I18N@
I18N_MB = @I18N_MB@
ICONEXT = @ICONEXT@
INTLIBS = @INTLIBS@
LIBPL_INC_PATH = @LIBPL_INC_PATH@
LIBPL_LIBS = @LIBPL_LIBS@
LN_S = @LN_S@
MAKEINFO = @MAKEINFO@
MOFILES = @MOFILES@
NLSDIR = @NLSDIR@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
REDUCE_APPICONS = @REDUCE_APPICONS@
SHAPE = @SHAPE@
SOUND = @SOUND@
VERSION = @VERSION@
WPMOFILES = @WPMOFILES@
XCFLAGS = @XCFLAGS@
XGETTEXT = @XGETTEXT@
XLFLAGS = @XLFLAGS@
XLIBS = @XLIBS@
XSHM = @XSHM@
X_EXTRA_LIBS = @X_EXTRA_LIBS@
X_LOCALE = @X_LOCALE@
pixmapdir = @pixmapdir@
wprefsdir = @wprefsdir@
AUTOMAKE_OPTIONS = no-dependencies
lib_LIBRARIES = libwraster.a
noinst_PROGRAMS = test testgrad testdraw view
EXTRA_DIST = test.png tile.xpm ballot_box.xpm ballot_box.tiff
include_HEADERS = wraster.h
libwraster_a_SOURCES = \
raster.c \
draw.c \
color.c \
load.c \
gradient.c \
xpixmap.c \
convert.c \
context.c \
misc.c \
scale.c \
convolve.c \
nxpm.c \
xpm.c \
xutil.c \
ppm.c \
png.c \
jpeg.c \
tiff.c \
gif.c
INCLUDES = @DFLAGS@ @XCFLAGS@ @GFXFLAGS@ @XSHM@
view_SOURCES= view.c
view_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
test_SOURCES = test.c
test_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
testgrad_SOURCES = testgrad.c
testgrad_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
testdraw_SOURCES = testdraw.c
testdraw_LDADD = -L. -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ -lm
libwraster_a_LIBADD = @ALLOCA@
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../src/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(lib_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I../src
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
X_CFLAGS = @X_CFLAGS@
X_LIBS = @X_LIBS@
X_PRE_LIBS = @X_PRE_LIBS@
libwraster_a_DEPENDENCIES = @ALLOCA@
libwraster_a_OBJECTS = raster.o draw.o color.o load.o gradient.o \
xpixmap.o convert.o context.o misc.o scale.o convolve.o nxpm.o xpm.o \
xutil.o ppm.o png.o jpeg.o tiff.o gif.o
AR = ar
PROGRAMS = $(noinst_PROGRAMS)
test_OBJECTS = test.o
test_DEPENDENCIES =
test_LDFLAGS =
testgrad_OBJECTS = testgrad.o
testgrad_DEPENDENCIES =
testgrad_LDFLAGS =
testdraw_OBJECTS = testdraw.o
testdraw_DEPENDENCIES =
testdraw_LDFLAGS =
view_OBJECTS = view.o
view_DEPENDENCIES =
view_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
HEADERS = $(include_HEADERS)
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
Makefile.in NEWS TODO alloca.c configure.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP = --best
SOURCES = $(libwraster_a_SOURCES) $(test_SOURCES) $(testgrad_SOURCES) $(testdraw_SOURCES) $(view_SOURCES)
OBJECTS = $(libwraster_a_OBJECTS) $(test_OBJECTS) $(testgrad_OBJECTS) $(testdraw_OBJECTS) $(view_OBJECTS)
all: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
.SUFFIXES:
.SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu wrlib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-libLIBRARIES:
clean-libLIBRARIES:
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
distclean-libLIBRARIES:
maintainer-clean-libLIBRARIES:
install-libLIBRARIES: $(lib_LIBRARIES)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(libdir)
list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
$(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
else :; fi; \
done
@$(POST_INSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(RANLIB) $(DESTDIR)$(libdir)/$$p"; \
$(RANLIB) $(DESTDIR)$(libdir)/$$p; \
else :; fi; \
done
uninstall-libLIBRARIES:
@$(NORMAL_UNINSTALL)
list='$(lib_LIBRARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(libdir)/$$p; \
done
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
libwraster.a: $(libwraster_a_OBJECTS) $(libwraster_a_DEPENDENCIES)
-rm -f libwraster.a
$(AR) cru libwraster.a $(libwraster_a_OBJECTS) $(libwraster_a_LIBADD)
$(RANLIB) libwraster.a
mostlyclean-noinstPROGRAMS:
clean-noinstPROGRAMS:
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
distclean-noinstPROGRAMS:
maintainer-clean-noinstPROGRAMS:
test: $(test_OBJECTS) $(test_DEPENDENCIES)
@rm -f test
$(LINK) $(test_LDFLAGS) $(test_OBJECTS) $(test_LDADD) $(LIBS)
testgrad: $(testgrad_OBJECTS) $(testgrad_DEPENDENCIES)
@rm -f testgrad
$(LINK) $(testgrad_LDFLAGS) $(testgrad_OBJECTS) $(testgrad_LDADD) $(LIBS)
testdraw: $(testdraw_OBJECTS) $(testdraw_DEPENDENCIES)
@rm -f testdraw
$(LINK) $(testdraw_LDFLAGS) $(testdraw_OBJECTS) $(testdraw_LDADD) $(LIBS)
view: $(view_OBJECTS) $(view_DEPENDENCIES)
@rm -f view
$(LINK) $(view_LDFLAGS) $(view_OBJECTS) $(view_LDADD) $(LIBS)
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(includedir)
@list='$(include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \
$(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
list='$(include_HEADERS)'; for p in $$list; do \
rm -f $(DESTDIR)$(includedir)/$$p; \
done
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
subdir = wrlib
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file; \
done
info:
dvi:
check: all
$(MAKE)
installcheck:
install-exec: install-libLIBRARIES
@$(NORMAL_INSTALL)
install-data: install-includeHEADERS
@$(NORMAL_INSTALL)
install: install-exec install-data all
@:
uninstall: uninstall-libLIBRARIES uninstall-includeHEADERS
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
installdirs:
$(mkinstalldirs) $(DATADIR)$(libdir) $(DATADIR)$(includedir)
mostlyclean-generic:
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-rm -f Makefile $(DISTCLEANFILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
mostlyclean: mostlyclean-libLIBRARIES mostlyclean-compile \
mostlyclean-noinstPROGRAMS mostlyclean-tags \
mostlyclean-generic
clean: clean-libLIBRARIES clean-compile clean-noinstPROGRAMS clean-tags \
clean-generic mostlyclean
distclean: distclean-libLIBRARIES distclean-compile \
distclean-noinstPROGRAMS distclean-tags \
distclean-generic clean
-rm -f config.status
maintainer-clean: maintainer-clean-libLIBRARIES \
maintainer-clean-compile \
maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
maintainer-clean-generic distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
.PHONY: mostlyclean-libLIBRARIES distclean-libLIBRARIES \
clean-libLIBRARIES maintainer-clean-libLIBRARIES uninstall-libLIBRARIES \
install-libLIBRARIES mostlyclean-compile distclean-compile \
clean-compile maintainer-clean-compile mostlyclean-noinstPROGRAMS \
distclean-noinstPROGRAMS clean-noinstPROGRAMS \
maintainer-clean-noinstPROGRAMS uninstall-includeHEADERS \
install-includeHEADERS tags mostlyclean-tags distclean-tags clean-tags \
maintainer-clean-tags distdir info dvi installcheck install-exec \
install-data install uninstall all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

0
wrlib/NEWS Normal file
View File

33
wrlib/README Normal file
View File

@@ -0,0 +1,33 @@
WindowMaker raster graphics library
This library is used to manipulate images and convert them to
a format that can be displayed through the X window system.
Read the wraster.h header for an idea of what is available
This Library is LGPL and
Copyright (c) Alfredo K. Kojima <kojima@inf.ufrgs.br>
The following environment variables control some parameters:
RIMAGE_CACHE <integer>
Is the maximum number of images to store in the internal cache.
Default is 8
RIMAGE_CACHE_SIZE <integer>
Is the size of the biggest image to store in the cache.
Default is 4k (64x64)
Porting
=======
It should be fairly easy to port it to other environments
(svgalib, libggi etc), probably only requiring wraster.h,
context.c and convert.c to be changed. Note that the X specific
code should be disabled in that case, including support for libXpm.

6
wrlib/TODO Normal file
View File

@@ -0,0 +1,6 @@
- support for other types of displays and convertion modes (currently only
supports PseudoColor and TrueColor in some depths)
- Gimp's xcf format?
- shared library version
- add clipping code to RCombineArea()
- remake and optimize converters

504
wrlib/alloca.c Normal file
View File

@@ -0,0 +1,504 @@
/* alloca.c -- allocate automatically reclaimed memory
(Mostly) portable public-domain implementation -- D A Gwyn
This implementation of the PWB library alloca function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
J.Otto Tennant <jot@cray.com> contributed the Cray support.
There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection. */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef emacs
#include "blockinput.h"
#endif
/* If compiling with GCC 2, this file's not needed. */
#if !defined (__GNUC__) || __GNUC__ < 2
/* If someone has defined alloca as a macro,
there must be some other way alloca is supposed to work. */
#ifndef alloca
#ifdef emacs
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs */
/* If your stack is a linked list of frames, you have to
provide an "address metric" ADDRESS_FUNCTION macro. */
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
long i00afunc ();
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
#else
#define ADDRESS_FUNCTION(arg) &(arg)
#endif
#if __STDC__
typedef void *pointer;
#else
typedef char *pointer;
#endif
#ifndef NULL
#define NULL 0
#endif
/* Different portions of Emacs need to call different versions of
malloc. The Emacs executable needs alloca to call xmalloc, because
ordinary malloc isn't protected from input signals. On the other
hand, the utilities in lib-src need alloca to call malloc; some of
them are very simple, and don't have an xmalloc routine.
Non-Emacs programs expect this to call use xmalloc.
Callers below should use malloc. */
#ifndef emacs
#define malloc xmalloc
#endif
extern pointer malloc ();
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* Direction unknown. */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
#else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
#define STACK_DIR stack_dir
static void
find_stack_direction ()
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
#endif /* STACK_DIRECTION == 0 */
/* An "alloca header" is used to:
(a) chain together all alloca'ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc
alignment chunk size. The following default should work okay. */
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* To force sizeof(header). */
struct
{
union hdr *next; /* For chaining headers. */
char *deep; /* For stack depth measure. */
} h;
} header;
static header *last_alloca_header = NULL; /* -> last alloca header. */
/* Return a pointer to at least SIZE bytes of storage,
which will be automatically reclaimed upon exit from
the procedure that called alloca. Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32. */
pointer
alloca (size)
unsigned size;
{
auto char probe; /* Probes stack depth: */
register char *depth = ADDRESS_FUNCTION (probe);
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* Unknown growth direction. */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca'd storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* Traverses linked list. */
#ifdef emacs
BLOCK_INPUT;
#endif
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free ((pointer) hp); /* Collect garbage. */
hp = np; /* -> next header. */
}
else
break; /* Rest are not deeper. */
last_alloca_header = hp; /* -> last valid storage. */
#ifdef emacs
UNBLOCK_INPUT;
#endif
}
if (size == 0)
return NULL; /* No allocation required. */
/* Allocate combined header + user data storage. */
{
register pointer new = malloc (sizeof (header) + size);
/* Address of header. */
if (new == 0)
abort();
((header *) new)->h.next = last_alloca_header;
((header *) new)->h.deep = depth;
last_alloca_header = (header *) new;
/* User storage begins just after header. */
return (pointer) ((char *) new + sizeof (header));
}
}
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
#ifdef DEBUG_I00AFUNC
#include <stdio.h>
#endif
#ifndef CRAY_STACK
#define CRAY_STACK
#ifndef CRAY2
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
struct stack_control_header
{
long shgrow:32; /* Number of times stack has grown. */
long shaseg:32; /* Size of increments to stack. */
long shhwm:32; /* High water mark of stack. */
long shsize:32; /* Current size of stack (all segments). */
};
/* The stack segment linkage control information occurs at
the high-address end of a stack segment. (The stack
grows from low addresses to high addresses.) The initial
part of the stack segment linkage control information is
0200 (octal) words. This provides for register storage
for the routine which overflows the stack. */
struct stack_segment_linkage
{
long ss[0200]; /* 0200 overflow words. */
long sssize:32; /* Number of words in this segment. */
long ssbase:32; /* Offset to stack base. */
long:32;
long sspseg:32; /* Offset to linkage control of previous
segment of stack. */
long:32;
long sstcpt:32; /* Pointer to task common address block. */
long sscsnm; /* Private control structure number for
microtasking. */
long ssusr1; /* Reserved for user. */
long ssusr2; /* Reserved for user. */
long sstpid; /* Process ID for pid based multi-tasking. */
long ssgvup; /* Pointer to multitasking thread giveup. */
long sscray[7]; /* Reserved for Cray Research. */
long ssa0;
long ssa1;
long ssa2;
long ssa3;
long ssa4;
long ssa5;
long ssa6;
long ssa7;
long sss0;
long sss1;
long sss2;
long sss3;
long sss4;
long sss5;
long sss6;
long sss7;
};
#else /* CRAY2 */
/* The following structure defines the vector of words
returned by the STKSTAT library routine. */
struct stk_stat
{
long now; /* Current total stack size. */
long maxc; /* Amount of contiguous space which would
be required to satisfy the maximum
stack demand to date. */
long high_water; /* Stack high-water mark. */
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
long hits; /* Number of internal buffer hits. */
long extends; /* Number of block extensions. */
long stko_mallocs; /* Block allocations by $STKOFEN. */
long underflows; /* Number of stack underflow calls ($STKRETN). */
long stko_free; /* Number of deallocations by $STKRETN. */
long stkm_free; /* Number of deallocations by $STKMRET. */
long segments; /* Current number of stack segments. */
long maxs; /* Maximum number of stack segments so far. */
long pad_size; /* Stack pad size. */
long current_address; /* Current stack segment address. */
long current_size; /* Current stack segment size. This
number is actually corrupted by STKSTAT to
include the fifteen word trailer area. */
long initial_address; /* Address of initial segment. */
long initial_size; /* Size of initial segment. */
};
/* The following structure describes the data structure which trails
any stack segment. I think that the description in 'asdef' is
out of date. I only describe the parts that I am sure about. */
struct stk_trailer
{
long this_address; /* Address of this block. */
long this_size; /* Size of this block (does not include
this trailer). */
long unknown2;
long unknown3;
long link; /* Address of trailer block of previous
segment. */
long unknown5;
long unknown6;
long unknown7;
long unknown8;
long unknown9;
long unknown10;
long unknown11;
long unknown12;
long unknown13;
long unknown14;
};
#endif /* CRAY2 */
#endif /* not CRAY_STACK */
#ifdef CRAY2
/* Determine a "stack measure" for an arbitrary ADDRESS.
I doubt that "lint" will like this much. */
static long
i00afunc (long *address)
{
struct stk_stat status;
struct stk_trailer *trailer;
long *block, size;
long result = 0;
/* We want to iterate through all of the segments. The first
step is to get the stack status structure. We could do this
more quickly and more directly, perhaps, by referencing the
$LM00 common block, but I know that this works. */
STKSTAT (&status);
/* Set up the iteration. */
trailer = (struct stk_trailer *) (status.current_address
+ status.current_size
- 15);
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
if (trailer == 0)
abort ();
/* Discard segments that do not contain our argument address. */
while (trailer != 0)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
if (block == 0 || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
break;
}
/* Set the result to the offset in this segment and add the sizes
of all predecessor segments. */
result = address - block;
if (trailer == 0)
{
return result;
}
do
{
if (trailer->this_size <= 0)
abort ();
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
while (trailer != 0);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
from subtracting the address of the first block. This is probably
not what you want. */
return (result);
}
#else /* not CRAY2 */
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Determine the number of the cell within the stack,
given the address of the cell. The purpose of this
routine is to linearize, in some sense, stack addresses
for alloca. */
static long
i00afunc (long address)
{
long stkl = 0;
long size, pseg, this_segment, stack;
long result = 0;
struct stack_segment_linkage *ssptr;
/* Register B67 contains the address of the end of the
current stack segment. If you (as a subprogram) store
your registers on the stack and find that you are past
the contents of B67, you have overflowed the segment.
B67 also points to the stack segment linkage control
area, which is what we are really interested in. */
stkl = CRAY_STACKSEG_END ();
ssptr = (struct stack_segment_linkage *) stkl;
/* If one subtracts 'size' from the end of the segment,
one has the address of the first word of the segment.
If this is not the first segment, 'pseg' will be
nonzero. */
pseg = ssptr->sspseg;
size = ssptr->sssize;
this_segment = stkl - size;
/* It is possible that calling this routine itself caused
a stack overflow. Discard stack segments which do not
contain the target address. */
while (!(this_segment <= address && address <= stkl))
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
#endif
if (pseg == 0)
break;
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
this_segment = stkl - size;
}
result = address - this_segment;
/* If you subtract pseg from the current end of the stack,
you get the address of the previous stack segment's end.
This seems a little convoluted to me, but I'll bet you save
a cycle somewhere. */
while (pseg != 0)
{
#ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o\n", pseg, size);
#endif
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
result += size;
}
return (result);
}
#endif /* not CRAY2 */
#endif /* CRAY */
#endif /* no alloca */
#endif /* not GCC version 2 */

BIN
wrlib/ballot_box.tiff Normal file

Binary file not shown.

906
wrlib/ballot_box.xpm Normal file
View File

@@ -0,0 +1,906 @@
/* XPM */
static char * ballot_box_xpm[] = {
"48 48 855 2",
" c None",
". c #B8B8B8",
"+ c #A0A0A0",
"@ c #4A2511",
"# c #A7A7A7",
"$ c #EDEDED",
"% c #EBE8E7",
"& c #A6948D",
"* c #904B22",
"= c #B4622D",
"- c #9F5427",
"; c #87431F",
"> c #4B2410",
", c #BFBFBF",
"' c #464646",
") c #818181",
"! c #D4D4D4",
"~ c #FEFEFE",
"{ c #E79860",
"] c #E38848",
"^ c #F4E2D5",
"/ c #F0E7E2",
"( c #C1804A",
"_ c #9B562B",
": c #7D3E1C",
"< c #8A8A8A",
"[ c #ECDEDF",
"} c #B68183",
"| c #E2E2E2",
"1 c #6A6A6A",
"2 c #686868",
"3 c #C6C6C6",
"4 c #F7F7F7",
"5 c #F5D6C1",
"6 c #E7C9B3",
"7 c #D1D1D1",
"8 c #FBFBFB",
"9 c #E7A966",
"0 c #E7AC69",
"a c #D79A5D",
"b c #B77642",
"c c #9B562C",
"d c #743819",
"e c #3E1C0C",
"f c #717171",
"g c #B4B4B4",
"h c #C1A7A8",
"i c #B37F80",
"j c #BC8E90",
"k c #797979",
"l c #343434",
"m c #E0E0E0",
"n c #DABFC0",
"o c #924345",
"p c #E3CFCF",
"q c #A46264",
"r c #D1B0B1",
"s c #91857C",
"t c #ABABAB",
"u c #EADBCA",
"v c #C98D54",
"w c #E7AA67",
"x c #E8AC69",
"y c #E8AD6B",
"z c #EAAF6C",
"A c #D99E61",
"B c #AD6E3E",
"C c #884723",
"D c #663015",
"E c #503C33",
"F c #565656",
"G c #7E7878",
"H c #978383",
"I c #E8E8E8",
"J c #DBDBDB",
"K c #5F5F5F",
"L c #444444",
"M c #343130",
"N c #EEEEEE",
"O c #BF9192",
"P c #C8A0A1",
"Q c #9B5254",
"R c #DDDDDD",
"S c #BDBDBD",
"T c #646464",
"U c #CEC3BA",
"V c #8D5730",
"W c #E6A865",
"X c #E2A466",
"Y c #EAB270",
"Z c #ECB472",
"` c #BC8450",
" . c #9A5C32",
".. c #763E20",
"+. c #4F3120",
"@. c #3A312C",
"#. c #5D5D5D",
"$. c #999999",
"%. c #2C2C2C",
"&. c #834D28",
"*. c #3D3834",
"=. c #C0C0C0",
"-. c #E1E1E1",
";. c #414141",
">. c #BBBBBB",
",. c #3B1407",
"'. c #2F2113",
"). c #764A2A",
"!. c #DFA061",
"~. c #E8AC6A",
"{. c #E9AE6B",
"]. c #EAB06D",
"^. c #EBB270",
"/. c #EDB673",
"(. c #D9A368",
"_. c #B17848",
":. c #8A4B27",
"<. c #470C06",
"[. c #4B220E",
"}. c #9D562A",
"|. c #CB7F43",
"1. c #D98D4C",
"2. c #AF7B4F",
"3. c #4F4F4F",
"4. c #D3C0C0",
"5. c #AB7D7E",
"6. c #C7C7C7",
"7. c #989898",
"8. c #535353",
"9. c #201714",
"0. c #8E8E8E",
"a. c #413531",
"b. c #B07042",
"c. c #E7AB68",
"d. c #EAB77D",
"e. c #ECB87E",
"f. c #EAB06E",
"g. c #EDB674",
"h. c #EEB877",
"i. c #F2C17E",
"j. c #D0B17B",
"k. c #693E29",
"l. c #34160A",
"m. c #854520",
"n. c #BB6F38",
"o. c #DC965F",
"p. c #E4AE81",
"q. c #F4E1D1",
"r. c #C4C4C4",
"s. c #333333",
"t. c #929292",
"u. c #DACDCD",
"v. c #A47071",
"w. c #7A7A7A",
"x. c #212121",
"y. c #252525",
"z. c #626262",
"A. c #CFD8D4",
"B. c #F4DABD",
"C. c #E9AF6C",
"D. c #EAB16F",
"E. c #EBB371",
"F. c #EDB875",
"G. c #F8D693",
"H. c #FCDD9A",
"I. c #E19151",
"J. c #3A1407",
"K. c #6B3316",
"L. c #B16532",
"M. c #D07F41",
"N. c #DC9A67",
"O. c #AEAEAE",
"P. c #9E9E9E",
"Q. c #9C9C9C",
"R. c #2F2F2F",
"S. c #8F8F8F",
"T. c #B0B0B0",
"U. c #9A9A9A",
"V. c #6D6D6D",
"W. c #363636",
"X. c #0F0F0F",
"Y. c #2D2D2D",
"Z. c #757575",
"`. c #A9ACAA",
" + c #91A59C",
".+ c #C0CBC6",
"++ c #637F72",
"@+ c #F0CAA1",
"#+ c #EEBB78",
"$+ c #FADA98",
"%+ c #F8D18E",
"&+ c #E58D48",
"*+ c #CB6830",
"=+ c #502510",
"-+ c #9B5328",
";+ c #C9773B",
">+ c #D27F40",
",+ c #D38141",
"'+ c #D48344",
")+ c #BF8253",
"!+ c #85532C",
"~+ c #361A0C",
"{+ c #686260",
"]+ c #CFCFCF",
"^+ c #5A5A5A",
"/+ c #1A1A1A",
"(+ c #5E5E5E",
"_+ c #5C5C5C",
":+ c #3A3A3A",
"<+ c #0D0D0D",
"[+ c #3E3E3E",
"}+ c #828282",
"|+ c #C4C7C6",
"1+ c #DFE4E2",
"2+ c #15402C",
"3+ c #A1B2AA",
"4+ c #F6E2CD",
"5+ c #EBB882",
"6+ c #EFBE7C",
"7+ c #FCE09D",
"8+ c #F2BC79",
"9+ c #D77334",
"0+ c #DF7D3A",
"a+ c #E07E3B",
"b+ c #8B4821",
"c+ c #BF6C34",
"d+ c #CE7A3D",
"e+ c #D07C3E",
"f+ c #D17E3F",
"g+ c #CA7A3E",
"h+ c #864722",
"i+ c #511F0C",
"j+ c #491909",
"k+ c #4B2211",
"l+ c #6C6360",
"m+ c #323232",
"n+ c #131313",
"o+ c #191919",
"p+ c #393939",
"q+ c #C9C9C9",
"r+ c #728C80",
"s+ c #967568",
"t+ c #66331A",
"u+ c #E6A965",
"v+ c #F4CB88",
"w+ c #FEE4A1",
"x+ c #E89F5D",
"y+ c #DC7736",
"z+ c #DD7937",
"A+ c #DE7A37",
"B+ c #D77536",
"C+ c #AF5F2C",
"D+ c #E2813C",
"E+ c #D77C3B",
"F+ c #CD783C",
"G+ c #CF7A3D",
"H+ c #CA793D",
"I+ c #B06733",
"J+ c #B26835",
"K+ c #815636",
"L+ c #1D1715",
"M+ c #1B0D08",
"N+ c #706F6F",
"O+ c #939393",
"P+ c #050505",
"Q+ c #040404",
"R+ c #000000",
"S+ c #0D0401",
"T+ c #1F0A03",
"U+ c #444140",
"V+ c #F7E6D6",
"W+ c #7A492D",
"X+ c #A96F3F",
"Y+ c #E6A966",
"Z+ c #F8D491",
"`+ c #F9D593",
" @ c #DF8748",
".@ c #DA7434",
"+@ c #DB7635",
"@@ c #DB7736",
"#@ c #D47234",
"$@ c #793E24",
"%@ c #361F1A",
"&@ c #4D1C0A",
"*@ c #783919",
"=@ c #D87A38",
"-@ c #D77B3B",
";@ c #CD773B",
">@ c #D07D3E",
",@ c #D27E40",
"'@ c #D38041",
")@ c #D48243",
"!@ c #D7894A",
"~@ c #B28E5F",
"{@ c #2A261D",
"]@ c #030100",
"^@ c #222121",
"/@ c #171717",
"(@ c #1B0F0B",
"_@ c #441708",
":@ c #57240E",
"<@ c #4D4743",
"[@ c #FCF7F3",
"}@ c #E5AA70",
"|@ c #E2A05E",
"1@ c #E8AE6B",
"2@ c #FADC99",
"3@ c #F3C685",
"4@ c #D87638",
"5@ c #D77132",
"6@ c #D87233",
"7@ c #D97334",
"8@ c #BF642D",
"9@ c #4F1F0D",
"0@ c #3A3432",
"a@ c #555555",
"b@ c #C1C1C1",
"c@ c #120000",
"d@ c #411608",
"e@ c #4D1B09",
"f@ c #5C260F",
"g@ c #A85A28",
"h@ c #D77A3A",
"i@ c #CC763A",
"j@ c #CE793C",
"k@ c #CF7B3D",
"l@ c #D07D3F",
"m@ c #D78849",
"n@ c #FBDD9B",
"o@ c #5F553C",
"p@ c #1F1F1F",
"q@ c #7D5737",
"r@ c #D79154",
"s@ c #DD9352",
"t@ c #804724",
"u@ c #733F21",
"v@ c #E3A66E",
"w@ c #E19C5B",
"x@ c #ECB876",
"y@ c #EBAE6F",
"z@ c #D46B30",
"A@ c #D56C30",
"B@ c #D66E31",
"C@ c #D77032",
"D@ c #994B20",
"E@ c #46190A",
"F@ c #312825",
"G@ c #6C6C6C",
"H@ c #D2D2D2",
"I@ c #B68F90",
"J@ c #D7BDBE",
"K@ c #060200",
"L@ c #331106",
"M@ c #8B3712",
"N@ c #68270D",
"O@ c #59240E",
"P@ c #A35829",
"Q@ c #CF7B3E",
"R@ c #D17D3F",
"S@ c #F1C584",
"T@ c #7F7250",
"U@ c #0D0804",
"V@ c #5E3C20",
"W@ c #B57642",
"X@ c #DA8E4D",
"Y@ c #DB8F4F",
"Z@ c #DC9150",
"`@ c #804725",
" # c #D58F51",
".# c #E19D5C",
"+# c #F2C886",
"@# c #FBDC99",
"## c #DD8D51",
"$# c #D1682E",
"%# c #D2692E",
"&# c #D36B2F",
"*# c #CC672E",
"=# c #7D3918",
"-# c #4D1A09",
";# c #290E05",
"># c #321A11",
",# c #3B3B3B",
"'# c #3D3D3D",
")# c #1E0A03",
"!# c #903A13",
"~# c #873511",
"{# c #63250C",
"]# c #693015",
"^# c #AC5F2E",
"/# c #CD783B",
"(# c #D38142",
"_# c #DD9656",
":# c #D68647",
"<# c #D88848",
"[# c #D88A49",
"}# c #D98C4C",
"|# c #DC9151",
"1# c #DD9453",
"2# c #E29F5E",
"3# c #F8D592",
"4# c #F4CB8A",
"5# c #D67B41",
"6# c #CD642C",
"7# c #CF662D",
"8# c #D0672E",
"9# c #C15F2A",
"0# c #632810",
"a# c #7D3817",
"b# c #C4642C",
"c# c #873F1A",
"d# c #7C2B0F",
"e# c #8D401A",
"f# c #290801",
"g# c #803310",
"h# c #823311",
"i# c #5A210B",
"j# c #6A3015",
"k# c #BC6C35",
"l# c #D37F40",
"m# c #D58344",
"n# c #D58445",
"o# c #D88948",
"p# c #D88B4A",
"q# c #DA8F4E",
"r# c #DB904F",
"s# c #E4A665",
"t# c #FCDF9C",
"u# c #EAB274",
"v# c #CD6831",
"w# c #CB612A",
"x# c #CC632B",
"y# c #AD5324",
"z# c #511D0B",
"A# c #763013",
"B# c #CB642C",
"C# c #C9612B",
"D# c #AC4A1E",
"E# c #9D4F22",
"F# c #1B0500",
"G# c #180902",
"H# c #50200A",
"I# c #7E3110",
"J# c #7B3D1C",
"K# c #BE6E36",
"L# c #D58546",
"M# c #D78748",
"N# c #D88949",
"O# c #D98B4A",
"P# c #ECB977",
"Q# c #DE975C",
"R# c #C75D27",
"S# c #C85F28",
"T# c #CA6029",
"U# c #93421C",
"V# c #622911",
"W# c #943412",
"X# c #BE5825",
"Y# c #D56E31",
"Z# c #A55525",
"`# c #310802",
" $ c #240601",
".$ c #150500",
"+$ c #200C03",
"@$ c #702D0E",
"#$ c #752D0F",
"$$ c #511D0A",
"%$ c #82401D",
"&$ c #C8773B",
"*$ c #D68546",
"=$ c #FADB99",
"-$ c #D27C44",
";$ c #C55B25",
">$ c #C65C26",
",$ c #C05B26",
"'$ c #793315",
")$ c #060606",
"!$ c #2E2E2E",
"~$ c #EEE1DB",
"{$ c #F8EBE4",
"]$ c #D5723B",
"^$ c #A45425",
"/$ c #260D04",
"($ c #2C0F05",
"_$ c #0C0501",
":$ c #070402",
"<$ c #3C1807",
"[$ c #883611",
"}$ c #8D4B24",
"|$ c #CA783C",
"1$ c #D58444",
"2$ c #DD9757",
"3$ c #F6D290",
"4$ c #F2C989",
"5$ c #C55F2B",
"6$ c #C25824",
"7$ c #C35925",
"8$ c #AF4F21",
"9$ c #60250E",
"0$ c #1C0A04",
"a$ c #0A0A0A",
"b$ c #87595A",
"c$ c #F2D8C9",
"d$ c #D0672D",
"e$ c #A35224",
"f$ c #0D0200",
"g$ c #0F0501",
"h$ c #282828",
"i$ c #070707",
"j$ c #0D0501",
"k$ c #56220B",
"l$ c #6C290E",
"m$ c #9B5126",
"n$ c #E4A766",
"o$ c #FBDE9B",
"p$ c #E5AD71",
"q$ c #BE5322",
"r$ c #BF5523",
"s$ c #C15623",
"t$ c #9D451C",
"u$ c #4C1B0A",
"v$ c #100704",
"w$ c #3F2C2C",
"x$ c #AB9898",
"y$ c #EAE3E3",
"z$ c #F7EAE3",
"A$ c #CE662D",
"B$ c #A25123",
"C$ c #878787",
"D$ c #7F7F7F",
"E$ c #DFDFDF",
"F$ c #425F51",
"G$ c #3E4F47",
"H$ c #121212",
"I$ c #1F0C03",
"J$ c #58210D",
"K$ c #DEB67D",
"L$ c #D38750",
"M$ c #BB5020",
"N$ c #BC5221",
"O$ c #853816",
"P$ c #3F1507",
"Q$ c #0A0402",
"R$ c #0E0E0E",
"S$ c #616161",
"T$ c #B69C9D",
"U$ c #893336",
"V$ c #DB926C",
"W$ c #7C3617",
"X$ c #EAEDEB",
"Y$ c #ACB7B2",
"Z$ c #8E9994",
"`$ c #424E48",
" % c #595959",
".% c #130602",
"+% c #100601",
"@% c #401907",
"#% c #9F411D",
"$% c #B84D1E",
"%% c #B94F1F",
"&% c #B54E20",
"*% c #6D2B10",
"=% c #160702",
"-% c #554338",
";% c #787878",
">% c #382B24",
",% c #97481F",
"'% c #C55F29",
")% c #723114",
"!% c #230B02",
"~% c #302A28",
"{% c #C2C0BE",
"]% c #EEF1F0",
"^% c #A1AFA8",
"/% c #C4CAC7",
"(% c #585858",
"_% c #280D05",
":% c #361207",
"<% c #401708",
"[% c #280F04",
"}% c #551F09",
"|% c #9A3E18",
"1% c #B74C1D",
"2% c #A4451B",
"3% c #5E230D",
"4% c #742E12",
"5% c #963714",
"6% c #883111",
"7% c #77290E",
"8% c #983814",
"9% c #9A3814",
"0% c #91421B",
"a% c #C96029",
"b% c #C25C28",
"c% c #5E250E",
"d% c #1F0A02",
"e% c #0A0200",
"f% c #311205",
"g% c #B8A8A2",
"h% c #82998E",
"i% c #CECECE",
"j% c #140602",
"k% c #3F1608",
"l% c #712B0F",
"m% c #833311",
"n% c #57210B",
"o% c #170802",
"p% c #250C03",
"q% c #6B250C",
"r% c #993D17",
"s% c #B54A1D",
"t% c #A2421A",
"u% c #873615",
"v% c #9D411A",
"w% c #B95020",
"x% c #BB5121",
"y% c #A9441A",
"z% c #9C3A15",
"A% c #C05723",
"B% c #C45B25",
"C% c #C75C27",
"D% c #B05122",
"E% c #55200C",
"F% c #160701",
"G% c #9E8075",
"H% c #BEBEBE",
"I% c #371307",
"J% c #6A280D",
"K% c #813211",
"L% c #803111",
"M% c #7F3111",
"N% c #7E3011",
"O% c #762D0F",
"P% c #451A08",
"Q% c #360B03",
"R% c #7C240B",
"S% c #481808",
"T% c #983C17",
"U% c #782E11",
"V% c #B74D1E",
"W% c #BD5322",
"X% c #B44C1E",
"Y% c #B84F20",
"Z% c #C35924",
"`% c #C45A25",
" & c #AE4F20",
".& c #461909",
"+& c #130600",
"@& c #2D1105",
"#& c #66260D",
"$& c #703D2A",
"%& c #8F7165",
"&& c #6E341C",
"*& c #7D3010",
"=& c #7C3010",
"-& c #7B2F10",
";& c #7A2F10",
">& c #792E10",
",& c #782E10",
"'& c #6A280E",
")& c #2F1205",
"!& c #331206",
"~& c #541E0B",
"{& c #843313",
"]& c #AE451A",
"^& c #B1471B",
"/& c #BF5422",
"(& c #9C451C",
"_& c #867872",
":& c #A68574",
"<& c #3F1B0F",
"[& c #0C0300",
"}& c #2C1005",
"|& c #501D0A",
"1& c #772D10",
"2& c #752C0F",
"3& c #742C0F",
"4& c #6F2A0E",
"5& c #722B0F",
"6& c #511E0A",
"7& c #6E270E",
"8& c #A93F18",
"9& c #B0461B",
"0& c #B4491C",
"a& c #B54A1C",
"b& c #BC5121",
"c& c #9A431B",
"d& c #3B3431",
"e& c #E9E9E9",
"f& c #838181",
"g& c #260400",
"h& c #6B280E",
"i& c #732B0F",
"j& c #712A0F",
"k& c #702A0F",
"l& c #6F2A0F",
"m& c #6E290E",
"n& c #5C220C",
"o& c #3D1407",
"p& c #832F11",
"q& c #AD4419",
"r& c #AF451A",
"s& c #B2481B",
"t& c #B84E1F",
"u& c #8C3C18",
"v& c #CACACA",
"w& c #454545",
"x& c #371506",
"y& c #702A0E",
"z& c #6D290E",
"A& c #6C280E",
"B& c #6A270E",
"C& c #69270E",
"D& c #3E1507",
"E& c #8B3413",
"F& c #AE431A",
"G& c #B1461B",
"H& c #B5491C",
"I& c #893816",
"J& c #452B1F",
"K& c #A3A3A3",
"L& c #DEDEE1",
"M& c #E6E6E6",
"N& c #0F0000",
"O& c #090300",
"P& c #160801",
"Q& c #531F0A",
"R& c #461A09",
"S& c #545454",
"T& c #724C3D",
"U& c #68260E",
"V& c #67260D",
"W& c #66250D",
"X& c #65250D",
"Y& c #3D1507",
"Z& c #863213",
"`& c #AC4119",
" * c #B0461A",
".* c #863514",
"+* c #53382D",
"@* c #959595",
"#* c #C6C6C9",
"$* c #4D4F60",
"%* c #7F808D",
"&* c #404154",
"** c #CECED3",
"=* c #BEBFC5",
"-* c #040100",
";* c #0E0500",
">* c #270E04",
",* c #382F2C",
"'* c #6B4638",
")* c #64250D",
"!* c #63240D",
"~* c #62230D",
"{* c #401608",
"]* c #722A0F",
"^* c #AB4018",
"/* c #AD421A",
"(* c #AF441A",
"_* c #7E3B20",
":* c #D3D1D1",
"<* c #ECECEC",
"[* c #5F6170",
"}* c #EEEEEF",
"|* c #303246",
"1* c #969696",
"2* c #CCCCCC",
"3* c #5B3324",
"4* c #61230C",
"5* c #60230C",
"6* c #5F230C",
"7* c #5E220C",
"8* c #70290F",
"9* c #AA3F18",
"0* c #973916",
"a* c #301006",
"b* c #312117",
"c* c #31302F",
"d* c #CDCDCD",
"e* c #8F909B",
"f* c #1E1E1E",
"g* c #D2D2D1",
"h* c #696969",
"i* c #583224",
"j* c #5E220B",
"k* c #5D220B",
"l* c #5C210B",
"m* c #6E280F",
"n* c #A83E17",
"o* c #A43E18",
"p* c #561E0C",
"q* c #2B0E05",
"r* c #505162",
"s* c #9F9FA9",
"t* c #BCBDC3",
"u* c #D6D6D6",
"v* c #9D9D9D",
"w* c #737373",
"x* c #694F45",
"y* c #5B200B",
"z* c #5A200B",
"A* c #591F0B",
"B* c #581F0A",
"C* c #381306",
"D* c #6D270E",
"E* c #A63D17",
"F* c #993915",
"G* c #240500",
"H* c #AEAFB7",
"I* c #F0F0F0",
"J* c #575757",
"K* c #CCCCD1",
"L* c #D8D7D7",
"M* c #A49590",
"N* c #561E0A",
"O* c #551D0A",
"P* c #351206",
"Q* c #6B260E",
"R* c #A53C16",
"S* c #903514",
"T* c #8E8E96",
"U* c #9B9BA0",
"V* c #F5F5F5",
"W* c #342721",
"X* c #290E04",
"Y* c #4F1B09",
"Z* c #521C0A",
"`* c #511C09",
" = c #69250D",
".= c #A33B15",
"+= c #822F11",
"@= c #1D0200",
"#= c #838383",
"$= c #6F707E",
"%= c #030000",
"&= c #0B0400",
"*= c #140701",
"== c #3B1406",
"-= c #4E1A09",
";= c #311005",
">= c #68240C",
",= c #802D10",
"'= c #050100",
")= c #919191",
"!= c #010000",
"~= c #0A0300",
"{= c #1D0A02",
"]= c #270D04",
"^= c #351005",
"/= c #100000",
"(= c #111111",
"_= c #0E0501",
":= c #0E0400",
"<= c #070000",
"[= c #909090",
" ",
" . + @ ",
" # $ % & * = - ; > , # ' ",
" ) ! ~ ~ ~ ~ { ] ^ / ( _ : > < [ } | + 1 1 ' ' ",
" 2 3 4 ~ ~ ~ ~ ~ 5 6 7 8 9 0 a b c d e f g h i j ~ ~ 4 3 k ",
" l m ~ n o p q r ~ 4 s t u v w x y z A B C D E F G H 7 I J K L ",
" M N O P Q [ ~ I R S T U V W w x y X Y Z ` ...+.@.#.$.%. ",
" D &.*.N p r ~ I J =.-.;.>.,.'.).!.~.{.].^.Z /.(._.:...<. ",
" [.}.|.1.2.3.~ [ 4.5.7 6.7.8.f 9.0.a.b.c.d.e.f.^.Z g.h.i.j.k. ",
" l.m.n.o.p.q.r.s.t.u.v.R S w.L x.y.z.! ~ ~ A.~ B.C.D.E.F.G.H.I.J. ",
" K.L.M.N.O.P.N 4 Q.R.S.T.U.V.W.X.Y.Z.`. +.+++ +~ @+y z #+$+%+&+*+J. ",
" =+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+++1+2+3+4+5+w x 6+7+8+9+0+a+J. ",
" l.b+c+d+e+f+>+g+h+i+j+k+l+r.m+n+l o+p+(+q+~ ~ r+A.s+j+t+u+v+w+x+y+z+A+B+J. ",
" K.C+D+E+F+G+e+f+H+I+J+K+L+M+N+O+P+Q+X.R+S+T+U+N ~ V+W+X+Y+Z+`+ @.@+@@@#@$@%@ ' ' ' ",
" &@*@=@D+-@;@F+G+>@,@'@)@!@~@{@]@^@/@Q+R+(@_@j+:@<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@| | t.",
" c@d@e@f@g@h@i@;@j@k@l@,@'@m@n@o@R+]@p@X.q@r@s@t@j+u@v@w@x@w+y@z@A@B@C@D@E@F@G@H@I@J@| ' ",
" K@L@M@N@j+O@P@i@;@j@Q@R@,@'@m@S@T@U@V@W@X@Y@Z@s@`@ #.#+#@###$#%#&#*#=#-#;#>#F ,#'#R+x. ",
" K@)#!#!#~#{#j+]#^#/#j@e+f+>+(#'+_#:#<#[#}#X@Y@|#1#2#3#4#5#6#7#8#9#0#a#b#c#d#e#L@ ",
" K@f#g#!#!#!#h#i#j+j#k#d+e+f+l#(#m#n#:#o#p#1.q#r#s#t#u#v#w#x#6#y#z#A#B#C#B@D#E#J. ",
" c@F#G#H#!#!#!#!#I#i#j+J#K#e+f+'@)@m#L#M#N#O#1.P#w+Q#R#S#T#w#U#,.V#W#X#&#A@Y#Z#J. ",
" `# $.$+$@$!#!#!#!##$$$j+%$&$,@'@)@m#*$M#q#+#=$-$;$>$R#,$'$;#)$!$~${$]$&#A@^$J. ",
" `#/$($_$:$<$[$!#!#!#!##$$$i+}$|$'@)@1$2$3$4$5$6$7$;$8$9$0$a$W.b$N c$d$%#&#e$J. ",
" f$g$_+#.h$i$j$k$!#!#!#!#M@l$e@i+m$R@n$o$p$q$r$s$6$t$u$v$X.w$x$y$z$6#A$d$%#B$J. ",
" C$D$0.N E$F$G$p+n+H$I$@$!#!#!#!#M@l$j+J$K$L$M$N$q$r$O$P$Q$R$S$T$U$~ V$x#6#A$d$W$($ ",
" k . 4 ~ X$Y$Z$`$ %L .%+%@%[$!#!#!#!#~#j+#%$%%%M$&%*%P$=%,.-%F ;%D$>%,%w#x#'%)%!% ",
" ~%{%]%++^%/%(%_%:%<%[%G#}%!#!#!#!#j+|%1%$%2%3%4%5%6%7%W#8%9%0%R#S#a%b%c%d% ",
" e%f%g%~ h%i%j%:%k%l%m%n%o%p%q%!#!#j+r%s%t%u%v%M$w%x%y%8%z%A%B%>$C%D%E%F% ",
" e%/$:%G%1+H%I%J%K%L%M%N%O%P%+%Q%R%S%T%U%U%1%V%%%M$N$W%X%Y%6$Z%`% &.&+& ",
" K@@&#&J.$&%&&&N%*&=&-&;&>&,&'&)&.$!&~&{&]&^&1%V%%%M$N$W%/&(&_&:&<&[& ",
" K@}&M%l%|&|&#&;&>&,&1&O%2&3&4&5&6&L@7&8&9&0&a&1%V%%%M$b&c&d&T.e&f&' ",
" g&-&;&>&3&h&O%2&3&i&5&j&k&l&m&n&o&p&q&r&s&0&a&1%V%t&u&d&# E$~ R v&< S$w& ",
" +%x&y&2&3&i&h&j&k&l&m&z&A&h&B&C&D&E&F&r&G&s&0&H&I&J&p+K&-.8 L&~ ~ ~ M&| 3 . $.1 ",
" N&O&P&Q&k&R&S&T&A&h&B&C&U&V&W&X&Y&Z&`&F&r& *.*+*S&@*q+#*$*%*&***=*~ ~ ~ ~ ~ ~ S. ",
" R+R+-*;*>*,*@*}+'*V&W&X&)*!*!*~*{*]*^*`&/*(*_*m+. :*<*[*%*&*=*&*L&}*|*~ ~ ~ ! ",
" R+R+R+f$1*2*O+Z.3*!*~*4*5*6*7*Y&8*9*^*`&0*:%a*b*c*d*=*e*=*&*}*}*&***~ ~ 4 f ",
" R+R+f*8 g*2*7.h*i*7*j*k*l*l*J.m*n*9*^*o*p*q*[&R+R+D$~ r*}*~ [*s*~ ~ ~ , ",
" R+f*i%L&t*-.u*v*w*x*y*z*A*B*C*D*E*n*9*F*_@G*R+R+R+R+!$i%~ e*e*H*~ ~ I*J* ",
" R+R+R+R$3.0.~ ~ }*&*K*-.u*L*M*-#N*O*O*P*Q*R*E*S*_@[& R+R+R+R+D$~ %*s*~ 4 $. ",
" l | ~ ~ ~ ~ ~ ~ T*%*L&&*U*-.V*W*X*Y*Z*`*L@ =.=+=J.@= R+R+R+!$i%~ e&$. ",
" i$#=I*~ e***~ =***=*[*H*$=8 K&%=&=*===-=;=>=,=L@'= R+R+R$)=w. ",
" R+o+$.4 }*$=s*L&&*[*s*s*~ ! l R+R+!=~={=]=C*^=/= R+R+(= ",
" R+R+l # $ ~ s*$=L&s*L&~ e&K R+R+R+R+_=:=<= ",
" R+R+s.[=e&~ **e*~ ~ | ) R+R+R+ ",
" R+R+i$3.! ~ d*4 , ' ",
" R+R+s.# J ) o+ ",
" R+R+X.'# ",
" ",
" "};

134
wrlib/color.c Normal file
View File

@@ -0,0 +1,134 @@
/* color.c - color stuff (rgb -> hsv convertion etc.)
*
* Raster graphics library
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <assert.h>
#include "wraster.h"
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
#define MIN3(a,b,c) MIN(MIN(a,b), c)
#define MAX3(a,b,c) MAX(MAX(a,b), c)
void
RHSVtoRGB(RHSVColor *hsv, RColor *rgb)
{
int h = hsv->hue % 360;
int s = hsv->saturation;
int v = hsv->value;
int i, f;
int p, q, t;
if (s == 0) {
rgb->red = rgb->green = rgb->blue = v;
return;
}
i = h / 60;
f = h % 60;
p = v * (255 - s) / 255;
q = v * (255 - s * f / 60) / 255;
t = v * (255 - s * (60 - f) / 60) / 255;
switch (i) {
case 0:
rgb->red = v;
rgb->green = t;
rgb->blue = p;
break;
case 1:
rgb->red = q;
rgb->green = v;
rgb->blue = p;
break;
case 2:
rgb->red = p;
rgb->green = v;
rgb->blue = t;
break;
case 3:
rgb->red = p;
rgb->green = q;
rgb->blue = v;
break;
case 4:
rgb->red = t;
rgb->green = p;
rgb->blue = v;
break;
case 5:
rgb->red = v;
rgb->green = p;
rgb->blue = q;
break;
}
}
void
RRGBtoHSV(RColor *rgb, RHSVColor *hsv)
{
int h, s, v;
int max = MAX3(rgb->red, rgb->green, rgb->blue);
int min = MIN3(rgb->red, rgb->green, rgb->blue);
v = max;
if (max == 0)
s = 0;
else
s = (max - min) * 255 / max;
if (s == 0)
h = 0;
else {
int rc, gc, bc;
rc = (max - rgb->red) * 255 / (max - min);
gc = (max - rgb->green) * 255 / (max - min);
bc = (max - rgb->blue) * 255 / (max - min);
if (rgb->red == max) {
h = ((bc - gc) * 60 / 255);
} else if (rgb->green == max) {
h = 2*60 + ((rc - bc) * 60 / 255);
} else {
h = 4*60 + ((gc - rc) * 60 / 255);
}
if (h < 0)
h += 360;
}
hsv->hue = h;
hsv->saturation = s;
hsv->value = v;
}

105
wrlib/configure.in Normal file
View File

@@ -0,0 +1,105 @@
dnl
dnl autoconf input for WRaster library
dnl
AC_INIT(raster.c)
AM_INIT_AUTOMAKE(wrlib, 0.3)
CFLAGS="$CFLAGS -O2"
dnl Checks for programs.
dnl ===================
AC_PROG_CC
AC_PROG_MAKE_SET
AC_PROG_RANLIB
AC_PROG_INSTALL
dnl Checks for library functions.
dnl ============================
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_FUNC_ALLOCA
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_PATH_XTRA
XCFLAGS="$X_CFLAGS"
_XLIBS="$X_LIBS $X_EXTRA_LIBS -lX11"
XLIBS="$X_EXTRA_LIBS -lX11"
XLFLAGS=$X_LIBS
AC_SUBST(XCFLAGS)
AC_SUBST(XLFLAGS)
dnl Pixmap Support
dnl ==============
xpm=yes
AC_ARG_ENABLE(xpm,
[ --disable-xpm disable XPM support through libXpm],
xpm=$enableval, xpm=yes)
GFXFLAGS=""
GFXLIBS=""
if test "$xpm" = yes; then
AC_CHECK_LIB(Xpm, XpmCreatePixmapFromData,
[GFXFLAGS=-DUSE_XPM GFXLIBS=-lXpm], ,$_XLIBS)
fi
dnl test for zlib
dnl =============
AC_CHECK_LIB(z, gzread, zlib=yes, zlib=no)
dnl PNG Support
dnl ===========
png=yes
AC_ARG_ENABLE(png,
[ --disable-png disable PNG support through libpng],
png=$enableval, png=yes)
if test "$png" = yes; then
if test "$zlib" = yes; then
AC_CHECK_LIB(png, png_get_valid, [GFXFLAGS="$GFXFLAGS -DUSE_PNG"
GFXLIBS="$GFXLIBS -lpng -lz"], , -lz -lm)
fi
fi
dnl TIFF Support
dnl ============
tif=yes
AC_ARG_ENABLE(tif,
[ --disable-tiff disable use of TIFF images through libtiff],
tif=$enableval, tif=yes)
if test "$tif" = yes; then
AC_CHECK_LIB(tiff, TIFFGetVersion,
[GFXFLAGS="$GFXFLAGS -DUSE_TIFF" GFXLIBS="$GFXLIBS -ltiff"],, -lm)
fi
AC_SUBST(GFXFLAGS)
AC_SUBST(GFXLIBS)
AC_SUBST(XLIBS)
if test "${prefix}" = "NONE"; then
prefix="/usr/local"
fi
if test "${exec_prefix}" = "NONE"; then
exec_prefix=$prefix
fi
AC_C_CONST
AC_OUTPUT(Makefile config.h)

557
wrlib/context.c Normal file
View File

@@ -0,0 +1,557 @@
/* context.c - X context management
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "wraster.h"
static Bool bestContext(Display *dpy, int screen_number, RContext *context);
static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
RC_UseSharedMemory|RC_RenderMode|RC_ColorsPerChannel, /* flags */
RM_DITHER, /* render_mode */
4, /* colors_per_channel */
0,
0,
0,
0,
True /* use_shared_memory */
};
static XColor*
allocatePseudoColor(RContext *ctx)
{
XColor *colors;
XColor avcolors[256];
int avncolors;
int i, ncolors, r, g, b;
int retries;
int cpc = ctx->attribs->colors_per_channel;
ncolors = cpc * cpc * cpc;
if ( ncolors > (1<<ctx->depth) ) {
/* reduce colormap size */
cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
ncolors = cpc * cpc * cpc;
}
if (cpc < 2 || ncolors > (1<<ctx->depth)) {
sprintf(RErrorString, "invalid colormap size %i", cpc);
return NULL;
}
colors = malloc(sizeof(XColor)*ncolors);
if (!colors) {
sprintf(RErrorString, "out of memory");
return NULL;
}
i=0;
if ((ctx->attribs->flags & RC_GammaCorrection) && ctx->attribs->rgamma > 0
&& ctx->attribs->ggamma > 0 && ctx->attribs->bgamma > 0) {
double rg, gg, bg;
double tmp;
/* do gamma correction */
rg = 1.0/ctx->attribs->rgamma;
gg = 1.0/ctx->attribs->ggamma;
bg = 1.0/ctx->attribs->bgamma;
for (r=0; r<cpc; r++) {
for (g=0; g<cpc; g++) {
for (b=0; b<cpc; b++) {
colors[i].red=(r*0xffff) / (cpc-1);
colors[i].green=(g*0xffff) / (cpc-1);
colors[i].blue=(b*0xffff) / (cpc-1);
colors[i].flags = DoRed|DoGreen|DoBlue;
tmp = (double)colors[i].red / 65536.0;
colors[i].red = (unsigned short)(65536.0*pow(tmp, rg));
tmp = (double)colors[i].green / 65536.0;
colors[i].green = (unsigned short)(65536.0*pow(tmp, gg));
tmp = (double)colors[i].blue / 65536.0;
colors[i].blue = (unsigned short)(65536.0*pow(tmp, bg));
i++;
}
}
}
} else {
for (r=0; r<cpc; r++) {
for (g=0; g<cpc; g++) {
for (b=0; b<cpc; b++) {
colors[i].red=(r*0xffff) / (cpc-1);
colors[i].green=(g*0xffff) / (cpc-1);
colors[i].blue=(b*0xffff) / (cpc-1);
colors[i].flags = DoRed|DoGreen|DoBlue;
i++;
}
}
}
}
/* try to allocate the colors */
for (i=0; i<ncolors; i++) {
if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
colors[i].flags = 0; /* failed */
} else {
colors[i].flags = DoRed|DoGreen|DoBlue;
}
}
/* try to allocate close values for the colors that couldn't
* be allocated before */
avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
for (i=0; i<ncolors; i++) {
if (colors[i].flags==0) {
int j;
unsigned long cdiff=0xffffffff, diff;
unsigned long closest=0;
retries = 2;
while (retries--) {
/* find closest color */
for (j=0; j<avncolors; j++) {
r = (colors[i].red - avcolors[i].red)>>8;
g = (colors[i].green - avcolors[i].green)>>8;
b = (colors[i].blue - avcolors[i].blue)>>8;
diff = r*r + g*g + b*b;
if (diff<cdiff) {
cdiff = diff;
closest = j;
}
}
/* allocate closest color found */
colors[i].red = avcolors[closest].red;
colors[i].green = avcolors[closest].green;
colors[i].blue = avcolors[closest].blue;
if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
colors[i].flags = DoRed|DoGreen|DoBlue;
break; /* succeeded, don't need to retry */
}
#ifdef DEBUG
printf("close color allocation failed. Retrying...\n");
#endif
}
}
}
return colors;
}
static XColor*
allocateGrayScale(RContext *ctx)
{
XColor *colors;
XColor avcolors[256];
int avncolors;
int i, ncolors, r, g, b;
int retries;
int cpc = ctx->attribs->colors_per_channel;
ncolors = cpc * cpc * cpc;
if (ctx->vclass == StaticGray) {
/* we might as well use all grays */
ncolors = 1<<ctx->depth;
} else {
if ( ncolors > (1<<ctx->depth) ) {
/* reduce colormap size */
cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
ncolors = cpc * cpc * cpc;
}
if (cpc < 2 || ncolors > (1<<ctx->depth)) {
sprintf(RErrorString, "invalid colormap size %i", cpc);
return NULL;
}
}
if (ncolors>=256 && ctx->vclass==StaticGray) {
/* don't need dithering for 256 levels of gray in StaticGray visual */
ctx->attribs->render_mode = RM_MATCH;
}
colors = malloc(sizeof(XColor)*ncolors);
if (!colors) {
sprintf(RErrorString, "out of memory");
return False;
}
for (i=0; i<ncolors; i++) {
colors[i].red=(i*0xffff) / (ncolors-1);
colors[i].green=(i*0xffff) / (ncolors-1);
colors[i].blue=(i*0xffff) / (ncolors-1);
colors[i].flags = DoRed|DoGreen|DoBlue;
}
/* try to allocate the colors */
for (i=0; i<ncolors; i++) {
#ifdef DEBUG
printf("trying:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
#endif
if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
colors[i].flags = 0; /* failed */
#ifdef DEBUG
printf("failed:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
#endif
} else {
colors[i].flags = DoRed|DoGreen|DoBlue;
#ifdef DEBUG
printf("success:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
#endif
}
}
/* try to allocate close values for the colors that couldn't
* be allocated before */
avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
for (i=0; i<ncolors; i++) {
if (colors[i].flags==0) {
int j;
unsigned long cdiff=0xffffffff, diff;
unsigned long closest=0;
retries = 2;
while (retries--) {
/* find closest color */
for (j=0; j<avncolors; j++) {
r = (colors[i].red - avcolors[i].red)>>8;
g = (colors[i].green - avcolors[i].green)>>8;
b = (colors[i].blue - avcolors[i].blue)>>8;
diff = r*r + g*g + b*b;
if (diff<cdiff) {
cdiff = diff;
closest = j;
}
}
/* allocate closest color found */
#ifdef DEBUG
printf("best match:%x,%x,%x => %x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue,avcolors[closest].red,avcolors[closest].green,avcolors[closest].blue);
#endif
colors[i].red = avcolors[closest].red;
colors[i].green = avcolors[closest].green;
colors[i].blue = avcolors[closest].blue;
if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
colors[i].flags = DoRed|DoGreen|DoBlue;
break; /* succeeded, don't need to retry */
}
#ifdef DEBUG
printf("close color allocation failed. Retrying...\n");
#endif
}
}
}
return colors;
}
static char*
mygetenv(char *var, int scr)
{
char *p;
char varname[64];
if (scr==0) {
p = getenv(var);
}
if (scr!=0 || !p) {
sprintf(varname, "%s%i", var, scr);
p = getenv(var);
}
return p;
}
static void
gatherconfig(RContext *context, int screen_n)
{
char *ptr;
ptr = mygetenv("WRASTER_GAMMA", screen_n);
if (ptr) {
float g1,g2,g3;
if (sscanf(ptr, "%f/%f/%f", &g1, &g2, &g3)!=3
|| g1<=0.0 || g2<=0.0 || g3<=0.0) {
printf("wrlib: invalid value(s) for gamma correction \"%s\"\n",
ptr);
} else {
context->attribs->flags |= RC_GammaCorrection;
context->attribs->rgamma = g1;
context->attribs->ggamma = g2;
context->attribs->bgamma = g3;
}
}
}
static void
getColormap(RContext *context, int screen_number)
{
Colormap cmap = None;
XStandardColormap *cmaps;
int ncmaps, i;
if (XGetRGBColormaps(context->dpy,
RootWindow(context->dpy, screen_number),
&cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) {
for (i=0; i<ncmaps; ++i) {
if (cmaps[i].visualid == context->visual->visualid) {
cmap = cmaps[i].colormap;
break;
}
}
XFree(cmaps);
}
if (cmap == None) {
XColor color;
cmap = XCreateColormap(context->dpy,
RootWindow(context->dpy, screen_number),
context->visual, AllocNone);
color.red = color.green = color.blue = 0;
XAllocColor(context->dpy, cmap, &color);
context->black = color.pixel;
color.red = color.green = color.blue = 0xffff;
XAllocColor(context->dpy, cmap, &color);
context->white = color.pixel;
}
context->cmap = cmap;
}
static int
count_offset(unsigned long mask)
{
int i;
i=0;
while ((mask & 1)==0) {
i++;
mask = mask >> 1;
}
return i;
}
RContext*
RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
{
RContext *context;
XGCValues gcv;
RErrorString[0]=0;
context = malloc(sizeof(RContext));
if (!context) {
sprintf(RErrorString, "out of memory");
return NULL;
}
memset(context, 0, sizeof(RContext));
context->dpy = dpy;
context->screen_number = screen_number;
context->attribs = malloc(sizeof(RContextAttributes));
if (!context->attribs) {
free(context);
sprintf(RErrorString, "out of memory");
return NULL;
}
if (!attribs)
*context->attribs = DEFAULT_CONTEXT_ATTRIBS;
else
*context->attribs = *attribs;
/* get configuration from environment variables */
gatherconfig(context, screen_number);
if ((context->attribs->flags & RC_VisualID)) {
XVisualInfo *vinfo, templ;
int nret;
templ.screen = screen_number;
templ.visualid = context->attribs->visualid;
vinfo = XGetVisualInfo(context->dpy, VisualIDMask|VisualScreenMask,
&templ, &nret);
if (!vinfo || nret==0) {
sprintf(RErrorString, "invalid visual id %x\n",
(unsigned int)context->attribs->visualid);
} else {
if (vinfo[0].visual == DefaultVisual(dpy, screen_number)) {
context->attribs->flags |= RC_DefaultVisual;
} else {
XSetWindowAttributes attr;
unsigned long mask;
context->visual = vinfo[0].visual;
context->depth = vinfo[0].depth;
context->vclass = vinfo[0].class;
getColormap(context, screen_number);
attr.colormap = context->cmap;
attr.override_redirect = True;
attr.border_pixel = 0;
attr.background_pixel = 0;
mask = CWBorderPixel|CWColormap|CWOverrideRedirect|CWBackPixel;
context->drawable =
XCreateWindow(dpy, RootWindow(dpy, screen_number), 1, 1,
1, 1, 0, context->depth, CopyFromParent,
context->visual, mask, &attr);
/* XSetWindowColormap(dpy, context->drawable, attr.colormap);*/
}
XFree(vinfo);
}
}
/* use default */
if (!context->visual) {
if ((context->attribs->flags & RC_DefaultVisual)
|| !bestContext(dpy, screen_number, context)) {
context->visual = DefaultVisual(dpy, screen_number);
context->depth = DefaultDepth(dpy, screen_number);
context->cmap = DefaultColormap(dpy, screen_number);
context->drawable = RootWindow(dpy, screen_number);
context->black = BlackPixel(dpy, screen_number);
context->white = WhitePixel(dpy, screen_number);
context->vclass = context->visual->class;
}
}
gcv.function = GXcopy;
gcv.graphics_exposures = False;
context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction
|GCGraphicsExposures, &gcv);
if (context->vclass == PseudoColor || context->vclass == StaticColor) {
context->colors = allocatePseudoColor(context);
if (!context->colors) {
return NULL;
}
} else if (context->vclass == GrayScale || context->vclass == StaticGray) {
context->colors = allocateGrayScale(context);
if (!context->colors) {
return NULL;
}
} else if (context->vclass == TrueColor) {
/* calc offsets to create a TrueColor pixel */
context->red_offset = count_offset(context->visual->red_mask);
context->green_offset = count_offset(context->visual->green_mask);
context->blue_offset = count_offset(context->visual->blue_mask);
/* disable dithering on 24 bits visuals */
if (context->depth >= 24)
context->attribs->render_mode = RM_MATCH;
}
/* check avaiability of MIT-SHM */
#ifdef XSHM
if (!(context->attribs->flags & RC_UseSharedMemory)) {
context->attribs->flags |= RC_UseSharedMemory;
context->attribs->use_shared_memory = True;
}
if (context->attribs->use_shared_memory) {
if (!XShmQueryExtension(context->dpy)) {
context->attribs->use_shared_memory = False;
}
}
#endif
return context;
}
static Bool
bestContext(Display *dpy, int screen_number, RContext *context)
{
XVisualInfo *vinfo=NULL, rvinfo;
int best = -1, numvis, i;
long flags;
XSetWindowAttributes attr;
rvinfo.class = TrueColor;
rvinfo.screen = screen_number;
flags = VisualClassMask | VisualScreenMask;
vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
if (vinfo) { /* look for a TrueColor, 24-bit or more (pref 24) */
for (i=numvis-1, best = -1; i>=0; i--) {
if (vinfo[i].depth == 24) best = i;
else if (vinfo[i].depth>24 && best<0) best = i;
}
}
if (best == -1) { /* look for a DirectColor, 24-bit or more (pref 24) */
rvinfo.class = DirectColor;
if (vinfo) XFree((char *) vinfo);
vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
if (vinfo) {
for (i=0, best = -1; i<numvis; i++) {
if (vinfo[i].depth == 24) best = i;
else if (vinfo[i].depth>24 && best<0) best = i;
}
}
}
if (best > -1) {
context->visual = vinfo[best].visual;
context->depth = vinfo[best].depth;
context->vclass = vinfo[best].class;
getColormap(context, screen_number);
attr.colormap = context->cmap;
attr.override_redirect = True;
attr.border_pixel = 0;
context->drawable =
XCreateWindow(dpy, RootWindow(dpy, screen_number),
1, 1, 1, 1, 0, context->depth,
CopyFromParent, context->visual,
CWBorderPixel|CWColormap|CWOverrideRedirect, &attr);
/* XSetWindowColormap(dpy, context->drawable, context->cmap);*/
}
if (vinfo) XFree((char *) vinfo);
if (best < 0)
return False;
else
return True;
}

786
wrlib/convert.c Normal file
View File

@@ -0,0 +1,786 @@
/* convert.c - convert RImage to Pixmap
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "wraster.h"
#define MIN(a,b) ((a)<(b) ? (a) : (b))
typedef struct RConversionTable {
unsigned short table[256];
unsigned short index;
struct RConversionTable *next;
} RConversionTable;
/*
* Lookup table for index*3/8
*/
static char errorTable1[]={
0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5,
6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11,
12, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17,
18, 18, 18, 19, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23,
24, 24, 24, 25, 25, 25, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29,
30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35,
36, 36, 36, 37, 37, 37, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41,
42, 42, 42, 43, 43, 43, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47,
48, 48, 48, 49, 49, 49, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53,
54, 54, 54, 55, 55, 55, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59,
60, 60, 60, 61, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65,
66, 66, 66, 67, 67, 67, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71,
72, 72, 72, 73, 73, 73, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77,
78, 78, 78, 79, 79, 79, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83,
84, 84, 84, 85, 85, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89,
90, 90, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 94, 94, 95
};
/*
* Lookup table for index*2/8
*/
static char errorTable2[]={
0, 1, 2, 1, 2, 3, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5,
4, 5, 6, 5, 6, 7, 6, 7, 6, 7, 8, 7, 8, 9, 8, 9,
8, 9, 10, 9, 10, 11, 10, 11, 10, 11, 12, 11, 12, 13, 12, 13,
12, 13, 14, 13, 14, 15, 14, 15, 14, 15, 16, 15, 16, 17, 16, 17,
16, 17, 18, 17, 18, 19, 18, 19, 18, 19, 20, 19, 20, 21, 20, 21,
20, 21, 22, 21, 22, 23, 22, 23, 22, 23, 24, 23, 24, 25, 24, 25,
24, 25, 26, 25, 26, 27, 26, 27, 26, 27, 28, 27, 28, 29, 28, 29,
28, 29, 30, 29, 30, 31, 30, 31, 30, 31, 32, 31, 32, 33, 32, 33,
32, 33, 34, 33, 34, 35, 34, 35, 34, 35, 36, 35, 36, 37, 36, 37,
36, 37, 38, 37, 38, 39, 38, 39, 38, 39, 40, 39, 40, 41, 40, 41,
40, 41, 42, 41, 42, 43, 42, 43, 42, 43, 44, 43, 44, 45, 44, 45,
44, 45, 46, 45, 46, 47, 46, 47, 46, 47, 48, 47, 48, 49, 48, 49,
48, 49, 50, 49, 50, 51, 50, 51, 50, 51, 52, 51, 52, 53, 52, 53,
52, 53, 54, 53, 54, 55, 54, 55, 54, 55, 56, 55, 56, 57, 56, 57,
56, 57, 58, 57, 58, 59, 58, 59, 58, 59, 60, 59, 60, 61, 60, 61,
60, 61, 62, 61, 62, 63, 62, 63, 62, 63, 64, 63, 64, 65, 64
};
static RConversionTable *conversionTable = NULL;
static unsigned short*
computeTable(unsigned short mask)
{
RConversionTable *tmp = conversionTable;
int i;
while (tmp) {
if (tmp->index == mask)
break;
tmp = tmp->next;
}
if (tmp)
return tmp->table;
tmp = (RConversionTable *)malloc(sizeof(RConversionTable));
if (tmp == NULL)
return NULL;
for (i=0;i<256;i++)
tmp->table[i] = (i*mask + 0x7f)/0xff;
tmp->index = mask;
tmp->next = conversionTable;
conversionTable = tmp;
return tmp->table;
}
static RXImage*
image2TrueColor(RContext *ctx, RImage *image)
{
RXImage *ximg;
register int x, y, r, g, b;
unsigned char *red, *grn, *blu;
unsigned long pixel;
unsigned short rmask, gmask, bmask;
unsigned short roffs, goffs, boffs;
unsigned short *rtable, *gtable, *btable;
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
return NULL;
}
red = image->data[0];
grn = image->data[1];
blu = image->data[2];
roffs = ctx->red_offset;
goffs = ctx->green_offset;
boffs = ctx->blue_offset;
rmask = ctx->visual->red_mask >> roffs;
gmask = ctx->visual->green_mask >> goffs;
bmask = ctx->visual->blue_mask >> boffs;
#if 0
/* this do not seem to increase speed. Only 0.06 second faster in
* rendering a 800x600 image to pixmap. 1.12 sec instead of 1.18.
* But does not require a 256*256*256 lookup table.
*/
if (ctx->depth==24) {
#ifdef DEBUG
puts("true color match for 24bpp");
#endif
for (y=0; y < image->height; y++) {
for (x=0; x < image->width; x++) {
pixel = (*(red++)<<roffs) | (*(grn++)<<goffs) | (*(blu++)<<boffs);
XPutPixel(ximg->image, x, y, pixel);
}
}
return ximg;
}
#endif
rtable = computeTable(rmask);
gtable = computeTable(gmask);
btable = computeTable(bmask);
if (rtable==NULL || gtable==NULL || btable==NULL) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
if (ctx->attribs->render_mode==RM_MATCH) {
/* fake match */
#ifdef DEBUG
puts("true color match");
#endif
for (y=0; y < image->height; y++) {
for (x=0; x < image->width; x++) {
/* reduce pixel */
r = rtable[*red++];
g = gtable[*grn++];
b = btable[*blu++];
pixel = (r<<roffs) | (g<<goffs) | (b<<boffs);
XPutPixel(ximg->image, x, y, pixel);
}
}
} else {
/* dither */
unsigned char *rerr, *gerr, *berr;
unsigned char *nrerr, *ngerr, *nberr;
unsigned char *rerr_, *gerr_, *berr_;
unsigned char *nrerr_, *ngerr_, *nberr_;
unsigned char *terr;
register int ac, err;
int width = image->width;
int dr=0xff-rmask;
int dg=0xff-gmask;
int db=0xff-bmask;
while ((dr & 1)==0) dr = dr >> 1;
while ((dg & 1)==0) dg = dg >> 1;
while ((db & 1)==0) db = db >> 1;
#ifdef DEBUG
puts("true color dither");
#endif
rerr_ = rerr = (unsigned char*)alloca((width+2)*sizeof(char));
gerr_ = gerr = (unsigned char*)alloca((width+2)*sizeof(char));
berr_ = berr = (unsigned char*)alloca((width+2)*sizeof(char));
nrerr_ = nrerr = (unsigned char*)alloca((width+2)*sizeof(char));
ngerr_ = ngerr = (unsigned char*)alloca((width+2)*sizeof(char));
nberr_ = nberr = (unsigned char*)alloca((width+2)*sizeof(char));
if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
for (x=0; x<width; x++) {
rerr[x] = *red++;
gerr[x] = *grn++;
berr[x] = *blu++;
}
rerr[x] = gerr[x] = berr[x] = 0;
/* convert and dither the image to XImage */
for (y=0; y<image->height; y++) {
if (y<image->height-1) {
memcpy(nrerr, red, width);
memcpy(ngerr, grn, width);
memcpy(nberr, blu, width);
red+=width;
grn+=width;
blu+=width;
/* last column */
nrerr[x] = *(red-1);
ngerr[x] = *(grn-1);
nberr[x] = *(blu-1);
}
for (x=0; x<width; x++) {
/* reduce pixel */
pixel = (rtable[*rerr]<<roffs) | (gtable[*gerr]<<goffs)
| (btable[*berr]<<boffs);
XPutPixel(ximg->image, x, y, pixel);
/* calc error */
err = *rerr&dr;
rerr++;
/* distribute error */
ac = errorTable1[err] + *rerr;
*rerr=MIN(ac, 0xff);
ac = errorTable1[err] + *nrerr;
*nrerr=MIN(ac, 0xff);
nrerr++;
ac = *nrerr + errorTable2[err];
*nrerr=MIN(ac,0xff);
/* calc error */
err = *gerr&dg;
gerr++;
/* distribute error */
ac = errorTable1[err] + *gerr;
*gerr=MIN(ac, 0xff);
ac = errorTable1[err] + *ngerr;
*ngerr=MIN(ac, 0xff);
ngerr++;
ac = *ngerr + errorTable2[err];
*ngerr=MIN(ac,0xff);
/* calc error */
err = *berr&db;
berr++;
/* distribute error */
ac = errorTable1[err] + *berr;
*berr=MIN(ac, 0xff);
ac = errorTable1[err] + *nberr;
*nberr=MIN(ac, 0xff);
nberr++;
ac = *nberr + errorTable2[err];
*nberr=MIN(ac,0xff);
}
/* skip to next line */
rerr = nrerr_;
nrerr = rerr_;
terr = nrerr_;
nrerr_ = rerr_;
rerr_ = terr;
gerr = ngerr_;
ngerr = gerr_;
terr = ngerr_;
ngerr_ = gerr_;
gerr_ = terr;
berr = nberr_;
nberr = berr_;
terr = nberr_;
nberr_ = berr_;
berr_ = terr;
}
}
return ximg;
}
static RXImage*
image2PseudoColor(RContext *ctx, RImage *image)
{
RXImage *ximg;
register int x, y, r, g, b;
unsigned char *red, *grn, *blu;
unsigned long pixel;
const int cpc=ctx->attribs->colors_per_channel;
const unsigned short rmask = cpc-1; /* different sizes could be used */
const unsigned short gmask = rmask; /* for r,g,b */
const unsigned short bmask = rmask;
unsigned short *rtable, *gtable, *btable;
const int cpccpc = cpc*cpc;
unsigned char *data;
int ofs;
/*register unsigned char maxrgb = 0xff;*/
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
return NULL;
}
red = image->data[0];
grn = image->data[1];
blu = image->data[2];
data = ximg->image->data;
/* Tables are same at the moment because rmask==gmask==bmask. */
rtable = computeTable(rmask);
gtable = computeTable(gmask);
btable = computeTable(bmask);
if (rtable==NULL || gtable==NULL || btable==NULL) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
if (ctx->attribs->render_mode == RM_MATCH) {
/* fake match */
#ifdef DEBUG
printf("pseudo color match with %d colors per channel\n", cpc);
#endif
for (y=0, ofs = 0; y<image->height; y++) {
for (x=0; x<image->width; x++, ofs++) {
/* reduce pixel */
r = rtable[red[ofs]];
g = gtable[grn[ofs]];
b = btable[blu[ofs]];
pixel = r*cpccpc + g*cpc + b;
/*data[ofs] = ctx->colors[pixel].pixel;*/
XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
}
}
} else {
/* dither */
short *rerr, *gerr, *berr;
short *nrerr, *ngerr, *nberr;
short *terr;
int rer, ger, ber;
const int dr=0xff/rmask;
const int dg=0xff/gmask;
const int db=0xff/bmask;
#ifdef DEBUG
printf("pseudo color dithering with %d colors per channel\n", cpc);
#endif
rerr = (short*)alloca((image->width+2)*sizeof(short));
gerr = (short*)alloca((image->width+2)*sizeof(short));
berr = (short*)alloca((image->width+2)*sizeof(short));
nrerr = (short*)alloca((image->width+2)*sizeof(short));
ngerr = (short*)alloca((image->width+2)*sizeof(short));
nberr = (short*)alloca((image->width+2)*sizeof(short));
if (!rerr || !gerr || !berr || !nrerr || !ngerr || !nberr) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
for (x=0; x<image->width; x++) {
rerr[x] = red[x];
gerr[x] = grn[x];
berr[x] = blu[x];
}
rerr[x] = gerr[x] = berr[x] = 0;
/* convert and dither the image to XImage */
for (y=0, ofs=0; y<image->height; y++) {
if (y<image->height-1) {
int x1;
for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
nrerr[x] = red[x1];
ngerr[x] = grn[x1];
nberr[x] = blu[x1];
}
/* last column */
x1--;
nrerr[x] = red[x1];
ngerr[x] = grn[x1];
nberr[x] = blu[x1];
}
for (x=0; x<image->width; x++, ofs++) {
/* reduce pixel */
if (rerr[x]>0xff) rerr[x]=0xff; else if (rerr[x]<0) rerr[x]=0;
if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
if (berr[x]>0xff) berr[x]=0xff; else if (berr[x]<0) berr[x]=0;
r = rtable[rerr[x]];
g = gtable[gerr[x]];
b = btable[berr[x]];
pixel = r*cpccpc + g*cpc + b;
/*data[ofs] = ctx->colors[pixel].pixel;*/
XPutPixel(ximg->image, x, y, ctx->colors[pixel].pixel);
/* calc error */
rer = rerr[x] - r*dr;
ger = gerr[x] - g*dg;
ber = berr[x] - b*db;
/* distribute error */
r = (rer*3)/8;
g = (ger*3)/8;
b = (ber*3)/8;
/* x+1, y */
rerr[x+1]+=r;
gerr[x+1]+=g;
berr[x+1]+=b;
/* x, y+1 */
nrerr[x]+=r;
ngerr[x]+=g;
nberr[x]+=b;
/* x+1, y+1 */
nrerr[x+1]+=rer-2*r;
ngerr[x+1]+=ger-2*g;
nberr[x+1]+=ber-2*b;
}
/* skip to next line */
terr = rerr;
rerr = nrerr;
nrerr = terr;
terr = gerr;
gerr = ngerr;
ngerr = terr;
terr = berr;
berr = nberr;
nberr = terr;
}
}
return ximg;
}
static RXImage*
image2GrayScale(RContext *ctx, RImage *image)
{
RXImage *ximg;
register int x, y, g;
unsigned char *red, *grn, *blu;
const int cpc=ctx->attribs->colors_per_channel;
unsigned short gmask;
unsigned short *table;
unsigned char *data;
int ofs;
/*register unsigned char maxrgb = 0xff;*/
ximg = RCreateXImage(ctx, ctx->depth, image->width, image->height);
if (!ximg) {
return NULL;
}
red = image->data[0];
grn = image->data[1];
blu = image->data[2];
data = ximg->image->data;
if (ctx->vclass == StaticGray)
gmask = (1<<ctx->depth) - 1; /* use all grays */
else
gmask = cpc*cpc*cpc-1;
table = computeTable(gmask);
if (table==NULL) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
if (ctx->attribs->render_mode == RM_MATCH) {
/* fake match */
#ifdef DEBUG
printf("grayscale match with %d colors per channel\n", cpc);
#endif
for (y=0, ofs = 0; y<image->height; y++) {
for (x=0; x<image->width; x++, ofs++) {
/* reduce pixel */
g = table[(red[ofs]*30+grn[ofs]*59+blu[ofs]*11)/100];
/*data[ofs] = ctx->colors[g].pixel;*/
XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
}
}
} else {
/* dither */
short *gerr;
short *ngerr;
short *terr;
int ger;
const int dg=0xff/gmask;
#ifdef DEBUG
printf("grayscale dither with %d colors per channel\n", cpc);
#endif
gerr = (short*)alloca((image->width+2)*sizeof(short));
ngerr = (short*)alloca((image->width+2)*sizeof(short));
if (!gerr || !ngerr) {
sprintf(RErrorString, "out of memory");
RDestroyXImage(ctx, ximg);
return NULL;
}
for (x=0; x<image->width; x++) {
gerr[x] = (red[x]*30 + grn[x]*59 + blu[x]*11)/100;
}
gerr[x] = 0;
/* convert and dither the image to XImage */
for (y=0, ofs=0; y<image->height; y++) {
if (y<image->height-1) {
int x1;
for (x=0, x1=ofs+image->width; x<image->width; x++, x1++) {
ngerr[x] = (red[x1]*30 + grn[x1]*59 + blu[x1]*11)/100;
}
/* last column */
x1--;
ngerr[x] = (red[x1]*30 + grn[x1]*59 + blu[x1]*11)/100;
}
for (x=0; x<image->width; x++, ofs++) {
/* reduce pixel */
if (gerr[x]>0xff) gerr[x]=0xff; else if (gerr[x]<0) gerr[x]=0;
g = table[gerr[x]];
/*data[ofs] = ctx->colors[g].pixel;*/
XPutPixel(ximg->image, x, y, ctx->colors[g].pixel);
/* calc error */
ger = gerr[x] - g*dg;
/* distribute error */
g = (ger*3)/8;
/* x+1, y */
gerr[x+1]+=g;
/* x, y+1 */
ngerr[x]+=g;
/* x+1, y+1 */
ngerr[x+1]+=ger-2*g;
}
/* skip to next line */
terr = gerr;
gerr = ngerr;
ngerr = terr;
}
}
ximg->image->data = (char*)data;
return ximg;
}
static RXImage*
image2Bitmap(RContext *ctx, RImage *image, int threshold)
{
RXImage *ximg;
unsigned char *alpha;
int x, y;
ximg = RCreateXImage(ctx, 1, image->width, image->height);
if (!ximg) {
return NULL;
}
alpha = image->data[3];
for (y = 0; y < image->height; y++) {
for (x = 0; x < image->width; x++) {
XPutPixel(ximg->image, x, y, (*alpha <= threshold ? 0 : 1));
alpha++;
}
}
return ximg;
}
int
RConvertImage(RContext *context, RImage *image, Pixmap *pixmap)
{
RXImage *ximg=NULL;
assert(context!=NULL);
assert(image!=NULL);
assert(pixmap!=NULL);
/* clear error message */
RErrorString[0] = 0;
if (context->vclass == TrueColor)
ximg = image2TrueColor(context, image);
else if (context->vclass == PseudoColor || context->vclass == StaticColor)
ximg = image2PseudoColor(context, image);
else if (context->vclass == GrayScale || context->vclass == StaticGray)
ximg = image2GrayScale(context, image);
if (!ximg) {
strcat(RErrorString, ":could not convert RImage to XImage");
#ifdef C_ALLOCA
alloca(0);
#endif
return False;
}
*pixmap = XCreatePixmap(context->dpy, context->drawable, image->width,
image->height, context->depth);
RPutXImage(context, *pixmap, context->copy_gc, ximg, 0, 0, 0, 0,
image->width, image->height);
RDestroyXImage(context, ximg);
#ifdef C_ALLOCA
alloca(0);
#endif
return True;
}
int
RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
Pixmap *mask, int threshold)
{
GC gc;
XGCValues gcv;
RXImage *ximg=NULL;
assert(context!=NULL);
assert(image!=NULL);
assert(pixmap!=NULL);
assert(mask!=NULL);
if (!RConvertImage(context, image, pixmap))
return False;
if (image->data[3]==NULL) {
*mask = None;
return True;
}
ximg = image2Bitmap(context, image, threshold);
if (!ximg) {
strcat(RErrorString, ":could not convert RImage mask to XImage");
#ifdef C_ALLOCA
alloca(0);
#endif
return False;
}
*mask = XCreatePixmap(context->dpy, context->drawable, image->width,
image->height, 1);
gcv.foreground = context->black;
gcv.background = context->white;
gcv.graphics_exposures = False;
gc = XCreateGC(context->dpy, *mask, GCForeground|GCBackground
|GCGraphicsExposures, &gcv);
RPutXImage(context, *mask, gc, ximg, 0, 0, 0, 0,
image->width, image->height);
RDestroyXImage(context, ximg);
#ifdef C_ALLOCA
alloca(0);
#endif
return True;
}
Bool
RGetClosestXColor(RContext *context, RColor *color, XColor *retColor)
{
RErrorString[0] = 0;
if (context->vclass == TrueColor) {
unsigned short rmask, gmask, bmask;
unsigned short roffs, goffs, boffs;
unsigned short *rtable, *gtable, *btable;
roffs = context->red_offset;
goffs = context->green_offset;
boffs = context->blue_offset;
rmask = context->visual->red_mask >> roffs;
gmask = context->visual->green_mask >> goffs;
bmask = context->visual->blue_mask >> boffs;
rtable = computeTable(rmask);
gtable = computeTable(gmask);
btable = computeTable(bmask);
retColor->pixel = (rtable[color->red]<<roffs) |
(rtable[color->green]<<goffs) | (rtable[color->blue]<<boffs);
retColor->red = rtable[color->red] << 8;
retColor->green = rtable[color->green] << 8;
retColor->blue = rtable[color->blue] << 8;
retColor->flags = DoRed|DoGreen|DoBlue;
} else if (context->vclass == PseudoColor || context->vclass == StaticColor) {
const int cpc=context->attribs->colors_per_channel;
const unsigned short rmask = cpc-1; /* different sizes could be used */
const unsigned short gmask = rmask; /* for r,g,b */
const unsigned short bmask = rmask;
unsigned short *rtable, *gtable, *btable;
const int cpccpc = cpc*cpc;
int index;
rtable = computeTable(rmask);
gtable = computeTable(gmask);
btable = computeTable(bmask);
if (rtable==NULL || gtable==NULL || btable==NULL) {
sprintf(RErrorString, "out of memory");
return False;
}
index = rtable[color->red]*cpccpc + gtable[color->green]*cpc
+ btable[color->blue];
*retColor = context->colors[index];
} else if (context->vclass == GrayScale || context->vclass == StaticGray) {
const int cpc = context->attribs->colors_per_channel;
unsigned short gmask;
unsigned short *table;
int index;
if (context->vclass == StaticGray)
gmask = (1<<context->depth) - 1; /* use all grays */
else
gmask = cpc*cpc*cpc-1;
table = computeTable(gmask);
if (!table)
return False;
index = table[(color->red*30 + color->green*59 + color->blue*11)/100];
*retColor = context->colors[index];
} else {
sprintf(RErrorString, "internal bug:unsupported visual:%i",
context->vclass);
return False;
}
return True;
}

325
wrlib/convolve.c Normal file
View File

@@ -0,0 +1,325 @@
/*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include "wraster.h"
/*
*----------------------------------------------------------------------
* RBlurImage--
* Apply 3x3 1 1 1 low pass, convolution mask to image.
* 1 1 1
* 1 1 1 /9
*----------------------------------------------------------------------
*/
int
RBlurImage(RImage *image)
{
register int x, y;
register int w, tmp;
unsigned char *r, *g, *b, *a;
unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
#define MASK(c,pc,p) ((*c + *(c-1) + *(c+1) + pc[p] + pc[p-1] + pc[p+1] \
+ *(c+w) + *(c+w-1) + *(c+w+1))/9)
pr = (unsigned char*)alloca(image->width*sizeof(char));
if (!pr)
goto outofmem;
pg = (unsigned char*)alloca(image->width*sizeof(char));
if (!pg)
goto outofmem;
pb = (unsigned char*)alloca(image->width*sizeof(char));
if (!pb)
goto outofmem;
pa = (unsigned char*)alloca(image->width*sizeof(char));
if (!pa)
goto outofmem;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (x=0; x<image->width; x++) {
pr[x] = *(r++);
pg[x] = *(g++);
pb[x] = *(b++);
}
w = image->width;
for (y=1; y<image->height-1; y++) {
pr[w-1] = r[w-1];
pg[w-1] = g[w-1];
pb[w-1] = b[w-1];
pr[0] = *(r++);
pg[0] = *(g++);
pb[0] = *(b++);
for (x=1; x<image->width-1; x++) {
tmp = *r;
*(r++) = MASK(r,pr,x);
pr[x] = tmp;
tmp = *g;
*(g++) = MASK(g,pg,x);
pg[x] = tmp;
tmp = *b;
*(b++) = MASK(b,pb,x);
pb[x] = tmp;
}
r++;
g++;
b++;
}
#undef MASK
#ifdef C_ALLOCA
alloca(0);
#endif
return True;
outofmem:
sprintf(RErrorString, "out of memory");
#ifdef C_ALLOCA
alloca(0);
#endif
return False;
}
#if 0
int
REdgeDetectImage(RImage *image)
{
register int x, y, d1, d2, d3, d4, rsum;
int w;
unsigned char *r, *g, *b, *a;
unsigned char *dr, *dg, *db, *da;
unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
RImage *image2;
image2 = RCloneImage(image);
pr = alloca(image->width*sizeof(char));
if (!pr)
goto outofmem;
pg = alloca(image->width*sizeof(char));
if (!pg)
goto outofmem;
pb = alloca(image->width*sizeof(char));
if (!pb)
goto outofmem;
pa = alloca(image->width*sizeof(char));
if (!pa)
goto outofmem;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
dr = image2->data[0];
dg = image2->data[1];
db = image2->data[2];
da = image2->data[3];
for (x=0; x<image->width; x++) {
*(dr++) = *(r++);
*(dg++) = *(g++);
*(db++) = *(b++);
}
w = image->width;
for (y=1; y<image->height-1; y++) {
dr[w-1] = r[w-1];
dg[w-1] = g[w-1];
db[w-1] = b[w-1];
*(dr++) = *(r++);
*(dg++) = *(g++);
*(db++) = *(b++);
for (x=1; x<image->width-1; x++) {
d1 = r[w+1] - r[-w-1];
d2 = r[1] - r[-1];
d3 = r[-w+1] - r[w-1];
d4 = r[-w] - r[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(dr++) = rsum;
d1 = g[w+1] - g[-w-1];
d2 = g[1] - g[-1];
d3 = g[-w+1] - g[w-1];
d4 = g[-w] - g[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(dg++) = rsum;
d1 = b[w+1] - b[-w-1];
d2 = b[1] - b[-1];
d3 = b[-w+1] - b[w-1];
d4 = b[-w] - b[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(db++) = rsum;
r++;
g++;
b++;
}
r++;
g++;
b++;
dr++;
dg++;
db++;
}
{
r = image->data[0];
image2->data[0] = r;
g = image->data[1];
image2->data[1] = g;
b = image->data[2];
image2->data[2] = b;
RDestroyImage(image2);
}
#undef MASK
return True;
}
int
RSmoothImage(RImage *image)
{
register int x, y;
register int v, w;
unsigned char *r, *g, *b, *a;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
w = image->width;
for (y=0; y<image->height - 1; y++) {
for (x=0; x<image->width - 1; x++) {
v = *r + 2 * *(r + 1) + 2 * *(r + w) + *(r + w + 1);
*(r++) = v/6;
v = *g + 2 * *(g + 1) + 2 * *(g + w) + *(g + w + 1);
*(g++) = v/6;
v = *b + 2 * *(b + 1) + 2 * *(b + w) + *(b + w + 1);
*(b++) = v/6;
}
/* last column */
v = 3 * *r + 3 * *(r + w);
*(r++) = v/6;
v = 3 * *g + 3 * *(g + w);
*(g++) = v/6;
v = 3 * *b + 3 * *(b + w);
*(b++) = v/6;
}
/* last line */
for (x=0; x<image->width - 1; x++) {
v = 3 * *r + 3 * *(r + 1);
*(r++) = v/6;
v = 3 * *g + 3 * *(g + 1);
*(g++) = v/6;
v = 3 * *b + 3 * *(b + 1);
*(b++) = v/6;
}
return True;
}
#endif

535
wrlib/draw.c Normal file
View File

@@ -0,0 +1,535 @@
/* draw.c - pixel plotting, line drawing
*
* Raster graphics library
*
* Copyright (c) 1998 Dan Pascu
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "wraster.h"
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
/*
* Returns the color of the pixel at coordinates (x, y) in "color".
*/
Bool
RGetPixel(RImage *image, int x, int y, RColor *color)
{
int ofs;
assert(image!=NULL);
if (x < 0 || x >= image->width
|| y < 0 || y >= image->height)
return False;
ofs = y*image->width + x;
color->red = image->data[0][ofs];
color->green = image->data[1][ofs];
color->blue = image->data[2][ofs];
/* If the image does not have alpha channel, we consider alpha 255 */
if (image->data[3])
color->alpha = image->data[3][ofs];
else
color->alpha = 255;
return True;
}
void
RPutPixel(RImage *image, int x, int y, RColor *color)
{
int ofs;
unsigned char *sr, *sg, *sb, *sa;
assert(image!=NULL);
assert(color!=NULL);
assert(x >= 0 && x < image->width);
assert(y >= 0 && y < image->height);
ofs = y*image->width + x;
sr = image->data[0] + ofs;
sg = image->data[1] + ofs;
sb = image->data[2] + ofs;
sa = image->data[3] + ofs;
if (color->alpha==255) {
*sr = color->red;
*sg = color->green;
*sb = color->blue;
if (image->data[3])
*sa = 255;
} else {
register int alpha, nalpha, r, g, b;
r = color->red;
g = color->green;
b = color->blue;
alpha = color->alpha;
nalpha = 255 - alpha;
*sr = (((int)*sr * nalpha) + (r * alpha))/256;
*sg = (((int)*sg * nalpha) + (g * alpha))/256;
*sb = (((int)*sb * nalpha) + (b * alpha))/256;
if (image->data[3])
*sa = alpha + ((int)*sa * nalpha)/256;
}
}
static void
operatePixel(RImage *image, int ofs, int operation, RColor *color)
{
unsigned char *sr, *sg, *sb, *sa;
register int alpha, nalpha, tmp;
int hasAlpha = image->data[3]!=NULL;
alpha = color->alpha;
nalpha = 255 - alpha;
sr = image->data[0] + ofs;
sg = image->data[1] + ofs;
sb = image->data[2] + ofs;
sa = image->data[3] + ofs;
switch (operation) {
case RClearOperation:
*sr = 0;
*sg = 0;
*sb = 0;
if (hasAlpha)
*sa = 0;
break;
case RCopyOperation:
*sr = color->red;
*sg = color->green;
*sb = color->blue;
if (hasAlpha)
*sa = color->alpha;
break;
case RNormalOperation:
if (color->alpha==255) {
*sr = color->red;
*sg = color->green;
*sb = color->blue;
if (hasAlpha)
*sa = 255;
} else {
*sr = (((int)*sr * nalpha) + ((int)color->red * alpha))/256;
*sg = (((int)*sg * nalpha) + ((int)color->green * alpha))/256;
*sb = (((int)*sb * nalpha) + ((int)color->blue * alpha))/256;
}
break;
case RAddOperation:
tmp = color->red + *sr;
*sr = MIN(255, tmp);
tmp = color->green + *sg;
*sg = MIN(255, tmp);
tmp = color->blue + *sb;
*sb = MIN(255, tmp);
if (hasAlpha)
*sa = MIN(*sa, color->alpha);
break;
case RSubtractOperation:
tmp = *sr - color->red;
*sr = MAX(0, tmp);
tmp = *sg - color->green;
*sg = MAX(0, tmp);
tmp = *sb - color->blue;
*sb = MAX(0, tmp);
if (hasAlpha)
*sa = MIN(*sa, color->alpha);
break;
}
}
void
ROperatePixel(RImage *image, int operation, int x, int y, RColor *color)
{
int ofs;
assert(image!=NULL);
assert(color!=NULL);
assert(x >= 0 && x < image->width);
assert(y >= 0 && y < image->height);
ofs = y*image->width + x;
operatePixel(image, ofs, operation, color);
}
void
RPutPixels(RImage *image, RPoint *points, int npoints, int mode, RColor *color)
{
register int x, y, i;
assert(image!=NULL);
assert(points!=NULL);
x = y = 0;
for (i=0; i<npoints; i++) {
if (mode == RAbsoluteCoordinates) {
x = points[i].x;
y = points[i].y;
} else {
x += points[i].x;
y += points[i].y;
}
RPutPixel(image, x, y, color);
}
}
void
ROperatePixels(RImage *image, int operation, RPoint *points, int npoints,
int mode, RColor *color)
{
register int x, y, i;
assert(image!=NULL);
assert(points!=NULL);
x = y = 0;
for (i=0; i<npoints; i++) {
if (mode == RAbsoluteCoordinates) {
x = points[i].x;
y = points[i].y;
} else {
x += points[i].x;
y += points[i].y;
}
ROperatePixel(image, operation, x, y, color);
}
}
/*
* This routine is a generic drawing routine, based on Bresenham's line
* drawing algorithm.
*/
static int
genericLine(RImage *image, int x0, int y0, int x1, int y1, RColor *color,
int operation, int polyline)
{
int i, err, du, dv, du2, dv2, uofs, vofs, last;
assert(image!=NULL);
assert(x0 >= 0 && x0 <= image->width);
assert(x1 >= 0 && x1 <= image->width);
assert(y0 >= 0 && y0 <= image->height);
assert(y1 >= 0 && y1 <= image->height);
if (x0 < x1) {
du = x1 - x0;
uofs = 1;
} else {
du = x0 - x1;
uofs = -1;
}
if (y0 < y1) {
dv = y1 -y0;
vofs = image->width;
} else {
dv = y0 - y1;
vofs = -image->width;
}
if (du < dv) {
/* Swap coordinates between them, so that always du>dv */
i = du; du = dv; dv = i;
i = uofs; uofs = vofs; vofs = i;
}
err = 0;
du2 = du<<1;
dv2 = dv<<1;
last = (polyline) ? du-1 : du;
if (color->alpha==255 || operation==RCopyOperation) {
unsigned char *sr, *sg, *sb, *sa;
i = y0*image->width + x0;
sr = image->data[0] + i;
sg = image->data[1] + i;
sb = image->data[2] + i;
sa = image->data[3] + i;
for (i=0; i<=last; i++) {
/* Draw the pixel */
*sr = color->red;
*sg = color->green;
*sb = color->blue;
if (image->data[3])
*sa = 255;
/* Compute error for NeXT Step */
err += dv2;
if (err >= du) {
sr += vofs; sg += vofs;
sb += vofs; sa += vofs;
err -= du2;
}
sr += uofs; sg += uofs;
sb += uofs; sa += uofs;
}
} else {
register int ofs = y0*image->width + x0;
for (i=0; i<=last; i++) {
/* Draw the pixel */
operatePixel(image, ofs, operation, color);
/* Compute error for NeXT Step */
err += dv2;
if (err >= du) {
ofs += vofs;
err -= du2;
}
ofs += uofs;
}
}
#if 0
if (mode == RALTER_PIXELS) {
RColorOffset *cdelta = (RColorOffset*)cdata;
register short r, g, b, a;
for (i=0; i<=last; i++) {
/* Change the pixel with offset */
r = (short)*sr + cdelta->red;
g = (short)*sg + cdelta->green;
b = (short)*sb + cdelta->blue;
if (r>255) r = 255; else if (r<0) r = 0;
if (g>255) g = 255; else if (g<0) g = 0;
if (b>255) b = 255; else if (b<0) b = 0;
*sr = (unsigned char) r;
*sg = (unsigned char) g;
*sb = (unsigned char) b;
if (image->data[3]) {
a = (short)*sa + cdelta->alpha;
if (a>255) a = 255; else if (a<0) a = 0;
*sa = (unsigned char) a;
}
/* Compute error for NeXT Step */
err += dv2;
if (err >= du) {
sr += vofs; sg += vofs;
sb += vofs; sa += vofs;
err -= du2;
}
sr += uofs; sg += uofs;
sb += uofs; sa += uofs;
}
} else {
RColor *color = (RColor*)cdata;
if (color->alpha==255) {
for (i=0; i<=last; i++) {
/* Draw the pixel */
*sr = color->red;
*sg = color->green;
*sb = color->blue;
if (image->data[3])
*sa = 255;
/* Compute error for NeXT Step */
err += dv2;
if (err >= du) {
sr += vofs; sg += vofs;
sb += vofs; sa += vofs;
err -= du2;
}
sr += uofs; sg += uofs;
sb += uofs; sa += uofs;
}
} else {
register short alpha, nalpha, r, g ,b;
alpha = color->alpha;
nalpha = 255 - alpha;
r = color->red;
g = color->green;
b = color->blue;
for (i=0; i<=last; i++) {
/* Draw the pixel */
*sr = (((int)*sr * nalpha) + (r * alpha))/256;
*sg = (((int)*sg * nalpha) + (g * alpha))/256;
*sb = (((int)*sb * nalpha) + (b * alpha))/256;
if (image->data[3])
*sa = alpha + ((int)*sa * nalpha)/256;
/* Compute error for NeXT Step */
err += dv2;
if (err >= du) {
sr += vofs; sg += vofs;
sb += vofs; sa += vofs;
err -= du2;
}
sr += uofs; sg += uofs;
sb += uofs; sa += uofs;
}
}
}
#endif
return True;
}
int
RDrawLine(RImage *image, int x0, int y0, int x1, int y1, RColor *color)
{
return genericLine(image, x0, y0, x1, y1, color, RNormalOperation, False);
}
int
ROperateLine(RImage *image, int operation, int x0, int y0, int x1,
int y1, RColor *color)
{
return genericLine(image, x0, y0, x1, y1, color, operation, False);
}
void
RDrawLines(RImage *image, RPoint *points, int npoints, int mode, RColor *color)
{
register int x1, y1, x2, y2, i;
assert(points!=NULL);
if (npoints==0)
return;
x1 = points[0].x;
y1 = points[0].y;
x2 = y2 = 0;
for (i=1; i<npoints-1; i++) {
if (mode == RAbsoluteCoordinates) {
x2 = points[i].x;
y2 = points[i].y;
} else {
x2 += points[i-1].x;
y2 += points[i-1].y;
}
/* Don't draw pixels at junction points twice */
genericLine(image, x1, y1, x2, y2, color, RNormalOperation, True);
x1 = x2;
y1 = y2;
}
i = npoints-1; /* last point */
if (mode == RAbsoluteCoordinates) {
x2 = points[i].x;
y2 = points[i].y;
} else {
x2 += points[i-1].x;
y2 += points[i-1].y;
}
i = (points[0].x==x2 && points[0].y==y2 && npoints>1);
genericLine(image, x1, y1, x2, y2, color, RNormalOperation, i);
}
void
ROperateLines(RImage *image, int operation, RPoint *points,
int npoints, int mode, RColor *color)
{
register int x1, y1, x2, y2, i;
assert(points!=NULL);
if (npoints==0)
return;
x1 = points[0].x;
y1 = points[0].y;
x2 = y2 = 0;
for (i=1; i<npoints-1; i++) {
if (mode == RAbsoluteCoordinates) {
x2 = points[i].x;
y2 = points[i].y;
} else {
x2 += points[i-1].x;
y2 += points[i-1].y;
}
/* Don't draw pixels at junction points twice */
genericLine(image, x1, y1, x2, y2, color, operation, True);
x1 = x2;
y1 = y2;
}
i = npoints-1; /* last point */
if (mode == RAbsoluteCoordinates) {
x2 = points[i].x;
y2 = points[i].y;
} else {
x2 += points[i-1].x;
y2 += points[i-1].y;
}
i = (points[0].x==x2 && points[0].y==y2 && npoints>1);
genericLine(image, x1, y1, x2, y2, color, operation, i);
}
void
RDrawSegments(RImage *image, RSegment *segs, int nsegs, RColor *color)
{
register int i;
assert(segs!=NULL);
for (i=0; i<nsegs; i++) {
genericLine(image, segs->x1, segs->y1, segs->x2, segs->y2, color,
RNormalOperation, False);
segs++;
}
}
void
ROperateSegments(RImage *image, int operation, RSegment *segs,
int nsegs, RColor *color)
{
register int i;
assert(segs!=NULL);
for (i=0; i<nsegs; i++) {
genericLine(image, segs->x1, segs->y1, segs->x2, segs->y2, color,
operation, False);
segs++;
}
}

201
wrlib/gif.c Normal file
View File

@@ -0,0 +1,201 @@
/* gif.c - load GIF image from file
*
* Raster graphics library
*
* Copyright (c) 1998 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#ifdef USE_GIF
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gif_lib.h>
#include "wraster.h"
static int InterlacedOffset[] = { 0, 4, 2, 1 };
static int InterlacedJumps[] = { 8, 8, 4, 2 };
/*
* Partially based on code in gif2rgb from giflib, by Gershon Elber.
*/
RImage*
RLoadGIF(RContext *context, char *file, int index)
{
RImage *image = NULL;
GifFileType *gif = NULL;
GifPixelType *buffer = NULL;
int i, j, k, ofs = 0;
int width, height;
GifRecordType recType;
ColorMapObject *colormap;
unsigned char rmap[256];
unsigned char gmap[256];
unsigned char bmap[256];
if (index < 0)
index = 0;
/* default error message */
sprintf(RErrorString, "file does not contain image of index %i", index);
gif = DGifOpenFileName(file);
if (!gif) {
sprintf(RErrorString, "could not load gif file");
return NULL;
}
colormap = gif->SColorMap;
i = 0;
do {
int extCode;
GifByteType *extension;
if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
switch (recType) {
case IMAGE_DESC_RECORD_TYPE:
if (i++ != index)
break;
if (DGifGetImageDesc(gif)==GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
width = gif->Image.Width;
height = gif->Image.Height;
if (gif->Image.ColorMap)
colormap = gif->Image.ColorMap;
/* the gif specs talk about a default colormap, but it
* doesnt say what the heck is this default colormap */
if (!colormap) {
/*
* Well, since the spec says the colormap can be anything,
* lets just render it with whatever garbage the stack
* has :)
*
sprintf(RErrorString, "bad gif file");
goto bye;
*/
} else {
for (j = 0; j < colormap->ColorCount; j++) {
rmap[j] = colormap->Colors[j].Red;
gmap[j] = colormap->Colors[j].Green;
bmap[j] = colormap->Colors[j].Blue;
}
}
buffer = malloc(width * sizeof(GifColorType));
if (!buffer) {
sprintf(RErrorString, "out of memory while loading gif");
goto bye;
}
image = RCreateImage(width, height, False);
if (!image) {
sprintf(RErrorString, "out of memory while loading gif");
goto bye;
}
if (gif->Image.Interlace) {
int l;
for (j = 0; j < 4; j++) {
for (k = InterlacedOffset[j]; k < height;
k += InterlacedJumps[j]) {
if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
ofs = k*width;
for (l = 0; l < width; l++, ofs++) {
int pixel = buffer[l];
image->data[0][ofs] = rmap[pixel];
image->data[1][ofs] = gmap[pixel];
image->data[2][ofs] = bmap[pixel];
}
}
}
} else {
for (j = 0; j < height; j++) {
if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
for (k = 0; k < width; k++, ofs++) {
int pixel = buffer[k];
image->data[0][ofs] = rmap[pixel];
image->data[1][ofs] = gmap[pixel];
image->data[2][ofs] = bmap[pixel];
}
}
}
break;
case EXTENSION_RECORD_TYPE:
/* skip all extension blocks */
if (DGifGetExtension(gif, &extCode, &extension)==GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
while (extension) {
if (DGifGetExtensionNext(gif, &extension)==GIF_ERROR) {
sprintf(RErrorString, "error while loading gif");
goto bye;
}
}
break;
default:
break;
}
} while (recType != TERMINATE_RECORD_TYPE && i <= index);
/* yuck! */
goto did_not_get_any_errors;
bye:
if (image)
RDestroyImage(image);
image = NULL;
did_not_get_any_errors:
if (buffer)
free(buffer);
if (gif)
DGifCloseFile(gif);
return image;
}
#endif /* USE_GIF */

508
wrlib/gradient.c Normal file
View File

@@ -0,0 +1,508 @@
/* gradient.c - renders gradients
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "wraster.h"
static RImage *renderHGradient(unsigned width, unsigned height,
int r0, int g0, int b0,
int rf, int gf, int bf);
static RImage *renderVGradient(unsigned width, unsigned height,
int r0, int g0, int b0,
int rf, int gf, int bf);
static RImage *renderDGradient(unsigned width, unsigned height,
int r0, int g0, int b0,
int rf, int gf, int bf);
static RImage *renderMHGradient(unsigned width, unsigned height,
RColor **colors, int count);
static RImage *renderMVGradient(unsigned width, unsigned height,
RColor **colors, int count);
static RImage *renderMDGradient(unsigned width, unsigned height,
RColor **colors, int count);
RImage*
RRenderMultiGradient(unsigned width, unsigned height, RColor **colors, int style)
{
int count;
count = 0;
while (colors[count]!=NULL) count++;
if (count > 2) {
switch (style) {
case RHorizontalGradient:
return renderMHGradient(width, height, colors, count);
case RVerticalGradient:
return renderMVGradient(width, height, colors, count);
case RDiagonalGradient:
return renderMDGradient(width, height, colors, count);
}
} else if (count > 1) {
return RRenderGradient(width, height, colors[0], colors[1], style);
} else if (count > 0) {
return RRenderGradient(width, height, colors[0], colors[0], style);
}
assert(0);
return NULL;
}
RImage*
RRenderGradient(unsigned width, unsigned height, RColor *from, RColor *to,
int style)
{
switch (style) {
case RHorizontalGradient:
return renderHGradient(width, height, from->red, from->green,
from->blue, to->red, to->green, to->blue);
case RVerticalGradient:
return renderVGradient(width, height, from->red, from->green,
from->blue, to->red, to->green, to->blue);
case RDiagonalGradient:
return renderDGradient(width, height, from->red, from->green,
from->blue, to->red, to->green, to->blue);
}
assert(0);
return NULL;
}
/*
*----------------------------------------------------------------------
* renderHGradient--
* Renders a horizontal linear gradient of the specified size in the
* RImage format with a border of the specified type.
*
* Returns:
* A 24bit RImage with the gradient (no alpha channel).
*
* Side effects:
* None
*----------------------------------------------------------------------
*/
static RImage*
renderHGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf)
{
int i;
unsigned long r, g, b, dr, dg, db;
RImage *image;
unsigned char *rp, *gp, *bp;
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
r = r0 << 16;
g = g0 << 16;
b = b0 << 16;
dr = ((rf-r0)<<16)/(int)width;
dg = ((gf-g0)<<16)/(int)width;
db = ((bf-b0)<<16)/(int)width;
/* render the first line */
for (i=0; i<width; i++) {
*(rp++) = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16);
r += dr;
g += dg;
b += db;
}
/* copy the first line to the other lines */
for (i=1; i<height; i++) {
memcpy(&(image->data[0][i*width]), image->data[0], width);
memcpy(&(image->data[1][i*width]), image->data[1], width);
memcpy(&(image->data[2][i*width]), image->data[2], width);
}
return image;
}
/*
*----------------------------------------------------------------------
* renderVGradient--
* Renders a vertical linear gradient of the specified size in the
* RImage format with a border of the specified type.
*
* Returns:
* A 24bit RImage with the gradient (no alpha channel).
*
* Side effects:
* None
*----------------------------------------------------------------------
*/
static RImage*
renderVGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf)
{
int i;
unsigned long r, g, b, dr, dg, db;
RImage *image;
unsigned char *rp, *gp, *bp;
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
r = r0<<16;
g = g0<<16;
b = b0<<16;
dr = ((rf-r0)<<16)/(int)height;
dg = ((gf-g0)<<16)/(int)height;
db = ((bf-b0)<<16)/(int)height;
for (i=0; i<height; i++) {
memset(rp, (unsigned char)(r>>16), width);
memset(gp, (unsigned char)(g>>16), width);
memset(bp, (unsigned char)(b>>16), width);
rp+=width;
gp+=width;
bp+=width;
r+=dr;
g+=dg;
b+=db;
}
return image;
}
/*
*----------------------------------------------------------------------
* renderDGradient--
* Renders a diagonal linear gradient of the specified size in the
* RImage format with a border of the specified type.
*
* Returns:
* A 24bit RImage with the gradient (no alpha channel).
*
* Side effects:
* None
*----------------------------------------------------------------------
*/
#if 0
/* This version is slower then the second below. It uses more operations,
* most of them multiplication of floats. -Dan
*/
static RImage*
renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf)
{
int x, y;
float from_red,from_green,from_blue;
float to_red,to_green,to_blue;
float dr,dg,db,dx,dy,w,h,xred,yred,xgreen,ygreen,xblue,yblue;
RImage *image;
unsigned char *rp, *gp, *bp;
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
from_red = (float)r0;
from_green = (float)g0;
from_blue = (float)b0;
to_red = (float)rf;
to_green = (float)gf;
to_blue = (float)bf;
w = (float) width;
h = (float) height;
dr = (to_red - from_red);
dg = (to_green - from_green);
db = (to_blue - from_blue);
for (y=0; y<height; y++) {
dy = y / h;
yred = dr * dy + from_red;
ygreen = dg * dy + from_green;
yblue = db * dy + from_blue;
for (x=0; x<width; x++) {
dx = x / w;
xred = dr * dx + from_red;
xgreen = dg * dx + from_green;
xblue = db * dx + from_blue;
*(rp++) = (unsigned char)((xred + yred)/2);
*(gp++) = (unsigned char)((xgreen + ygreen)/2);
*(bp++) = (unsigned char)((xblue + yblue)/2);
}
}
return image;
}
#endif
static RImage*
renderDGradient(unsigned width, unsigned height, int r0, int g0, int b0,
int rf, int gf, int bf)
{
RImage *image, *tmp;
float a;
int i, offset;
if (width == 1)
return renderVGradient(width, height, r0, g0, b0, rf, gf, bf);
else if (height == 1)
return renderHGradient(width, height, r0, g0, b0, rf, gf, bf);
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
tmp = renderHGradient(2*width-1, 1, r0, g0, b0, rf, gf, bf);
if (!tmp) {
RDestroyImage(image);
return NULL;
}
a = ((float)(width - 1))/((float)(height - 1));
/* copy the first line to the other lines with corresponding offset */
for (i=0; i<height; i++) {
offset = (int)(a*i+0.5);
memcpy(&(image->data[0][i*width]), &(tmp->data[0][offset]), width);
memcpy(&(image->data[1][i*width]), &(tmp->data[1][offset]), width);
memcpy(&(image->data[2][i*width]), &(tmp->data[2][offset]), width);
}
RDestroyImage(tmp);
return image;
}
static RImage*
renderMHGradient(unsigned width, unsigned height, RColor **colors, int count)
{
int i, j, k;
unsigned long r, g, b, dr, dg, db;
RImage *image;
unsigned char *rp, *gp, *bp;
unsigned width2;
assert(count > 2);
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
if (count > width)
count = width;
if (count > 1)
width2 = width/(count-1);
else
width2 = width;
k = 0;
r = colors[0]->red << 16;
g = colors[0]->green << 16;
b = colors[0]->blue << 16;
/* render the first line */
for (i=1; i<count; i++) {
dr = ((int)(colors[i]->red - colors[i-1]->red) <<16)/(int)width2;
dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)width2;
db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)width2;
for (j=0; j<width2; j++) {
*(rp++) = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16);
r += dr;
g += dg;
b += db;
k++;
}
r = colors[i]->red << 16;
g = colors[i]->green << 16;
b = colors[i]->blue << 16;
}
for (j=k; j<width; j++) {
*(rp++) = (unsigned char)(r>>16);
*(gp++) = (unsigned char)(g>>16);
*(bp++) = (unsigned char)(b>>16);
}
/* copy the first line to the other lines */
for (i=1; i<height; i++) {
memcpy(&(image->data[0][i*width]), image->data[0], width);
memcpy(&(image->data[1][i*width]), image->data[1], width);
memcpy(&(image->data[2][i*width]), image->data[2], width);
}
return image;
}
static RImage*
renderMVGradient(unsigned width, unsigned height, RColor **colors, int count)
{
int i, j, k;
unsigned long r, g, b, dr, dg, db;
RImage *image;
unsigned char *rp, *gp, *bp;
unsigned height2;
assert(count > 2);
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
rp = image->data[0];
gp = image->data[1];
bp = image->data[2];
if (count > height)
count = height;
if (count > 1)
height2 = height/(count-1);
else
height2 = height;
k = 0;
r = colors[0]->red << 16;
g = colors[0]->green << 16;
b = colors[0]->blue << 16;
for (i=1; i<count; i++) {
dr = ((int)(colors[i]->red - colors[i-1]->red) <<16)/(int)height2;
dg = ((int)(colors[i]->green - colors[i-1]->green)<<16)/(int)height2;
db = ((int)(colors[i]->blue - colors[i-1]->blue) <<16)/(int)height2;
for (j=0; j<height2; j++) {
memset(rp, (unsigned char)(r>>16), width);
memset(gp, (unsigned char)(g>>16), width);
memset(bp, (unsigned char)(b>>16), width);
rp+=width;
gp+=width;
bp+=width;
r += dr;
g += dg;
b += db;
k++;
}
r = colors[i]->red << 16;
g = colors[i]->green << 16;
b = colors[i]->blue << 16;
}
for (j=k; j<height; j++) {
memset(rp, (unsigned char)(r>>16), width);
memset(gp, (unsigned char)(g>>16), width);
memset(bp, (unsigned char)(b>>16), width);
rp+=width;
gp+=width;
bp+=width;
}
return image;
}
static RImage*
renderMDGradient(unsigned width, unsigned height, RColor **colors, int count)
{
RImage *image, *tmp;
float a;
int i, offset;
assert(count > 2);
if (width == 1)
return renderMVGradient(width, height, colors, count);
else if (height == 1)
return renderMHGradient(width, height, colors, count);
image = RCreateImage(width, height, False);
if (!image) {
return NULL;
}
if (count > width)
count = width;
if (count > height)
count = height;
if (count > 2)
tmp = renderMHGradient(2*width-1, 1, colors, count);
else
tmp = renderHGradient(2*width-1, 1, colors[0]->red<<8,
colors[0]->green<<8, colors[0]->blue<<8,
colors[1]->red<<8, colors[1]->green<<8,
colors[1]->blue<<8);
if (!tmp) {
RDestroyImage(image);
return NULL;
}
a = ((float)(width - 1))/((float)(height - 1));
/* copy the first line to the other lines with corresponding offset */
for (i=0; i<height; i++) {
offset = (int)(a*i+0.5);
memcpy(&(image->data[0][i*width]), &(tmp->data[0][offset]), width);
memcpy(&(image->data[1][i*width]), &(tmp->data[1][offset]), width);
memcpy(&(image->data[2][i*width]), &(tmp->data[2][offset]), width);
}
RDestroyImage(tmp);
return image;
}

181
wrlib/jpeg.c Normal file
View File

@@ -0,0 +1,181 @@
/* jpeg.c - load JPEG image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#ifdef USE_JPEG
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <jpeglib.h>
#include "wraster.h"
/*
* <setjmp.h> is used for the optional error recovery mechanism shown in
* the second part of the example.
*/
#include <setjmp.h>
/*
* ERROR HANDLING:
*
* The JPEG library's standard error handler (jerror.c) is divided into
* several "methods" which you can override individually. This lets you
* adjust the behavior without duplicating a lot of code, which you might
* have to update with each future release.
*
* Our example here shows how to override the "error_exit" method so that
* control is returned to the library's caller when a fatal error occurs,
* rather than calling exit() as the standard error_exit method does.
*
* We use C's setjmp/longjmp facility to return control. This means that the
* routine which calls the JPEG library must first execute a setjmp() call to
* establish the return point. We want the replacement error_exit to do a
* longjmp(). But we need to make the setjmp buffer accessible to the
* error_exit routine. To do this, we make a private extension of the
* standard JPEG error handler object. (If we were using C++, we'd say we
* were making a subclass of the regular error handler.)
*
* Here's the extended error handler struct:
*/
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
typedef struct my_error_mgr * my_error_ptr;
/*
* Here's the routine that will replace the standard error_exit method:
*/
void
my_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
RImage*
RLoadJPEG(RContext *context, char *file_name, int index)
{
RImage *image = NULL;
struct jpeg_decompress_struct cinfo;
int i, j;
unsigned char *r, *g, *b;
JSAMPROW buffer[1];
FILE *file;
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
struct my_error_mgr jerr;
file = fopen(file_name, "r");
if (!file) {
sprintf(RErrorString, "could not open JPEG file \"%s\"", file_name);
return NULL;
}
RErrorString[0] = 0;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
jpeg_destroy_decompress(&cinfo);
fclose(file);
return NULL;
}
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, file);
jpeg_read_header(&cinfo, TRUE);
buffer[0] = (JSAMPROW)malloc(cinfo.image_width*cinfo.num_components);
if (!buffer[0]) {
sprintf(RErrorString, "out of memory");
goto bye;
}
image = RCreateImage(cinfo.image_width, cinfo.image_height, False);
if (!image) {
sprintf(RErrorString, "out of memory");
goto bye;
}
cinfo.out_color_space = JCS_RGB;
cinfo.quantize_colors = FALSE;
cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE;
jpeg_start_decompress(&cinfo);
r = image->data[0];
g = image->data[1];
b = image->data[2];
while (cinfo.output_scanline < cinfo.image_height) {
jpeg_read_scanlines(&cinfo, buffer, 1);
for (i=0,j=0; i<cinfo.image_width; i++) {
*(r++) = buffer[0][j++];
*(g++) = buffer[0][j++];
*(b++) = buffer[0][j++];
}
}
/*
jpeg_finish_decompress(&cinfo);
*/
bye:
jpeg_destroy_decompress(&cinfo);
fclose(file);
if (buffer[0])
free(buffer[0]);
return image;
}
#endif /* USE_JPEG */

384
wrlib/load.c Normal file
View File

@@ -0,0 +1,384 @@
/* load.c - load image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#ifdef USE_PNG
#include <png.h>
#endif
#include "wraster.h"
typedef struct RCachedImage {
RImage *image;
char *file;
time_t last_modif; /* last time file was modified */
time_t last_use; /* last time image was used */
} RCachedImage;
/*
* Size of image cache
*/
static int RImageCacheSize = -1;
/*
* Max. size of image to store in cache
*/
static int RImageCacheMaxImage = -1; /* 0 = any size */
#define IMAGE_CACHE_SIZE 8
#define IMAGE_CACHE_MAX_IMAGE 64*64
static RCachedImage *RImageCache;
#define IM_ERROR -1
#define IM_UNKNOWN 0
#define IM_XPM 1
#define IM_TIFF 2
#define IM_PNG 3
#define IM_PPM 4
#define IM_JPEG 5
#define IM_GIF 6
/* How many image types do we have. */
/* Increase this when adding new image types! */
#define IM_TYPES 6
static int identFile(char *path);
extern RImage *RLoadPPM(RContext *context, char *file_name, int index);
extern RImage *RLoadXPM(RContext *context, char *file, int index);
#ifdef USE_TIFF
extern RImage *RLoadTIFF(RContext *context, char *file, int index);
#endif
#ifdef USE_PNG
extern RImage *RLoadPNG(RContext *context, char *file, int index);
#endif
#ifdef USE_JPEG
extern RImage *RLoadJPEG(RContext *context, char *file_name, int index);
#endif
#ifdef USE_GIF
extern RImage *RLoadGIF(RContext *context, char *file_name, int index);
#endif
static char*
wstrdup(char *s)
{
char *tmp;
tmp = malloc(strlen(s)+1);
if (!tmp)
return NULL;
return strcpy(tmp, s);
}
char**
RSupportedFileFormats(void)
{
char **tmp;
int i = 0;
tmp = malloc(sizeof(char*)*(IM_TYPES+1));
if (!tmp)
return NULL;
memset(tmp, 0, sizeof(char*)*(IM_TYPES+1));
/* built-in */
tmp[i++] = wstrdup("XPM");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
/* built-in */
tmp[i++] = wstrdup("PPM");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
#ifdef USE_TIFF
tmp[i++] = wstrdup("TIFF");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
#endif
#ifdef USE_PNG
tmp[i++] = wstrdup("PNG");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
#endif
#ifdef USE_JPEG
tmp[i++] = wstrdup("JPEG");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
#endif
#ifdef USE_GIF
tmp[i++] = wstrdup("GIF");
if (!tmp[i-1]) {
RFreeStringList(tmp);
return NULL;
}
#endif
tmp[i] = NULL;
return tmp;
}
void
RFreeStringList(char **list)
{
int i;
for (i = 0; list[i]!=NULL; i++) {
free(list[i]);
}
free(list);
}
static void
init_cache()
{
char *tmp;
tmp = getenv("RIMAGE_CACHE");
if (!tmp || sscanf(tmp, "%i", &RImageCacheSize)!=1) {
RImageCacheSize = IMAGE_CACHE_SIZE;
}
if (RImageCacheSize<0)
RImageCacheSize = 0;
tmp = getenv("RIMAGE_CACHE_SIZE");
if (!tmp || sscanf(tmp, "%i", &RImageCacheMaxImage)!=1) {
RImageCacheMaxImage = IMAGE_CACHE_MAX_IMAGE;
}
if (RImageCacheSize>0) {
RImageCache = malloc(sizeof(RCachedImage)*RImageCacheSize);
if (RImageCache==NULL) {
printf("wrlib: out of memory for image cache\n");
return;
}
memset(RImageCache, 0, sizeof(RCachedImage)*RImageCacheSize);
}
}
RImage*
RLoadImage(RContext *context, char *file, int index)
{
RImage *image = NULL;
int i;
struct stat st;
RErrorString[0] = 0;
if (RImageCacheSize<0) {
init_cache();
}
if (RImageCacheSize>0) {
for (i=0; i<RImageCacheSize; i++) {
if (RImageCache[i].file
&& strcmp(file, RImageCache[i].file)==0) {
if (stat(file, &st)==0
&& st.st_mtime == RImageCache[i].last_modif) {
RImageCache[i].last_use = time(NULL);
return RCloneImage(RImageCache[i].image);
} else {
free(RImageCache[i].file);
RImageCache[i].file = NULL;
RDestroyImage(RImageCache[i].image);
}
}
}
}
switch (identFile(file)) {
case IM_ERROR:
sprintf(RErrorString, "error opening file");
return NULL;
case IM_UNKNOWN:
sprintf(RErrorString, "unknown image format");
return NULL;
case IM_XPM:
image = RLoadXPM(context, file, index);
break;
#ifdef USE_TIFF
case IM_TIFF:
image = RLoadTIFF(context, file, index);
break;
#endif /* USE_TIFF */
#ifdef USE_PNG
case IM_PNG:
image = RLoadPNG(context, file, index);
break;
#endif /* USE_PNG */
#ifdef USE_JPEG
case IM_JPEG:
image = RLoadJPEG(context, file, index);
break;
#endif /* USE_JPEG */
#ifdef USE_GIF
case IM_GIF:
image = RLoadGIF(context, file, index);
break;
#endif /* USE_GIF */
case IM_PPM:
image = RLoadPPM(context, file, index);
break;
default:
sprintf(RErrorString, "unsupported image format");
return NULL;
}
/* store image in cache */
if (RImageCacheSize>0 && image &&
(RImageCacheMaxImage==0
|| RImageCacheMaxImage >= image->width*image->height)) {
time_t oldest=time(NULL);
int oldest_idx = 0;
int done = 0;
for (i=0; i<RImageCacheSize; i++) {
if (!RImageCache[i].file) {
RImageCache[i].file = malloc(strlen(file)+1);
strcpy(RImageCache[i].file, file);
RImageCache[i].image = RCloneImage(image);
RImageCache[i].last_modif = st.st_mtime;
RImageCache[i].last_use = time(NULL);
done = 1;
break;
} else {
if (oldest > RImageCache[i].last_use) {
oldest = RImageCache[i].last_use;
oldest_idx = i;
}
}
}
/* if no slot available, dump least recently used one */
if (!done) {
free(RImageCache[oldest_idx].file);
RDestroyImage(RImageCache[oldest_idx].image);
RImageCache[oldest_idx].file = malloc(strlen(file)+1);
strcpy(RImageCache[oldest_idx].file, file);
RImageCache[oldest_idx].image = RCloneImage(image);
RImageCache[oldest_idx].last_modif = st.st_mtime;
RImageCache[oldest_idx].last_use = time(NULL);
}
}
return image;
}
static int
identFile(char *path)
{
int fd;
unsigned char buffer[32];
if (!path)
return IM_ERROR;
fd = open(path, O_RDONLY);
if (fd < 0)
return IM_ERROR;
if (read(fd, buffer, 32)<1) {
close(fd);
return IM_ERROR;
}
close(fd);
/* check for XPM */
if (strncmp((char*)buffer, "/* XPM */", 9)==0)
return IM_XPM;
/* check for TIFF */
if ((buffer[0]=='I' && buffer[1]=='I' && buffer[2]=='*' && buffer[3]==0)
||(buffer[0]=='M' && buffer[1]=='M' && buffer[2]==0 && buffer[3]=='*'))
return IM_TIFF;
#ifdef USE_PNG
/* check for PNG */
if (png_check_sig(buffer, 8))
return IM_PNG;
#endif
/* check for raw PPM or PGM */
if (buffer[0]=='P' && (buffer[1]=='5' || buffer[1]=='6'))
return IM_PPM;
/* check for JPEG */
if (buffer[0] == 0xff && buffer[1] == 0xd8)
return IM_JPEG;
/* check for GIF */
if (buffer[0] == 'G' && buffer[1] == 'I' && buffer[2] == 'F')
return IM_GIF;
return IM_UNKNOWN;
}

131
wrlib/misc.c Normal file
View File

@@ -0,0 +1,131 @@
/*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include "wraster.h"
int
RBevelImage(RImage *image, int bevel_type)
{
RColor color;
RColor cdelta;
int w, h;
if (image->width<3 || image->height<3)
return False;
w = image->width;
h = image->height;
if (bevel_type>0) { /* raised */
/* top */
cdelta.alpha = 0;
cdelta.red = cdelta.green = cdelta.blue = 80;
ROperateLine(image, RAddOperation, 0, 0, w-1, 0, &cdelta);
if (bevel_type==RBEV_RAISED3 && w>3)
ROperateLine(image, RAddOperation, 1, 1, w-3, 1,&cdelta);
/* left */
ROperateLine(image, RAddOperation, 0, 1, 0, h-1, &cdelta);
if (bevel_type==RBEV_RAISED3 && h>3)
ROperateLine(image, RAddOperation, 1, 2, 1, h-3, &cdelta);
/* bottom */
color.alpha = 255;
color.red = color.green = color.blue = 0;
cdelta.red = cdelta.green = cdelta.blue = 40;
if (bevel_type==RBEV_RAISED2 || bevel_type==RBEV_RAISED3) {
ROperateLine(image, RSubtractOperation, 0, h-2, w-3,
h-2, &cdelta);
RDrawLine(image, 0, h-1, w-1, h-1, &color);
} else {
ROperateLine(image, RSubtractOperation, 0, h-1, w-1, h-1,
&cdelta);
}
/* right */
if (bevel_type==RBEV_RAISED2 || bevel_type==RBEV_RAISED3) {
ROperateLine(image, RSubtractOperation, w-2, 0, w-2, h-2,
&cdelta);
RDrawLine(image, w-1, 0, w-1, h-2, &color);
} else {
ROperateLine(image, RSubtractOperation, w-1, 0, w-1, h-2,
&cdelta);
}
} else { /* sunken */
cdelta.alpha = 0;
cdelta.red = cdelta.green = cdelta.blue = 40;
ROperateLine(image, RSubtractOperation, 0, 0, w-1, 0,
&cdelta); /* top */
ROperateLine(image, RSubtractOperation, 0, 1, 0, h-1,
&cdelta); /* left */
cdelta.red = cdelta.green = cdelta.blue = 80;
ROperateLine(image, RAddOperation, 0, h-1, w-1, h-1, &cdelta); /* bottom */
ROperateLine(image, RAddOperation, w-1, 0, w-1, h-2, &cdelta); /* right */
}
return True;
}
int
RClearImage(RImage *image, RColor *color)
{
int bytes;
bytes = image->width*image->height;
if (color->alpha==255) {
memset(image->data[0], color->red, bytes);
memset(image->data[1], color->green, bytes);
memset(image->data[2], color->blue, bytes);
if (image->data[3])
memset(image->data[3], 0xff, bytes);
} else {
register int i;
unsigned char *dr, *dg, *db;
int alpha, nalpha, r, g, b;
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
r = color->red;
g = color->green;
b = color->blue;
alpha = color->alpha;
nalpha = 255 - alpha;
for (i=0; i<bytes; i++) {
*dr = (((int)*dr * nalpha) + (r * alpha))/256;
*dg = (((int)*dg * nalpha) + (g * alpha))/256;
*db = (((int)*db * nalpha) + (b * alpha))/256;
dr++; dg++; db++;
}
}
return True;
}

413
wrlib/nxpm.c Normal file
View File

@@ -0,0 +1,413 @@
/* nxpm.c - load "normalized" XPM image
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wraster.h"
/*
* Restricted support for XPM images.
*
* The images must be in the following "normalized" format:
*
*
* line content
* 1 signature comment
* 2 ignored ( normally "static char *xpm[] = {" )
* 3 "width height color_count chars" where chars is 1 or 2
* 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
* format OR None
* n data
*
* - no comments or blank lines are allowed, except for the signature
* - all lines must have at most 256 characters
* - no white spaces allowed at left of each line
*/
#define LINEWIDTH 64
#ifndef USE_XPM
RImage*
RGetImageFromXPMData(RContext *context, char **data)
{
RImage *image = NULL;
unsigned char *color_table[4];
unsigned short *symbol_table;
unsigned char *r, *g, *b, *a;
int i, j, k, line = 0;
int transp;
unsigned short color;
int bsize;
int w, h, ccount, csize;
if (sscanf(data[line++], "%i %i %i %i", &w, &h, &ccount, &csize)!=4
|| w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
goto bad_format;
if (csize!=1 && csize!=2)
goto bad_format;
color_table[0] = alloca(ccount);
color_table[1] = alloca(ccount);
color_table[2] = alloca(ccount);
color_table[3] = alloca(ccount);
symbol_table = alloca(ccount * sizeof(unsigned short));
bsize = csize * w + 16;
if (!color_table[0] || !color_table[1] || !color_table[2] ||
!color_table[3] || !symbol_table || !bsize) {
sprintf(RErrorString, "out of memory while converting XPM data");
alloca(0);
return NULL;
}
transp = 0;
/* get color table */
for (i=0; i<ccount; i++) {
symbol_table[i] = data[line][0];
if (csize==2)
symbol_table[i] |= data[line][1]<<8;
j = csize;
while (data[line][j]!='#' && data[line][j]!=0
&& data[line][j]!='N') j++;
if (data[line][j]=='#') {
unsigned int red, green, blue;
k = 0;
j++;
while (data[line][j+k]!=0) k++;
if (k==6) {
if (sscanf(&(data[line][j]), "%2x%2x%2x", &red, &green, &blue)!=3)
goto bad_format;
} else if (k==12) {
if (sscanf(&(data[line][j]), "%4x%4x%4x", &red, &green, &blue)!=3)
goto bad_format;
red >>= 8;
green >>= 8;
blue >>= 8;
} else
goto bad_format;
color_table[0][i] = red;
color_table[1][i] = green;
color_table[2][i] = blue;
color_table[3][i] = 255;
} else if (strncmp(&(data[line][j]), "None", 4)==0) {
color_table[3][i] = 0;
transp = 1;
} else {
goto bad_format;
}
line++;
}
image = RCreateImage(w, h, transp);
if (!image) {
sprintf(RErrorString, "out of memory while converting XPM data");
alloca(0);
return NULL;
}
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (i=0; i<h; i++) {
if (csize==1) {
for (j=0; j<w; j++) {
color = data[line][j];
for (k=0; k<ccount; k++) {
if (symbol_table[k] == color)
break;
}
if (k==ccount)
k = 0;
*(r++) = color_table[0][k];
*(g++) = color_table[1][k];
*(b++) = color_table[2][k];
if (a)
*(a++) = color_table[3][k];
}
} else {
for (j=0; j<w*2; j++) {
color = data[line][j++];
color |= data[line][j];
for (k=0; k<ccount; k++) {
if (symbol_table[k] == color)
break;
}
if (k==ccount)
k = 0;
*(r++) = color_table[0][k];
*(g++) = color_table[1][k];
*(b++) = color_table[2][k];
if (a)
*(a++) = color_table[3][k];
}
}
line++;
}
#ifdef C_ALLOCA
alloca(0);
#endif
return image;
bad_format:
sprintf(RErrorString, "XPM data is not in the normalized format");
#ifdef C_ALLOCA
alloca(0);
#endif
if (image)
RDestroyImage(image);
return NULL;
}
RImage*
RLoadXPM(RContext *context, char *file, int index)
{
RImage *image = NULL;
char line[LINEWIDTH+1];
char *buffer;
unsigned char *color_table[4];
unsigned short *symbol_table;
unsigned char *r, *g, *b, *a;
int i, j, k;
int transp;
unsigned short color;
int bsize;
int w, h, ccount, csize;
FILE *f;
f = fopen(file, "r");
if (!f) {
sprintf(RErrorString, "can't open XPM file \"%s\"", file);
return NULL;
}
/* sig */
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
/* declaration */
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
/* data */
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
if (line[0]=='/')
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
if (sscanf(line, "\"%i %i %i %i\"", &w, &h, &ccount, &csize)!=4
|| w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
goto bad_file;
if (csize!=1 && csize!=2)
goto bad_format;
color_table[0] = alloca(ccount);
color_table[1] = alloca(ccount);
color_table[2] = alloca(ccount);
color_table[3] = alloca(ccount);
symbol_table = alloca(ccount * sizeof(unsigned short));
bsize = csize * w + 16;
buffer = alloca(bsize);
if (!color_table[0] || !color_table[1] || !color_table[2] ||
!color_table[3] || !symbol_table || !bsize) {
sprintf(RErrorString, "out of memory while loading XPM file \"%s\"",
file);
fclose(f);
alloca(0);
return NULL;
}
transp = 0;
/* get color table */
for (i=0; i<ccount; i++) {
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
if (line[0]=='/')
if (!fgets(line, LINEWIDTH, f))
goto bad_file;
symbol_table[i] = line[1];
if (csize==2)
symbol_table[i] |= line[2]<<8;
j = csize+1;
while (line[j]!='#' && line[j]!='"' && line[j]!=0 && line[j]!='N') j++;
if (line[j]=='#') {
unsigned int red, green, blue;
k = 0;
j++;
while (line[j+k]!='"' && line[j+k]!=0) k++;
if (k==6) {
if (sscanf(&(line[j]), "%2x%2x%2x", &red, &green, &blue)!=3)
goto bad_format;
} else if (k==12) {
if (sscanf(&(line[j]), "%4x%4x%4x", &red, &green, &blue)!=3)
goto bad_format;
red >>= 8;
green >>= 8;
blue >>= 8;
} else
goto bad_format;
color_table[0][i] = red;
color_table[1][i] = green;
color_table[2][i] = blue;
color_table[3][i] = 255;
} else if (strncmp(&(line[j]), "None", 4)==0) {
color_table[3][i] = 0;
transp = 1;
} else {
goto bad_format;
}
}
image = RCreateImage(w, h, transp);
if (!image) {
sprintf(RErrorString, "out of memory while loading XPM file \"%s\"",
file);
fclose(f);
alloca(0);
return NULL;
}
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (i=0; i<h; i++) {
if (!fgets(buffer, bsize, f))
goto bad_file;
if (buffer[0]=='/')
if (!fgets(buffer, bsize, f))
goto bad_file;
if (csize==1) {
for (j=1; j<=w; j++) {
color = buffer[j];
for (k=0; k<ccount; k++) {
if (symbol_table[k] == color)
break;
}
if (k==ccount)
k = 0;
*(r++) = color_table[0][k];
*(g++) = color_table[1][k];
*(b++) = color_table[2][k];
if (a)
*(a++) = color_table[3][k];
}
} else {
for (j=1; j<=w*2; j++) {
color = buffer[j++];
color |= buffer[j] << 8;
for (k=0; k<ccount; k++) {
if (symbol_table[k] == color)
break;
}
if (k==ccount) {
k = 0;
}
*(r++) = color_table[0][k];
*(g++) = color_table[1][k];
*(b++) = color_table[2][k];
if (a)
*(a++) = color_table[3][k];
}
}
}
fclose(f);
#ifdef C_ALLOCA
alloca(0);
#endif
return image;
bad_format:
sprintf(RErrorString, "XPM file \"%s\" is not in the normalized format", file);
fclose(f);
#ifdef C_ALLOCA
alloca(0);
#endif
if (image)
RDestroyImage(image);
return NULL;
bad_file:
sprintf(RErrorString, "bad XPM file \"%s\"", file);
fclose(f);
#ifdef C_ALLOCA
alloca(0);
#endif
if (image)
RDestroyImage(image);
return NULL;
}
#endif

243
wrlib/png.c Normal file
View File

@@ -0,0 +1,243 @@
/* png.c - load PNG image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
# define alloca __builtin_alloca
#else
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
# pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
#ifdef USE_PNG
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <png.h>
#if PNG_LIBPNG_VER < 96
#error libpng_must_be_more_at_least_0_96
#endif
#include "wraster.h"
RImage*
RLoadPNG(RContext *context, char *file, int index)
{
char *tmp;
RImage *image=NULL;
FILE *f;
png_structp png;
png_infop pinfo, einfo;
png_color_16p bkcolor;
int alpha;
int x, y, i;
double gamma, sgamma;
png_uint_32 width, height;
int depth, junk, color_type;
png_bytep *png_rows;
unsigned char *r, *g, *b, *a;
f = fopen(file, "r");
if (!f) {
sprintf(RErrorString, "could not open file \"%s\"", file);
return NULL;
}
png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL);
if (!png) {
sprintf(RErrorString, "error loading PNG file \"%s\"", file);
fclose(f);
return NULL;
}
pinfo = png_create_info_struct(png);
if (!pinfo) {
sprintf(RErrorString, "error loading PNG file \"%s\"", file);
fclose(f);
png_destroy_read_struct(&png, NULL, NULL);
return NULL;
}
einfo = png_create_info_struct(png);
if (!einfo) {
sprintf(RErrorString, "error loading PNG file \"%s\"", file);
fclose(f);
png_destroy_read_struct(&png, &pinfo, NULL);
return NULL;
}
if (setjmp(png->jmpbuf)) {
sprintf(RErrorString, "error loading PNG file \"%s\"", file);
fclose(f);
png_destroy_read_struct(&png, &pinfo, &einfo);
if (image)
RDestroyImage(image);
return NULL;
}
png_init_io(png, f);
png_read_info(png, pinfo);
png_get_IHDR(png, pinfo, &width, &height, &depth, &color_type,
&junk, &junk, &junk);
/* check for an alpha channel */
if (png_get_valid(png, pinfo, PNG_INFO_tRNS))
alpha = True;
else
alpha = (color_type & PNG_COLOR_MASK_ALPHA);
/* allocate RImage */
image = RCreateImage(width, height, alpha);
if (!image) {
sprintf(RErrorString, "could not create RImage");
fclose(f);
png_destroy_read_struct(&png, &pinfo, &einfo);
return NULL;
}
/* normalize to 8bpp with alpha channel */
if (color_type == PNG_COLOR_TYPE_PALETTE && depth < 8)
png_set_expand(png);
if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
png_set_expand(png);
if (png_get_valid(png, pinfo, PNG_INFO_tRNS))
png_set_expand(png);
if (depth == 16)
png_set_strip_16(png);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png);
/* set gamma correction */
if ((context->attribs->flags & RC_GammaCorrection)
&& context->depth != 8) {
sgamma = (context->attribs->rgamma + context->attribs->ggamma +
context->attribs->bgamma) / 3;
} else if ((tmp = getenv("DISPLAY_GAMMA")) != NULL) {
sgamma = atof(tmp);
if (sgamma==0)
sgamma = 1;
} else {
sgamma = 2.0;
}
if (png_get_gAMA(png, pinfo, &gamma))
png_set_gamma(png, sgamma, gamma);
else
png_set_gamma(png, sgamma, 0.45);
/* do the transforms */
png_read_update_info(png, pinfo);
/* set background color */
if (png_get_bKGD(png, pinfo, &bkcolor)) {
image->background.red = bkcolor->red >> 8;
image->background.green = bkcolor->green >> 8;
image->background.blue = bkcolor->blue >> 8;
}
png_rows = alloca(sizeof(char*)*height);
if (!png_rows) {
sprintf(RErrorString, "out of memory loading \"%s\"", file);
fclose(f);
RDestroyImage(image);
png_destroy_read_struct(&png, &pinfo, &einfo);
#ifdef C_ALLOCA
alloca(0);
#endif
return NULL;
}
for (y=0; y<height; y++) {
png_rows[y] = alloca(png_get_rowbytes(png, pinfo));
if (!png_rows[y]) {
sprintf(RErrorString, "out of memory loading \"%s\"", file);
fclose(f);
RDestroyImage(image);
png_destroy_read_struct(&png, &pinfo, &einfo);
#ifdef C_ALLOCA
alloca(0);
#endif
return NULL;
}
}
/* read data */
png_read_image(png, png_rows);
png_read_end(png, einfo);
png_destroy_read_struct(&png, &pinfo, &einfo);
fclose(f);
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
/* convert to RImage */
if (alpha) {
for (y=0; y<height; y++) {
for (x=0, i=0; x<width; x++) {
*(r++) = *(png_rows[y]+i++);
*(g++) = *(png_rows[y]+i++);
*(b++) = *(png_rows[y]+i++);
*(a++) = *(png_rows[y]+i++);
}
}
} else {
for (y=0; y<height; y++) {
for (x=0, i=0; x<width; x++) {
*(r++) = *(png_rows[y]+i++);
*(g++) = *(png_rows[y]+i++);
*(b++) = *(png_rows[y]+i++);
}
}
}
#ifdef C_ALLOCA
alloca(0);
#endif
return image;
}
#endif /* USE_PNG */

172
wrlib/ppm.c Normal file
View File

@@ -0,0 +1,172 @@
/* ppm.c - load PPM image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wraster.h"
static RImage*
load_graymap(char *file_name, FILE *file, int w, int h, int max, int raw)
{
RImage *image;
image = RCreateImage(w, h, 0);
if (!image) {
sprintf(RErrorString, "out of memory");
return NULL;
}
if (!raw) {
} else {
if (max<256) {
if (!fgets(image->data[0], w*h, file))
goto short_file;
memcpy(image->data[0], image->data[1], w*h);
memcpy(image->data[0], image->data[2], w*h);
} else {
}
}
return image;
short_file:
sprintf(RErrorString, "PPM file \"%s\" seems to be truncated", file_name);
return NULL;
}
static RImage*
load_pixmap(char *file_name, FILE *file, int w, int h, int max, int raw)
{
RImage *image;
int i;
char buf[3];
char *r, *g, *b;
image = RCreateImage(w, h, 0);
if (!image) {
sprintf(RErrorString, "out of memory");
return NULL;
}
r = image->data[0];
g = image->data[1];
b = image->data[2];
if (!raw) {
} else {
if (max<256) {
i = 0;
while (i < w*h) {
if (fread(buf, 1, 3, file)!=3)
goto short_file;
*(r++) = buf[0];
*(g++) = buf[1];
*(b++) = buf[2];
i++;
}
} else {
}
}
return image;
short_file:
sprintf(RErrorString, "PPM file \"%s\" seems to be truncated", file_name);
return NULL;
}
RImage*
RLoadPPM(RContext *context, char *file_name, int index)
{
FILE *file;
RImage *image = NULL;
char buffer[256];
int w, h, m;
int type;
#define GETL() if (!fgets(buffer, 255, file)) goto short_file
RErrorString[0] = 0;
file = fopen(file_name, "r");
if (!file) {
sprintf(RErrorString, "could not open PPM file \"%s\"", file_name);
return NULL;
}
/* get signature */
GETL();
/* only accept raw pixmaps or graymaps */
if (buffer[0] != 'P' || (buffer[1] != '5' && buffer[1] != '6')) {
sprintf(RErrorString, "unknown PPM format in \"%s\"", file_name);
fclose(file);
return NULL;
}
type = buffer[1];
/* skip comments */
while (1) {
GETL();
if (buffer[0]!='#')
break;
}
/* get size */
if (sscanf(buffer, "%i %i", &w, &h)!=2)
goto bad_file;
GETL();
if (sscanf(buffer, "%i", &m)!=1 || m < 1)
goto bad_file;
if (type=='5')
image = load_graymap(file_name, file, w, h, m, type=='5');
else if (type=='6')
image = load_pixmap(file_name, file, w, h, m, type=='6');
fclose(file);
return image;
bad_file:
sprintf(RErrorString, "PPM file \"%s\" seems to be corrupted", file_name);
fclose(file);
return NULL;
short_file:
sprintf(RErrorString, "PPM file \"%s\" seems to be truncated", file_name);
fclose(file);
return NULL;
}

529
wrlib/raster.c Normal file
View File

@@ -0,0 +1,529 @@
/* raster.c - main and other misc stuff
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include "wraster.h"
#include <assert.h>
#define MAXERRLEN 512
char *WRasterLibVersion="0.2";
char RErrorString[MAXERRLEN];
RImage*
RCreateImage(unsigned width, unsigned height, int alpha)
{
RImage *image=NULL;
int i;
assert(width>0 && height>0);
image = malloc(sizeof(RImage));
if (!image) {
sprintf(RErrorString, "out of memory");
return NULL;
}
memset(image, 0, sizeof(RImage));
image->width = width;
image->height = height;
for (i=0; i<3+(alpha?1:0); i++) {
image->data[i] = malloc(width*height);
if (!image->data[i])
goto error;
}
return image;
error:
for (i=0; i<4; i++) {
if (image->data[i])
free(image->data[i]);
}
if (image)
free(image);
sprintf(RErrorString, "out of memory");
return NULL;
}
RImage*
RCloneImage(RImage *image)
{
RImage *new_image;
assert(image!=NULL);
new_image = RCreateImage(image->width, image->height, image->data[3]!=NULL);
if (!new_image)
return NULL;
new_image->background = image->background;
memcpy(new_image->data[0], image->data[0], image->width*image->height);
memcpy(new_image->data[1], image->data[1], image->width*image->height);
memcpy(new_image->data[2], image->data[2], image->width*image->height);
if (image->data[3])
memcpy(new_image->data[3], image->data[3], image->width*image->height);
return new_image;
}
RImage*
RGetSubImage(RImage *image, int x, int y, unsigned width, unsigned height)
{
int i, ofs;
RImage *new_image;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *dr, *dg, *db, *da;
assert(image!=NULL);
assert(x>=0 && y>=0);
assert(x<image->width && y<image->height);
assert(width>0 && height>0);
if (x+width > image->width)
width = image->width-x;
if (y+height > image->height)
height = image->height-y;
new_image = RCreateImage(width, height, image->data[3]!=NULL);
if (!new_image)
return NULL;
new_image->background = image->background;
ofs = image->width*y+x;
sr = image->data[0]+ofs;
sg = image->data[1]+ofs;
sb = image->data[2]+ofs;
sa = image->data[3]+ofs;
dr = new_image->data[0];
dg = new_image->data[1];
db = new_image->data[2];
da = new_image->data[3];
for (i=0; i<height; i++) {
memcpy(dr, sr, width);
memcpy(dg, sg, width);
memcpy(db, sb, width);
sr += image->width;
sg += image->width;
sb += image->width;
dr += width;
dg += width;
db += width;
if (da) {
memcpy(da, sa, width);
sa += image->width;
da += width;
}
}
return new_image;
}
void
RDestroyImage(RImage *image)
{
int i;
assert(image!=NULL);
for (i=0; i<4; i++) {
if (image->data[i])
free(image->data[i]);
}
free(image);
}
/*
*----------------------------------------------------------------------
* RCombineImages-
* Combines two equal sized images with alpha image. The second
* image will be placed on top of the first one.
*----------------------------------------------------------------------
*/
void
RCombineImages(RImage *image, RImage *src)
{
register int i;
unsigned char *dr, *dg, *db, *da;
unsigned char *sr, *sg, *sb, *sa;
int alpha, calpha;
assert(image->width == src->width);
assert(image->height == src->height);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
sr = src->data[0];
sg = src->data[1];
sb = src->data[2];
sa = src->data[3];
if (!sa) {
memcpy(dr, sr, image->height*image->width);
memcpy(dg, sg, image->height*image->width);
memcpy(db, sb, image->height*image->width);
} else {
for (i=0; i<image->height*image->width; i++) {
alpha = *sa;
calpha = 255 - *sa;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256;
if (image->data[3])
*da |= *sa;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
da++;
}
}
}
void
RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness)
{
register int i;
unsigned char *dr, *dg, *db;
unsigned char *sr, *sg, *sb, *sa;
int c_opaqueness;
assert(image->width == src->width);
assert(image->height == src->height);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
sr = src->data[0];
sg = src->data[1];
sb = src->data[2];
sa = src->data[3];
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
if (!src->data[3]) {
#define COP c_opaqueness
for (i=0; i<image->width*image->height; i++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
}
#undef COP
} else {
int tmp;
for (i=0; i<image->width*image->height; i++) {
tmp= (*sa * opaqueness)/256;
*dr = (((int)*dr *(int)(255-tmp)) + ((int)*sr *(int)tmp))/256;
*dg = (((int)*dg *(int)(255-tmp)) + ((int)*sg *(int)tmp))/256;
*db = (((int)*db *(int)(255-tmp)) + ((int)*sb *(int)tmp))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
}
}
#undef OP
}
void
RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
unsigned height, int dx, int dy)
{
int x, y, dwi, swi;
unsigned char *dr, *dg, *db;
unsigned char *sr, *sg, *sb, *sa;
int alpha, calpha;
assert(dy < image->height);
assert(dx < image->width);
assert(sy + height <= src->height);
assert(sx + width <= src->width);
dr = image->data[0] + dy*(int)image->width + dx;
dg = image->data[1] + dy*(int)image->width + dx;
db = image->data[2] + dy*(int)image->width + dx;
sr = src->data[0] + sy*(int)src->width + sx;
sg = src->data[1] + sy*(int)src->width + sx;
sb = src->data[2] + sy*(int)src->width + sx;
sa = src->data[3] + sy*(int)src->width + sx;
swi = src->width - width;
dwi = image->width - width;
if (height > image->height - dy)
height = image->height - dy;
if (!src->data[3]) {
for (y=sy; y<height+sy; y++) {
for (x=sx; x<width+sx; x++) {
*(dr++) = *(sr++);
*(dg++) = *(sg++);
*(db++) = *(sb++);
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
}
} else {
for (y=sy; y<height+sy; y++) {
for (x=sx; x<width+sx; x++) {
alpha = *sa;
calpha = 255 - alpha;
*dr = (((int)*dr * calpha) + ((int)*sr * alpha))/256;
*dg = (((int)*dg * calpha) + ((int)*sg * alpha))/256;
*db = (((int)*db * calpha) + ((int)*sb * alpha))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
sa += swi;
}
}
}
void
RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
unsigned width, unsigned height, int dx, int dy,
int opaqueness)
{
int x, y, dwi, swi;
int c_opaqueness;
unsigned char *dr, *dg, *db;
unsigned char *sr, *sg, *sb, *sa;
assert(dy <= image->height);
assert(dx <= image->width);
assert(sy <= height);
assert(sx <= width);
dr = image->data[0] + dy*image->width + dx;
dg = image->data[1] + dy*image->width + dx;
db = image->data[2] + dy*image->width + dx;
sr = src->data[0] + sy*src->width;
sg = src->data[1] + sy*src->width;
sb = src->data[2] + sy*src->width;
sa = src->data[3] + sy*src->width;
swi = src->width - width;
dwi = image->width - width;
/* clip */
width -= sx;
height -= sy;
if (height > image->height - dy)
height = image->height - dy;
c_opaqueness = 255 - opaqueness;
#define OP opaqueness
if (!src->data[3]) {
#define COP c_opaqueness
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
*dr = (((int)*dr *(int)COP) + ((int)*sr *(int)OP))/256;
*dg = (((int)*dg *(int)COP) + ((int)*sg *(int)OP))/256;
*db = (((int)*db *(int)COP) + ((int)*sb *(int)OP))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
}
#undef COP
} else {
int tmp;
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
tmp= (*sa * opaqueness)/256;
*dr = (((int)*dr *(int)(255-tmp)) + ((int)*sr *(int)tmp))/256;
*dg = (((int)*dg *(int)(255-tmp)) + ((int)*sg *(int)tmp))/256;
*db = (((int)*db *(int)(255-tmp)) + ((int)*sb *(int)tmp))/256;
dr++; dg++; db++;
sr++; sg++; sb++;
sa++;
}
dr += dwi; dg += dwi; db += dwi;
sr += swi; sg += swi; sb += swi;
sa += swi;
}
}
#undef OP
}
void
RCombineImageWithColor(RImage *image, RColor *color)
{
register int i;
unsigned char *dr, *dg, *db, *da;
int alpha, nalpha, r, g, b;
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
if (!da) {
/* Image has no alpha channel, so we consider it to be all 255 */
return;
}
r = color->red;
g = color->green;
b = color->blue;
for (i=0; i<image->width*image->height; i++) {
alpha = *da;
nalpha = 255 - alpha;
*dr = (((int)*dr * alpha) + (r * nalpha))/256;
*dg = (((int)*dg * alpha) + (g * nalpha))/256;
*db = (((int)*db * alpha) + (b * nalpha))/256;
dr++; dg++; db++; da++;
}
}
RImage*
RMakeTiledImage(RImage *tile, unsigned width, unsigned height)
{
int x, y;
unsigned w;
unsigned long tile_size = tile->width * tile->height;
unsigned long tx = 0;
int have_alpha = (tile->data[3]!=NULL);
RImage *image;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *dr, *dg, *db, *da;
if (width == tile->width && height == tile->height)
image = RCloneImage(tile);
else if (width <= tile->width && height <= tile->height)
image = RGetSubImage(tile, 0, 0, width, height);
else {
image = RCreateImage(width, height, have_alpha);
dr = image->data[0];
dg = image->data[1];
db = image->data[2];
da = image->data[3];
sr = tile->data[0];
sg = tile->data[1];
sb = tile->data[2];
sa = tile->data[3];
for (y = 0; y < height; y++) {
for (x = 0; x < width; x += tile->width) {
w = (width - x < tile->width) ? width - x : tile->width;
memcpy(dr, sr+tx, w);
memcpy(dg, sg+tx, w);
memcpy(db, sb+tx, w);
if (have_alpha) {
memcpy(da, sa+tx, w);
da += w;
}
dr += w;
dg += w;
db += w;
}
tx = (tx + tile->width) % tile_size;
}
}
return image;
}
RImage*
RMakeCenteredImage(RImage *image, unsigned width, unsigned height, RColor *color)
{
int x, y, w, h, sx, sy;
RImage *tmp;
tmp = RCreateImage(width, height, False);
if (!tmp) {
return NULL;
}
RClearImage(tmp, color);
if (image->height < height) {
h = image->height;
y = (height - h)/2;
sy = 0;
} else {
sy = (image->height - height)/2;
y = 0;
h = height;
}
if (image->width < width) {
w = image->width;
x = (width - w)/2;
sx = 0;
} else {
sx = (image->width - width)/2;
x = 0;
w = width;
}
RCombineArea(tmp, image, sx, sy, w, h, x, y);
return tmp;
}

143
wrlib/scale.c Normal file
View File

@@ -0,0 +1,143 @@
/* scale.c - image scaling
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <assert.h>
#include "wraster.h"
/*
*----------------------------------------------------------------------
* RScaleImage--
* Creates a scaled copy of an image.
*
* Returns:
* The new scaled image.
*
*----------------------------------------------------------------------
*/
RImage*
RScaleImage(RImage *image, unsigned new_width, unsigned new_height)
{
int ox;
int px, py;
register int x, y, t;
int dx, dy;
unsigned char *sr, *sg, *sb, *sa;
unsigned char *dr, *dg, *db, *da;
RImage *img;
assert(new_width >= 0 && new_height >= 0);
if (new_width == image->width && new_height == image->height)
return RCloneImage(image);
img = RCreateImage(new_width, new_height, image->data[3]!=NULL);
if (!img)
return NULL;
/* fixed point math idea taken from Imlib by
* Carsten Haitzler (Rasterman) */
dx = (image->width<<16)/new_width;
dy = (image->height<<16)/new_height;
py = 0;
dr = img->data[0];
dg = img->data[1];
db = img->data[2];
da = img->data[3];
if (image->data[3]!=NULL) {
int ot;
ot = -1;
for (y=0; y<new_height; y++) {
t = image->width*(py>>16);
sr = image->data[0]+t;
sg = image->data[1]+t;
sb = image->data[2]+t;
sa = image->data[3]+t;
ot = t;
ox = 0;
px = 0;
for (x=0; x<new_width; x++) {
px += dx;
*(dr++) = *sr;
*(dg++) = *sg;
*(db++) = *sb;
*(da++) = *sa;
t = (px - ox)>>16;
ox += t<<16;
sr += t;
sg += t;
sb += t;
sa += t;
}
py += dy;
}
} else {
int ot;
ot = -1;
for (y=0; y<new_height; y++) {
t = image->width*(py>>16);
sr = image->data[0]+t;
sg = image->data[1]+t;
sb = image->data[2]+t;
ot = t;
ox = 0;
px = 0;
for (x=0; x<new_width; x++) {
px += dx;
*(dr++) = *sr;
*(dg++) = *sg;
*(db++) = *sb;
t = (px-ox)>>16;
ox += t<<16;
sr += t;
sg += t;
sb += t;
}
py += dy;
}
}
return img;
}

85
wrlib/test.c Normal file
View File

@@ -0,0 +1,85 @@
#include "wraster.h"
#include <X11/Xlib.h>
#include <stdio.h>
Display *dpy;
Window win;
RContext *ctx;
RImage *img, *tile, *new, *mini, *tiled;
Pixmap pix;
void main(int argc, char **argv)
{
RContextAttributes attr;
int a=0;
if (argc<1) {
puts("You must supply t,p or x as the file type to load");
puts("t is tiff, p is png and x is xpm");
exit(0);
}
if (argc>1) {
if (argv[1][0]=='t')
a=1;
else if (argv[1][0]=='p')
a=2;
else a=0;
}
dpy = XOpenDisplay("");
if (!dpy) {
puts("cant open display");
exit(1);
}
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, 250, 250,
0, 0, 0);
XMapRaised(dpy, win);
XFlush(dpy);
attr.flags = RC_RenderMode | RC_ColorsPerChannel | RC_DefaultVisual;
attr.render_mode = RM_DITHER;
attr.colors_per_channel = 4;
ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);
#ifdef USE_TIFF
if (a==1)
img = RLoadImage(ctx, "ballot_box.tiff", 0);
#endif
#ifdef USE_PNG
if (a==2)
img = RLoadImage(ctx, "test.png", 0);
#endif
#ifdef USE_XPM
if (a==0)
img = RLoadImage(ctx, "ballot_box.xpm", 0);
#endif
if (!img) {
puts(RErrorString);
exit(1);
}
new = RLoadImage(ctx, "tile.xpm", 0);
if (!new) {
puts(RErrorString);
exit(1);
}
RCombineArea(new, img, 0, 0, img->width, img->height, 8, 8);
RConvertImage(ctx, new, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, new->width, new->height,
0, 0);
mini = RScaleImage(new, 20, 20);
RConvertImage(ctx, mini, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 20, 20,
new->width, new->height);
tiled = RMakeTiledImage(img, 160, 160);
RConvertImage(ctx, tiled, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 160, 160,
new->width+mini->width, new->height+mini->height);
XFlush(dpy);
getchar();
}

BIN
wrlib/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

555
wrlib/testdraw.c Normal file
View File

@@ -0,0 +1,555 @@
#include "wraster.h"
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
Display *dpy;
RContext *ctx;
char *ProgName;
void
testDraw()
{
RImage *img, *tile, *icon, *tmp;
RColor color, from, to;
RColor cdelta;
RSegment segs[20];
int i, x, y;
XSetWindowAttributes val;
Pixmap pix, back;
Window win;
val.background_pixel = ctx->black;
val.colormap = ctx->cmap;
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 128, 256,
0, ctx->depth, InputOutput, ctx->visual,
CWColormap|CWBackPixel, &val);
back = XCreatePixmap(ctx->dpy, ctx->drawable, 128, 256, ctx->depth);
/* Dark blue tile gradient */
from.red = 0x28;
from.green = 0x45;
from.blue = 0x69;
from.alpha = 0xff;
to.red = 0x08;
to.green = 0x24;
to.blue = 0x20;
to.alpha = 0xff;
/* Standard gray tile gradient */
/*from.red = 0xa6;
from.green = 0xa6;
from.blue = 0xb6;
from.alpha = 0xff;
to.red = 0x51;
to.green = 0x55;
to.blue = 0x61;
to.alpha = 0xff;*/
/* Make the tile, and put it as a sample in the first place */
tile = RRenderGradient(64, 64, &from, &to, RGRD_DIAGONAL);
img = RCloneImage(tile);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 0, 0);
/* Read the image, and combine it with the tile. Put it as a sample
* in the second slot, and also save a copy for later use. */
icon = RLoadImage(ctx, "ballot_box.xpm", 0);
if (!icon) {
puts(RErrorString);
exit(1);
}
RCombineArea(img, icon, 0, 0, icon->width, icon->height, 8, 8);
RDestroyImage(icon);
tmp = img;
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 64, 0);
img = RCloneImage(tile);
/* Draw random pixels on image */
for (i=0; i< 200; i++) {
color.red = rand()%256;
color.green = rand()%256;
color.blue = rand()%256;
color.alpha = 255;
x = rand()%64;
y = rand()%64;
RPutPixel(img, x, y, &color);
}
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 0, 64);
RDestroyImage(img);
img = RCloneImage(tile);
/* Alter random pixels in image with the same amount for r/g/b */
for (i=0; i< 200; i++) {
cdelta.red = cdelta.green = cdelta.blue = rand()%511 - 255;
cdelta.alpha = 0;
x = rand()%64;
y = rand()%64;
ROperatePixel(img, RAddOperation, x, y, &cdelta);
}
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 64, 64);
RDestroyImage(img);
img = RCloneImage(tile);
/* Draw lines in all directions to test different slopes */
color.red = 0xff;
color.green = 0x7d;
color.blue = 0x52;
color.alpha = 0xff;
for (i=0; i<16; i++)
segs[i].x1 = segs[i].y1 = 31;
segs[6].x2 = segs[7].x2 = segs[8].x2 = segs[9].x2 = segs[10].x2 = 0;
segs[2].y2 = segs[3].y2 = segs[4].y2 = segs[5].y2 = segs[6].y2 = 0;
segs[5].x2 = segs[11].x2 = 16;
segs[1].y2 = segs[7].y2 = 16;
segs[4].x2 = segs[12].x2 = 31;
segs[0].y2 = segs[8].y2 = 31;
segs[3].x2 = segs[13].x2 = 46;
segs[9].y2 = segs[15].y2 = 46;
segs[0].x2 = segs[1].x2 = segs[2].x2 = segs[14].x2 = segs[15].x2 = 62;
segs[10].y2 = segs[11].y2 = segs[12].y2 = segs[13].y2 = segs[14].y2 = 62;
RDrawSegments(img, segs, 9, &color);
/* Also test how alpha channel behaves when drawing lines */
color.alpha = 0x80;
RDrawSegments(img, &segs[9], 7, &color);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 0, 128);
RDestroyImage(img);
img = RCloneImage(tile);
/* Alter lines in all directions (test different slopes) */
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta.alpha = 0;
ROperateSegments(img, RAddOperation, segs, 16, &cdelta);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 64, 128);
RDestroyImage(img);
/* Create a bevel around the icon, and save it for a later use */
img = tmp;
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta.alpha = 0;
ROperateLine(img, RAddOperation, 8, 8, 56, 8, &cdelta);
ROperateLine(img, RAddOperation, 8, 9, 8, 56, &cdelta);
cdelta.red = cdelta.green = cdelta.blue = 40;
cdelta.alpha = 0;
ROperateLine(img, RSubtractOperation, 8, 56, 56, 56, &cdelta);
ROperateLine(img, RSubtractOperation, 56, 8, 56, 55, &cdelta);
RDestroyImage(tile);
tmp = RCloneImage(img);
/* Draw some solid lines over the icon */
color.red = 0xff;
color.green = 0x7d;
color.blue = 0x52;
color.alpha = 0xff;
for (i=16; i<24; i++) {
RDrawLine(img, 9, i, 55, i, &color);
}
/* Also try some lines with alpha over the icon */
color.alpha = 0x80;
for (i=40; i<48; i++) {
RDrawLine(img, 9, i, 55, i, &color);
}
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 0, 192);
RDestroyImage(img);
/* Restore the image with the icon, and alter some lines */
img = tmp;
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta.alpha = 0;
for (i=16; i<24; i++) {
ROperateLine(img, RSubtractOperation, 9, i, 55, i, &cdelta);
}
cdelta.red = cdelta.green = cdelta.blue = 80;
for (i=40; i<48; i++) {
ROperateLine(img, RAddOperation, 9, i, 55, i, &cdelta);
}
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 64, 192);
XSetWindowBackgroundPixmap(dpy, win, back);
XMapRaised(dpy, win);
XClearWindow(dpy, win);
XFlush(dpy);
}
void
testBevel()
{
RImage *img, *tile;
RColor color, from, to;
XSetWindowAttributes val;
Pixmap pix, back;
Window win;
val.background_pixel = ctx->black;
val.colormap = ctx->cmap;
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 140, 140,
0, ctx->depth, InputOutput, ctx->visual,
CWColormap|CWBackPixel, &val);
back = XCreatePixmap(ctx->dpy, ctx->drawable, 140, 140, ctx->depth);
/* Standard gray tile gradient */
from.red = 0xa6;
from.green = 0xa6;
from.blue = 0xb6;
from.alpha = 0xff;
to.red = 0x51;
to.green = 0x55;
to.blue = 0x61;
to.alpha = 0xff;
/* Dark blue tile gradient */
/*from.red = 0x28;
from.green = 0x45;
from.blue = 0x69;
from.alpha = 0xff;
to.red = 0x08;
to.green = 0x24;
to.blue = 0x20;
to.alpha = 0xff;*/
/* Create Background */
img = RCreateImage(140, 140, True);
color.red = 0x28;
color.green = 0x45;
color.blue = 0x69;
color.alpha = 0xff;
RClearImage(img, &color);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 140, 140, 0, 0);
RDestroyImage(img);
tile = RRenderGradient(64, 64, &from, &to, RGRD_DIAGONAL);
img = RCloneImage(tile);
RBevelImage(img, RBEV_SUNKEN);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 3, 3);
RDestroyImage(img);
img = RCloneImage(tile);
RBevelImage(img, RBEV_RAISED);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 73, 3);
RDestroyImage(img);
img = RCloneImage(tile);
RBevelImage(img, RBEV_RAISED2);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 3, 73);
RDestroyImage(img);
img = RCloneImage(tile);
RBevelImage(img, RBEV_RAISED3);
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 73, 73);
RDestroyImage(img);
XSetWindowBackgroundPixmap(dpy, win, back);
XMapRaised(dpy, win);
XClearWindow(dpy, win);
XFlush(dpy);
}
void
drawClip()
{
RImage *img;
RColor color, from, to, tmp;
RColor cdelta, cdelta1;
RSegment segs[20];
XSetWindowAttributes val;
Pixmap pix, back;
Window win;
val.background_pixel = ctx->black;
val.colormap = ctx->cmap;
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 64, 64,
0, ctx->depth, InputOutput, ctx->visual,
CWColormap|CWBackPixel, &val);
back = XCreatePixmap(ctx->dpy, ctx->drawable, 64, 64, ctx->depth);
/* Standard gray tile gradient */
from.red = 0xa6;
from.green = 0xa6;
from.blue = 0xb6;
from.alpha = 0xff;
to.red = 0x51;
to.green = 0x55;
to.blue = 0x61;
to.alpha = 0xff;
/* Dark blue tile gradient */
from.red = 0x28;
from.green = 0x45;
from.blue = 0x69;
from.alpha = 0xff;
to.red = 0x08;
to.green = 0x24;
to.blue = 0x20;
to.alpha = 0xff;
img = RRenderGradient(64, 64, &from, &to, RGRD_DIAGONAL);
RBevelImage(img, RBEV_RAISED3);
#if 1
color.alpha = 255;
color.red = color.green = color.blue = 0;
cdelta.alpha = 0;
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta1.alpha = 0;
cdelta1.red = cdelta1.green = cdelta1.blue = 40;
segs[0].x1 = segs[2].y1 = segs[4].x1 = segs[4].x2 = 63-21;
segs[0].x2 = segs[2].y2 = segs[1].x2 = segs[3].y2 = 63-2;
segs[0].y1 = segs[2].x1 = segs[1].y1 = segs[3].x1 = 2;
segs[0].y2 = segs[2].x2 = segs[6].x1 = segs[6].x2 = 21;
segs[1].x1 = segs[3].y1 = segs[5].x1 = segs[5].x2 = 63-22;
segs[1].y2 = segs[3].x2 = segs[7].x1 = segs[7].x2 = 22;
segs[4].y1 = segs[5].y1 = segs[10].x1 = segs[11].x1 = 0;
segs[4].y2 = segs[5].y2 = segs[10].x2 = segs[11].x2 = 1;
segs[6].y1 = segs[7].y1 = segs[8].x1 = segs[9].x1 = 63-1;
segs[6].y2 = segs[7].y2 = segs[8].x2 = segs[9].x2 = 63;
segs[8].y1 = segs[8].y2 = 21;
segs[9].y1 = segs[9].y2 = 22;
segs[10].y1 = segs[10].y2 = 63-21;
segs[11].y1 = segs[11].y2 = 63-22;
/* Black segments */
RDrawSegments(img, segs, 12, &color);
segs[0].x1 = segs[3].y1 = 63-20;
segs[0].x2 = segs[1].y2 = segs[2].x2 = segs[3].y2 = 63-2;
segs[0].y1 = segs[1].x1 = segs[2].y1 = segs[3].x1 = 2;
segs[1].y1 = segs[2].x1 = 63-23;
segs[0].y2 = segs[3].x2 = 20;
segs[1].x2 = segs[2].y2 = 23;
/* Bevels arround black segments */
ROperateSegments(img, RAddOperation, segs, 2, &cdelta);
ROperateSegments(img, RSubtractOperation, &segs[2], 2 ,&cdelta1);
RGetPixel(img, 63-2, 20, &tmp);
/*RPutPixel(img, 63-1, 23, &tmp);*/
RDrawLine(img, 63-1, 23, 63, 23, &tmp);
RGetPixel(img, 63-23, 2, &tmp);
RDrawLine(img, 63-23, 0, 63-23, 1, &tmp);
RGetPixel(img, 23, 63-2, &tmp);
/*RPutPixel(img, 23, 63-1, &tmp);*/
RDrawLine(img, 23, 63-1, 23, 63, &tmp);
RGetPixel(img, 2, 63-20, &tmp);
RDrawLine(img, 0, 63-23, 1, 63-23, &tmp);
#else
color.alpha = 255;
color.red = color.green = color.blue = 0;
cdelta.alpha = 0;
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta1.alpha = 0;
cdelta1.red = cdelta1.green = cdelta1.blue = 40;
RDrawLine(img, 63-21, 2, 63-2, 21, &color); /* upper 2 black lines */
ROperateLine(img, RAddOperation, 63-20, 2, 63-2, 20, &cdelta); /* the bevel arround them */
ROperateLine(img, RSubtractOperation, 63-22, 2, 63-2, 22, &cdelta1);
RDrawLine(img, 63-21, 0, 63-21, 1, &color); /* upper small black lines */
RDrawLine(img, 63-1, 21, 63, 21, &color);
RGetPixel(img, 63-2, 20, &tmp);
RPutPixel(img, 63-1, 22, &tmp);
RGetPixel(img, 2, 63-22, &tmp);
RDrawLine(img, 63-22, 0, 63-22, 1, &tmp);
RDrawLine(img, 2, 63-21, 21, 63-2, &color); /* lower 2 black lines */
ROperateLine(img, RSubtractOperation, 2, 63-20, 20, 63-2, &cdelta1); /* the bevel arround them */
ROperateLine(img, RAddOperation, 2, 63-22, 22, 63-2, &cdelta);
RDrawLine(img, 21, 63-1, 21, 63, &color); /* lower small black lines */
RDrawLine(img, 0, 63-21, 1, 63-21, &color);
ROperateLine(img, RAddOperation, 22, 63-1, 22, 63, &cdelta);
/*ROperateLine(img, RAddOperation, 22, 63-1, 22, 63, &cdelta);*/ /* the bevel arround them */
ROperateLine(img, RSubtractOperation, 0, 63-22, 1, 63-22, &cdelta1);
#endif
RConvertImage(ctx, img, &pix);
XCopyArea(dpy, pix, back, ctx->copy_gc, 0, 0, 64, 64, 0, 0);
RDestroyImage(img);
XSetWindowBackgroundPixmap(dpy, win, back);
XMapRaised(dpy, win);
XClearWindow(dpy, win);
XFlush(dpy);
}
void
benchmark()
{
RImage *img;
RColor color;
RColor cdelta;
double t1, t2, total, d1=0, d2=0, d3=0;
struct timeval timev;
int i, j;
puts("Starting benchmark");
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
img = RCreateImage(1024, 768, True);
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("Image created in %f sec\n", total);
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
color.red = 0x28;
color.green = 0x45;
color.blue = 0x69;
color.alpha = 0xff;
RClearImage(img, &color);
color.red = 0xff;
color.green = 0x7d;
color.blue = 0x52;
color.alpha = 0xff;
cdelta.red = cdelta.green = cdelta.blue = 80;
cdelta.alpha = 0;
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("Image filled in %f sec\n", total);
for(j=1; j<6; j++) {
printf("Pass %d...\n", j);
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
color.alpha = 0xff;
for (i=0; i< 10000; i++) {
RDrawLine(img, 0, i%64, i%64, 63, &color);
}
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("Drawing 10000 lines in %f sec\n", total);
d1 += total;
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
color.alpha = 80;
for (i=0; i< 10000; i++) {
RDrawLine(img, 0, i%64, i%64, 63, &color);
}
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("Drawing 10000 lines with alpha in %f sec\n", total);
d2+=total;
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
for (i=0; i< 10000; i++) {
ROperateLine(img, RAddOperation, 0, i%64, i%64, 63, &cdelta);
}
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("Altering 10000 lines in %f sec\n", total);
d3+=total;
}
printf("Average: %f, %f, %f\n", d1/5, d2/5, d3/5);
RDestroyImage(img);
}
void main(int argc, char **argv)
{
RContextAttributes attr;
int visualID = -1;
ProgName = strrchr(argv[0],'/');
if (!ProgName)
ProgName = argv[0];
else
ProgName++;
dpy = XOpenDisplay("");
if (!dpy) {
puts("cant open display");
exit(1);
}
attr.flags = RC_RenderMode | RC_ColorsPerChannel;
attr.render_mode = RM_DITHER;
attr.colors_per_channel = 4;
if (visualID >= 0) {
attr.flags |= RC_VisualID;
attr.visualid = visualID;
}
ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);
if (!ctx) {
printf("could not initialize graphics library context: %s\n",
RErrorString);
exit(1);
}
/* Here are the things we want to test */
testDraw();
testBevel();
/*
drawClip();
benchmark();
*/
getchar();
}

207
wrlib/testgrad.c Normal file
View File

@@ -0,0 +1,207 @@
#include "wraster.h"
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef BENCH
#include <sys/time.h>
#include <time.h>
#endif
Display *dpy;
Window win;
RContext *ctx;
RImage *imgh, *imgv, *imgd;
Pixmap pix;
char *ProgName;
void
print_help()
{
printf("usage: %s [-options] color1 [color2 ...]\n", ProgName);
puts("options:");
puts(" -m match colors");
puts(" -d dither colors (default)");
puts(" -c <cpc> colors per channel to use");
puts(" -v <vis-id> visual id to use");
}
void main(int argc, char **argv)
{
RContextAttributes attr;
RColor **colors = NULL;
int i, rmode = RM_DITHER, ncolors = 0, cpc = 4;
char **color_name;
XColor color;
XSetWindowAttributes val;
int visualID = -1;
#ifdef BENCH
double t1, t2, total, t, rt;
struct timeval timev;
#endif
ProgName = strrchr(argv[0],'/');
if (!ProgName)
ProgName = argv[0];
else
ProgName++;
color_name = (char **) malloc(sizeof(char*) * argc);
if(color_name == NULL) {
fprintf(stderr, "Cannot allocate memory!\n");
exit(1);
}
if (argc>1) {
for (i=1; i<argc; i++) {
if (strcmp(argv[i], "-m")==0) {
rmode = RM_MATCH;
} else if (strcmp(argv[i], "-d")==0) {
rmode = RM_DITHER;
} else if (strcmp(argv[i], "-c")==0) {
i++;
if (i>=argc) {
fprintf(stderr, "too few arguments for %s\n", argv[i-1]);
exit(0);
}
if (sscanf(argv[i], "%i", &cpc)!=1) {
fprintf(stderr, "bad value for colors per channel: \"%s\"\n", argv[i]);
exit(0);
}
} else if (strcmp(argv[i], "-v")==0) {
i++;
if (i>=argc) {
fprintf(stderr, "too few arguments for %s\n", argv[i-1]);
exit(0);
}
if (sscanf(argv[i], "%i", &visualID)!=1) {
fprintf(stderr, "bad value for visual ID: \"%s\"\n", argv[i]);
exit(0);
}
} else if (argv[i][0] != '-') {
color_name[ncolors++] = argv[i];
} else {
print_help();
exit(1);
}
}
}
if (ncolors == 0) {
print_help();
exit(1);
}
dpy = XOpenDisplay("");
if (!dpy) {
puts("cant open display");
exit(1);
}
attr.flags = RC_RenderMode | RC_ColorsPerChannel;
attr.render_mode = rmode;
attr.colors_per_channel = cpc;
if (visualID >= 0) {
attr.flags |= RC_VisualID;
attr.visualid = visualID;
}
ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);
if (!ctx) {
printf("could not initialize graphics library context: %s\n",
RErrorString);
exit(1);
}
colors = malloc(sizeof(RColor*)*(ncolors+1));
for (i=0; i<ncolors; i++) {
if (!XParseColor(dpy, ctx->cmap, color_name[i], &color)) {
printf("could not parse color \"%s\"\n", color_name[i]);
exit(1);
}
else {
colors[i] = malloc(sizeof(RColor));
colors[i]->red = color.red >> 8;
colors[i]->green = color.green >> 8;
colors[i]->blue = color.blue >> 8;
printf("0x%02x%02x%02x\n", colors[i]->red, colors[i]->green,
colors[i]->blue);
}
}
colors[i] = NULL;
val.background_pixel = ctx->black;
val.colormap = ctx->cmap;
#ifdef BENCH
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 250, 250,
0, ctx->depth, InputOutput, ctx->visual,
CWColormap|CWBackPixel, &val);
#else
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 10, 10, 750, 250,
0, ctx->depth, InputOutput, ctx->visual,
CWColormap|CWBackPixel, &val);
#endif
XMapRaised(dpy, win);
XFlush(dpy);
#ifdef BENCH
rt = 0;
gettimeofday(&timev, NULL);
t = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
for (i=0; i<9; i++) {
if (i>0)
printf("\nrepeating...\n\n");
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
if (i%3==0)
imgh = RRenderMultiGradient(250, 250, colors, RGRD_HORIZONTAL);
else if (i%3==1)
imgh = RRenderMultiGradient(250, 250, colors, RGRD_VERTICAL);
else
imgh = RRenderMultiGradient(250, 250, colors, RGRD_DIAGONAL);
gettimeofday(&timev, NULL);
t2 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t2 - t1;
printf("gradient rendered in %f sec\n", total);
RConvertImage(ctx, imgh, &pix);
gettimeofday(&timev, NULL);
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
total = t1 - t2;
rt += total;
printf("image converted in %f sec\n", total);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0);
XFlush(dpy);
}
t1 = (double)timev.tv_sec + (((double)timev.tv_usec)/1000000);
printf("------------------------------------------\n");
printf("%i images processed in %f sec\n", i, t1-t);
printf("average time per convertion %f sec\n", rt/i);
printf("------------------------------------------\n");
#else
imgh = RRenderMultiGradient(250, 250, colors, RGRD_HORIZONTAL);
imgv = RRenderMultiGradient(250, 250, colors, RGRD_VERTICAL);
imgd = RRenderMultiGradient(250, 250, colors, RGRD_DIAGONAL);
RConvertImage(ctx, imgh, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 0, 0);
RConvertImage(ctx, imgv, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 250, 0);
RConvertImage(ctx, imgd, &pix);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, 250, 250, 500, 0);
XFlush(dpy);
#endif
getchar();
}

141
wrlib/tiff.c Normal file
View File

@@ -0,0 +1,141 @@
/* tiff.c - load TIFF image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#ifdef USE_TIFF
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tiff.h>
#include <tiffio.h>
#include "wraster.h"
RImage*
RLoadTIFF(RContext *context, char *file, int index)
{
RImage *image = NULL;
TIFF *tif;
int i;
unsigned char *r, *g, *b, *a;
uint16 alpha, amode;
uint32 width, height;
uint32 *data, *ptr;
uint16 extrasamples;
uint16 *sampleinfo;
tif = TIFFOpen(file, "r");
if (!tif)
return NULL;
/* seek index */
i = index;
while (i>0) {
if (!TIFFReadDirectory(tif)) {
sprintf(RErrorString, "bad index %i for file \"%s\"", index, file);
TIFFClose(tif);
return NULL;
}
i--;
}
/* get info */
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
&extrasamples, &sampleinfo);
alpha = (extrasamples == 1 &&
((sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA) || (sampleinfo[0] == EXTRASAMPLE_UNASSALPHA)));
amode = (extrasamples == 1 && sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
if (width<1 || height<1) {
sprintf(RErrorString, "bad data in file \"%s\"", file);
TIFFClose(tif);
return NULL;
}
/* read data */
ptr = data = (uint32*)_TIFFmalloc(width * height * sizeof(uint32));
if (!data) {
sprintf(RErrorString, "out of memory");
} else {
if (!TIFFReadRGBAImage(tif, width, height, data, 0)) {
sprintf(RErrorString, "error reading file \"%s\"", file);
} else {
/* convert data */
image = RCreateImage(width, height, alpha);
if (image) {
int x, y;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
/* data seems to be stored upside down */
data += width * (height-1);
for (y=0; y<height; y++) {
for (x=0; x<width; x++) {
*(r) = (*data) & 0xff;
*(g) = (*data >> 8) & 0xff;
*(b) = (*data >> 16) & 0xff;
if (alpha) {
*(a) = (*data >> 24) & 0xff;
if (amode && (*a > 0)) {
*r = (*r * 255) / *(a);
*g = (*g * 255) / *(a);
*b = (*b * 255) / *(a);
}
a++;
}
r++; g++; b++;
data++;
}
data -= 2*width;
}
}
}
_TIFFfree(ptr);
}
TIFFClose(tif);
return image;
}
#endif /* USE_TIFF */

121
wrlib/tile.xpm Normal file
View File

@@ -0,0 +1,121 @@
/* XPM */
static char * image_name[] = {
"64 64 54 1",
" c white",
". c #000000000000",
"X c #514461856185",
"o c #A289A289B2CA",
"O c #A289A289A289",
"+ c #A2899248B2CA",
"@ c #9248A289A289",
"# c #A2899248A289",
"$ c #92489248A289",
"% c #924892489248",
"& c #92488207A289",
"* c #820792489248",
"= c #924882079248",
"- c #820782079248",
"; c #820782078207",
": c #820771C69248",
"> c #618551446185",
", c #9248A289B2CA",
"< c #92489248B2CA",
"1 c #82079248A289",
"2 c #82078207A289",
"3 c #71C682079248",
"4 c #71C682078207",
"5 c #514451446185",
"6 c #514451445144",
"7 c #820771C68207",
"8 c #410351445144",
"9 c #514441035144",
"0 c #71C671C69248",
"q c #71C671C68207",
"w c #71C671C671C6",
"e c #410341035144",
"r c #71C661858207",
"t c #618571C68207",
"y c #410351444103",
"u c #410341034103",
"i c #618571C671C6",
"p c #410330C24103",
"a c #30C241034103",
"s c #71C6618571C6",
"d c #6185618571C6",
"f c #618561858207",
"g c #30C230C230C2",
"h c #618561856185",
"j c #30C230C24103",
"k c #5144618571C6",
"l c #30C2410330C2",
"z c #6185514471C6",
"x c #208130C230C2",
"c c #30C2208130C2",
"v c #5144514471C6",
"b c #2081208130C2",
"n c #208120812081",
"m c #410330C25144",
" .",
" X.",
" oOoO+O+O+O+@#$+@#$#$#$$$#$$%&%&%&%&*&*&*=-=*=-=-=--;---;:;:;>.",
" oo@o,o@o@o@+@+@<@$@$@$@$@$1$$$*$*$*&*&*2*&*2*-*-*-----3-3-4-X.",
" oO+OoO#O+@#@#@#$#@#$#%#$$%$%$%&%&*=%&*=*=*=-=-=--;-;-;:;:;:;5.",
" ,ooo@+@+@+@+@<@#@<@$$$$$$$$$*$1$*&*&*&*&*2*---*-----3---4:4:6.",
" +O+O+O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=*=---=--;---;:;:4:;:45.",
" @o@o@o@+@+@<@$@$@$$$@$1$1$*$*$*&*&*2*=*2*-*-*-----4-3-4:4-4:6.",
" +O#O+@#@#@#$#$#$#%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:4745.",
" @+@+@+@+@<@#@$@$$$$$$$$$*$*$*&*&*&*&*2*---*-----3---4:4:4:4:8.",
" #O+@#$#@#$#$#$$%$$$%&%&%&%&*=*&*=-=-=---=--;:;-;:;:4:4:474:49.",
" @o@<@+@<@$@$@$$$$$1$1$*$*$*&*&*2*=*2*-*-*-----4-4-4:4:4:4:408.",
" +@#@#@#$#$#$$%#%$%&%$%&%&*=*&*=*=*=-=-=--;-;-;:;:;:;:474747q9.",
" @+@+@<@$$$@$$$$$1$$$*&*$*&*&*&*&*2*---------3-3-4:4:4:4:404q8.",
" #$#@#$#$#$$%$$$%&%&%&%&*=-&*=-=-=---=--;:;:;:;:4:4:474:47q7q9.",
" @#@<@$@$@$$$$$*$1$*$*$*&*&*2*-*2*-*-*-3---4-4-4:4:4:4:404q4q8.",
" #@#$#$#$$%$%$%&%$%&%&*=*=*=-=*=-=;=--;-;-;:;:47;:474747q7q7q9.",
" @<@$$$@$$$$$1$$$*&*&*&*&*&*=*2*---------4-3-4:4:4:4:404qq04q8.",
" #$#$#$$%$%$%&%&%&%&*=-&*=-=-=------;:;:;:;:4:4:47q747qqq7qqq9.",
" @$@$@$$$$$*$1$*$*$*&*&*2*-*-*---*-3-3-4-4-4:4:4:4:404q4q4qqq8.",
" #$#$$%$%$%&%&%&%&*=*=*=-=-=-=;=--;:;-;:;:474:474747q7q7qqwqw9.",
" $$@$$$$$*$$$*&*&*&*&*2*=*2*---------4-3-4:4:4:4:404qqq4qqqqqe.",
" #$$%$%$%&%&*&%&*=-&*=-=-=------;:;:;:;:4:4:47q7q7qqq7qqwrqqw9.",
" @$$$$$*$1$*&*$*2*&*2*-*-*-----3-3-4-4-4:4:404:404q4q4qqqqqtqy.",
" $%$%$%&%&%=%&*=*=*=-=-=--;=--;:;-;:;:474:474747q7q7qqwqwqwrwe.",
" $$$$*$1$*&*&*&*&*2*--2*-----3---4:3-4:4:4:4:404qqqqqqqqqtqtqu.",
" &%$%&%&*&*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqq7qqwrqrwrwrip.",
" $$*$*$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q404q4q4qtqqqiqtqiru.",
" $%&%&*=%&*=*=*=-=-=--;-;-;:;-;:;:474:47q747q7q7qqwqwqwrwrirwu.",
" *$1$*&*&*&*&*2*---*-----3---4:4:4:4:4:4:404qqqqqqqqqtqtqirira.",
" &%&*=*&*=-=*=-=-=--;---;:;:;:;:4:4:47q7q7qqqqqqwrqrwrwriririp.",
" *$*&*&*2*&*2*-*-*-----3-3-4-4-4:4:404q4q4qqq4qtqtqiqiqiriqira.",
" &*=*&*=*=*=-=-=--;-;-;:;:;:;:474:47q7q7q7q7qqwrwqwrwrirwrisip.",
" *&*&*&*&*2*---*-----3---4:4:4:4:404:404qqqqqqqqqtqtqiriririra.",
" =*&*=-=*=---=--;---;:;:4:;:474:47q7q7qqqqqqwrwrwrwriririsdrdp.",
" *&*2*=*2*-*-*-----4-3-4:4-4:4:404q4q4qqqqqtqtqiqiqiriqifirifa.",
" &*=*=*=-=-=--;-;-;:;:;:;:474747q7q7qqq7qqwrwqwrwrirwrisisisdp.",
" *&*&*2*---*-----3-3-4:4:4:4:404qq04qqqqqtqqqirtqiririririfida.",
" =-=-=---=--;:;-;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdrdsdddp.",
" *=*2*-*-*-----4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiriqifififidida.",
" =*=-=-=--;-;-;:;:4:;:474747q7q7qqwqwqwrwqwrwrirwrisdsisdsdsdp.",
" *2*---------4-3-4:4:4:4:404qq04qqqqqtqqqiririririririfidddddg.",
" =---=--;:;:;:;:4:4:474:47q7q7qqqqqqwrwrwrwriririsdsdsddddddhj.",
" *---*-3---4-4-4:4:4:4:404q4q4qqqqqtqtqiqiqiririfififidddidkdl.",
" =;=--;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrirwrisdsdsdsdsddhzhj.",
" --------4-3-4:4:4:4:404qq04qqqqqtqqqiririririfirifidddddddddx.",
" ---;:;:;:;:4:4:47q747qqq7qqwqqqwrwrirwriririsdsdsddddddhzhzhc.",
" --3-3-4-4-4:4:4:4:404q4q4qqqqqtqtqiriqiririfififidddddkdkdXdx.",
" -;:;-;:;:474:474747q7q7qqwqwqwrwrwrwrisisisdsdsdddsddhzhdhzhg.",
" ----4-3-4:4:4:4:404qqq4qqqqqtqtqiriririrififdfidddddkdddkzkdx.",
" :;:;:;:4:4:47q7q7qqq7qqwrqqwrwriririririsdsdsddddddhzhzhzhzXc.",
" 3-4-4-4:4:404:404q4q4qqqqqtqtqiriqiririfidididddddkdkdXdXdXzx.",
" -;:;:474:47q747q7q7qqwqwqwrwrirwrisisisdsdsddddddhzhdhzhzXzhc.",
" 4:4-4:4:4:4:404qqqqqqqqqtqtqiriririrififdfidddddkdddkzkdXzXzx.",
" :;:4:4:47q7q7qqq7qqwrqrwrwriririsirisdsdsddddddhzhzhzhzXzXzXc.",
" 4-4:4:404q404qqq4qtqqqiqtqiriqiririfidididddddkdkdXdXdXzXzXvx.",
" :474:47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddddddhzhzhzhzXzhzX>5c.",
" 4:4:4:4:404qqqqqqqqqtqtqiririririfiddfidddddkdddXzkdXzXzXvXzx.",
" :4:47q7q7qqqqqqwrwrwrwriririsdrisdddsddddddhzhzXzhzXzXzX>5>5c.",
" 4:404q4q4qqqqqtqtqiqiqiriqiririfidididddddkdkdXzXdXzXzXvXvXvx.",
" :47q7q7q7q7qqwrwqwrwrirwrisisisdsdsddhdddhzhzhzhzXzXzX>5>5>5b.",
" 404:404qqqqqqqqqiqtqiririririfidddidddddkdkdXzkzXzXzXvXv5vX5n.",
" >65656569698989y9e9u9ueumueupupapaplpgjgjgjgcgcgcgcxcbcncnbnb.",
" ..............................................................."};

62
wrlib/view.c Normal file
View File

@@ -0,0 +1,62 @@
#include "wraster.h"
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include "tile.xpm"
Display *dpy;
Window win;
RContext *ctx;
RImage *img;
Pixmap pix;
void main(int argc, char **argv)
{
RContextAttributes attr;
dpy = XOpenDisplay("");
if (!dpy) {
puts("cant open display");
exit(1);
}
attr.flags = RC_RenderMode | RC_ColorsPerChannel;
attr.render_mode = RM_DITHER;
attr.colors_per_channel = 4;
ctx = RCreateContext(dpy, DefaultScreen(dpy), &attr);
if (argc<2)
img = RGetImageFromXPMData(ctx, image_name);
else
img = RLoadImage(ctx, argv[1], argc>2 ? atol(argv[2]) : 0);
if (!img) {
puts(RErrorString);
exit(1);
}
if (!RConvertImage(ctx, img, &pix)) {
puts(RErrorString);
exit(1);
}
win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 10, 10, img->width,
img->height, 0, 0, 0);
XSelectInput(dpy, win, ExposureMask);
XMapRaised(dpy, win);
XSync(dpy, False);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height,
0, 0);
XSync(dpy, False);
while (1) {
XEvent ev;
XNextEvent(dpy, &ev);
if (ev.type==Expose)
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height,
0, 0);
}
XFlush(dpy);
getchar();
}

364
wrlib/wraster.h Normal file
View File

@@ -0,0 +1,364 @@
/*
* Raster graphics library
*
* Copyright (c) 1997, 1998 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Environment variables:
*
* WRASTER_GAMMA <rgamma>/<ggamma>/<bgamma>
* gamma correction value. Must be greater than 0
* Only for PseudoColor visuals.
*
* Default:
* WRASTER_GAMMA 1/1/1
*
*
* If you want a specific value for a screen, append the screen number
* preceded by a hash to the variable name as in
* WRASTER_GAMMA#1
* for screen number 1
*/
#ifndef RLRASTER_H_
#define RLRASTER_H_
/* version of the header for the library: 0.8 */
#define WRASTER_HEADER_VERSION 8
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef XSHM
#include <X11/extensions/XShm.h>
#endif
/* RM_MATCH or RM_DITHER */
#define RC_RenderMode (1<<0)
/* number of colors per channel for colormap in PseudoColor mode */
#define RC_ColorsPerChannel (1<<1)
/* do gamma correction */
#define RC_GammaCorrection (1<<2)
/* visual id to use */
#define RC_VisualID (1<<3)
/* shared memory usage */
#define RC_UseSharedMemory (1<<4)
/* use default instead of best visual */
#define RC_DefaultVisual (1<<5)
typedef struct RContextAttributes {
int flags;
int render_mode;
int colors_per_channel; /* for PseudoColor */
float rgamma; /* gamma correction for red, */
float ggamma; /* green, */
float bgamma; /* and blue */
VisualID visualid; /* visual ID to use */
int use_shared_memory; /* True of False */
} RContextAttributes;
/*
* describes a screen in terms of depth, visual, number of colors
* we can use, if we should do dithering, and what colors to use for
* dithering.
*/
typedef struct RContext {
Display *dpy;
int screen_number;
Colormap cmap;
RContextAttributes *attribs;
GC copy_gc;
Visual *visual;
int depth;
Window drawable; /* window to pass for XCreatePixmap().*/
/* generally = root */
int vclass;
unsigned long black;
unsigned long white;
int red_offset; /* only used in 24bpp */
int green_offset;
int blue_offset;
/* only used for pseudocolor and grayscale */
int ncolors; /* total number of colors we can use */
XColor *colors; /* internal colormap */
} RContext;
typedef struct RColor {
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;
} RColor;
typedef struct RHSVColor {
unsigned short hue; /* 0-359 */
unsigned char saturation; /* 0-255 */
unsigned char value; /* 0-255 */
} RHSVColor;
typedef struct RPoint {
int x, y;
} RPoint;
typedef struct RSegment {
int x1, y1, x2, y2;
} RSegment;
/*
* internal 24bit+alpha image representation
*/
typedef struct RImage {
unsigned width, height; /* size of the image */
RColor background; /* background color */
unsigned char *data[4]; /* image data (R,G,B,A) */
} RImage;
/*
* internal wrapper for XImage. Used for shm abstraction
*/
typedef struct RXImage {
XImage *image;
#ifdef XSHM
XShmSegmentInfo info;
int is_shared;
#endif
} RXImage;
/* note that not all operations are supported in all functions */
enum {
RClearOperation, /* clear with 0 */
RCopyOperation,
RNormalOperation, /* same as combine */
RAddOperation,
RSubtractOperation
};
/* image display modes */
enum {
RDitheredRendering = 0,
RBestMatchRendering = 1
};
/* bw compat */
#define RM_DITHER RDitheredRendering
#define RM_MATCH RBestMatchRendering
enum {
RAbsoluteCoordinates = 0,
RRelativeCoordinates = 1
};
enum {
RSunkenBevel = -1,
RRaisedBevel = 1
};
/* bw compat */
#define RBEV_SUNKEN RSunkenBevel
/* 1 pixel wide */
#define RBEV_RAISED RRaisedBevel
/* 1 pixel wide on top/left 2 on bottom/right */
#define RBEV_RAISED2 2
/* 2 pixel width */
#define RBEV_RAISED3 3
enum {
RHorizontalGradient = 2,
RVerticalGradient = 3,
RDiagonalGradient = 4
};
/* for backwards compatibility */
#define RGRD_HORIZONTAL RHorizontalGradient
#define RGRD_VERTICAL RVerticalGradient
#define RGRD_DIAGONAL RDiagonalGradient
/*
* Returns a NULL terminated array of strings containing the
* supported formats, such as: TIFF, XPM, PNG, JPEG, PPM, GIF
*/
char **RSupportedFileFormats(void);
void RFreeStringList(char **list);
/*
* Xlib contexts
*/
RContext *RCreateContext(Display *dpy, int screen_number,
RContextAttributes *attribs);
Bool RGetClosestXColor(RContext *context, RColor *color, XColor *retColor);
/*
* RImage creation
*/
RImage *RCreateImage(unsigned width, unsigned height, int alpha);
RImage *RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask);
RImage *RCreateImageFromDrawable(RContext *context, Drawable drawable,
Pixmap mask);
RImage *RLoadImage(RContext *context, char *file, int index);
void RDestroyImage(RImage *image);
RImage *RGetImageFromXPMData(RContext *context, char **data);
/*
* Area manipulation
*/
RImage *RCloneImage(RImage *image);
RImage *RGetSubImage(RImage *image, int x, int y, unsigned width,
unsigned height);
void RCombineImageWithColor(RImage *image, RColor *color);
void RCombineImages(RImage *image, RImage *src);
void RCombineArea(RImage *image, RImage *src, int sx, int sy, unsigned width,
unsigned height, int dx, int dy);
void RCombineImagesWithOpaqueness(RImage *image, RImage *src, int opaqueness);
void RCombineAreaWithOpaqueness(RImage *image, RImage *src, int sx, int sy,
unsigned width, unsigned height, int dx, int dy,
int opaqueness);
RImage *RScaleImage(RImage *image, unsigned new_width, unsigned new_height);
RImage *RMakeTiledImage(RImage *tile, unsigned width, unsigned height);
RImage* RMakeCenteredImage(RImage *image, unsigned width, unsigned height,
RColor *color);
/*
* Drawing
*/
Bool RGetPixel(RImage *image, int x, int y, RColor *color);
void RPutPixel(RImage *image, int x, int y, RColor *color);
void ROperatePixel(RImage *image, int operation, int x, int y, RColor *color);
void RPutPixels(RImage *image, RPoint *points, int npoints, int mode,
RColor *color);
void ROperatePixels(RImage *image, int operation, RPoint *points,
int npoints, int mode, RColor *color);
int RDrawLine(RImage *image, int x0, int y0, int x1, int y1, RColor *color);
int ROperateLine(RImage *image, int operation, int x0, int y0, int x1, int y1,
RColor *color);
void RDrawLines(RImage *image, RPoint *points, int npoints, int mode,
RColor *color);
void ROperateLines(RImage *image, int operation, RPoint *points, int npoints,
int mode, RColor *color);
void RDrawSegments(RImage *image, RSegment *segs, int nsegs, RColor *color);
void ROperateSegments(RImage *image, int operation, RSegment *segs, int nsegs,
RColor *color);
/*
* Color convertion
*/
void RRGBtoHSV(RColor *color, RHSVColor *hsv);
void RHSVtoRGB(RHSVColor *hsv, RColor *rgb);
/*
* Painting
*/
int RClearImage(RImage *image, RColor *color);
int RBevelImage(RImage *image, int bevel_type);
RImage *RRenderGradient(unsigned width, unsigned height, RColor *from,
RColor *to, int style);
RImage *RRenderMultiGradient(unsigned width, unsigned height, RColor **colors,
int style);
/*
* Convertion into X Pixmaps
*/
int RConvertImage(RContext *context, RImage *image, Pixmap *pixmap);
int RConvertImageMask(RContext *context, RImage *image, Pixmap *pixmap,
Pixmap *mask, int threshold);
/*
* misc. utilities
*/
RXImage *RCreateXImage(RContext *context, int depth,
unsigned width, unsigned height);
void RDestroyXImage(RContext *context, RXImage *ximage);
void RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage,
int src_x, int src_y, int dest_x, int dest_y,
unsigned width, unsigned height);
/****** Global Variables *******/
/*
* Where error strings are stored
*/
extern char RErrorString[];
#endif

169
wrlib/xpixmap.c Normal file
View File

@@ -0,0 +1,169 @@
/* xpixmap.c - Make RImage from Pixmap or XImage
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "wraster.h"
static int
get_shifts(unsigned long mask)
{
int i=0;
while (mask) {
mask>>=1;
i++;
}
return i;
}
RImage*
RCreateImageFromXImage(RContext *context, XImage *image, XImage *mask)
{
RImage *img;
int x, y;
unsigned long pixel;
unsigned char *r, *g, *b, *a;
int rshift, gshift, bshift;
int rmask, gmask, bmask;
RErrorString[0] = 0;
assert(image!=NULL);
assert(image->format==ZPixmap);
assert(!mask || mask->format==ZPixmap);
img = RCreateImage(image->width, image->height, mask!=NULL);
if (!img) {
return NULL;
}
/* I don't know why, but XGetImage() for pixmaps don't set the
* {red,green,blue}_mask values correctly. This will not
* work for imageis of depth different than the root window
* one used in wrlib
*/
if (context->depth==image->depth) {
rmask = context->visual->red_mask;
gmask = context->visual->green_mask;
bmask = context->visual->blue_mask;
} else {
rmask = image->red_mask;
gmask = image->green_mask;
bmask = image->blue_mask;
}
/* how many bits to shift to normalize the color into 8bpp */
rshift = get_shifts(rmask) - 8;
gshift = get_shifts(gmask) - 8;
bshift = get_shifts(bmask) - 8;
r = img->data[0];
g = img->data[1];
b = img->data[2];
a = img->data[3];
#define NORMALIZE_RED(pixel) ((rshift>0) ? ((pixel) & rmask) >> rshift \
: ((pixel) & rmask) << -rshift)
#define NORMALIZE_GREEN(pixel) ((gshift>0) ? ((pixel) & gmask) >> gshift \
: ((pixel) & gmask) << -gshift)
#define NORMALIZE_BLUE(pixel) ((bshift>0) ? ((pixel) & bmask) >> bshift \
: ((pixel) & bmask) << -bshift)
for (y = 0; y < image->height; y++) {
for (x = 0; x < image->width; x++) {
pixel = XGetPixel(image, x, y);
*(r++) = NORMALIZE_RED(pixel);
*(g++) = NORMALIZE_GREEN(pixel);
*(b++) = NORMALIZE_BLUE(pixel);
}
}
if (mask && a) {
for (y = 0; y < mask->height; y++) {
for (x = 0; x < mask->width; x++) {
if (XGetPixel(mask, x, y)) {
*(a++) = 0xff;
} else {
*(a++) = 0xff;
}
}
}
}
return img;
}
RImage*
RCreateImageFromDrawable(RContext *context, Drawable drawable, Pixmap mask)
{
RImage *image;
XImage *pimg, *mimg;
unsigned int w, h, bar;
int foo;
Window baz;
RErrorString[0] = 0;
assert(drawable!=None);
if (!XGetGeometry(context->dpy, drawable, &baz, &foo, &foo,
&w, &h, &bar, &bar)) {
printf("wrlib:invalid window or pixmap passed to RCreateImageFromPixmap\n");
return NULL;
}
pimg = XGetImage(context->dpy, drawable, 0, 0, w, h, AllPlanes,
ZPixmap);
if (!pimg) {
sprintf(RErrorString, "could not get image");
return NULL;
}
mimg = NULL;
if (mask) {
if (XGetGeometry(context->dpy, mask, &baz, &foo, &foo,
&w, &h, &bar, &bar)) {
mimg = XGetImage(context->dpy, mask, 0, 0, w, h, AllPlanes,
ZPixmap);
}
}
image = RCreateImageFromXImage(context, pimg, mimg);
XDestroyImage(pimg);
if (mimg)
XDestroyImage(mimg);
return image;
}

228
wrlib/xpm.c Normal file
View File

@@ -0,0 +1,228 @@
/* xpm.c - load XPM image from file
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#ifdef USE_XPM
#include <X11/Xlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/xpm.h>
#include "wraster.h"
RImage*
RGetImageFromXPMData(RContext *context, char **data)
{
Display *dpy = context->dpy;
Colormap cmap = context->cmap;
RImage *image;
XpmImage xpm;
unsigned char *color_table[3];
unsigned char *r, *g, *b, *a;
int *p;
int i;
int transp=-1;
RErrorString[0] = 0;
if (XpmCreateXpmImageFromData(data, &xpm, (XpmInfo *)NULL)!=XpmSuccess) {
sprintf(RErrorString, "error converting XPM data");
return NULL;
}
if (xpm.height<1 || xpm.width < 1) {
sprintf(RErrorString, "can't convert XPM data. Size too weird");
XpmFreeXpmImage(&xpm);
return NULL;
}
if (xpm.colorTable==NULL) {
sprintf(RErrorString, "error converting XPM data");
XpmFreeXpmImage(&xpm);
return NULL;
}
image = RCreateImage(xpm.width, xpm.height, True);
if (!image) {
sprintf(RErrorString, ":could not create RImage");
XpmFreeXpmImage(&xpm);
return NULL;
}
/* make color table */
for (i=0; i<3; i++) {
color_table[i] = malloc(xpm.ncolors*sizeof(char));
if (!color_table[i]) {
for (i=i-1;i>=0; i--) {
if (color_table[i])
free(color_table[i]);
}
RDestroyImage(image);
sprintf(RErrorString, "out of memory while converting XPM data");
XpmFreeXpmImage(&xpm);
return NULL;
}
}
for (i=0; i<xpm.ncolors; i++) {
XColor xcolor;
if (strncmp(xpm.colorTable[i].c_color,"None",4)==0) {
color_table[0][i]=0;
color_table[1][i]=0;
color_table[2][i]=0;
transp = i;
continue;
}
if (XParseColor(dpy, cmap, xpm.colorTable[i].c_color, &xcolor)) {
color_table[0][i] = xcolor.red>>8;
color_table[1][i] = xcolor.green>>8;
color_table[2][i] = xcolor.blue>>8;
} else {
color_table[0][i]=0xbe;
color_table[1][i]=0xbe;
color_table[2][i]=0xbe;
}
}
memset(image->data[3], 255, xpm.width*xpm.height);
/* convert pixmap to RImage */
p = (int*)xpm.data;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (i=0; i<xpm.width*xpm.height; i++) {
if (*p==transp)
*a=0;
a++;
*(r++)=color_table[0][*p];
*(g++)=color_table[1][*p];
*(b++)=color_table[2][*p];
p++;
}
for(i=0; i<3; i++) {
free(color_table[i]);
}
XpmFreeXpmImage(&xpm);
return image;
}
RImage*
RLoadXPM(RContext *context, char *file, int index)
{
Display *dpy = context->dpy;
Colormap cmap = context->cmap;
RImage *image;
XpmImage xpm;
unsigned char *color_table[3];
unsigned char *r, *g, *b, *a;
int *p;
int i;
int transp=-1;
RErrorString[0] = 0;
if (XpmReadFileToXpmImage(file, &xpm, (XpmInfo *)NULL)!=XpmSuccess) {
sprintf(RErrorString, "error loading XPM file \"%s\"", file);
return NULL;
}
if (xpm.height<1 || xpm.width < 1) {
sprintf(RErrorString, "can't load XPM file \"%s\". Size too weird",
file);
XpmFreeXpmImage(&xpm);
return NULL;
}
if (xpm.colorTable==NULL) {
sprintf(RErrorString, "error loading XPM file \"%s\"", file);
XpmFreeXpmImage(&xpm);
return NULL;
}
image = RCreateImage(xpm.width, xpm.height, True);
if (!image) {
strcat(RErrorString, ":could not create RImage");
XpmFreeXpmImage(&xpm);
return NULL;
}
/* make color table */
for (i=0; i<3; i++) {
color_table[i] = malloc(xpm.ncolors*sizeof(char));
if (!color_table[i]) {
for (i=i-1;i>=0; i--) {
if (color_table[i])
free(color_table[i]);
}
RDestroyImage(image);
sprintf(RErrorString, "out of memory while loading file \"%s\"",
file);
XpmFreeXpmImage(&xpm);
return NULL;
}
}
for (i=0; i<xpm.ncolors; i++) {
XColor xcolor;
if (strncmp(xpm.colorTable[i].c_color,"None",4)==0) {
color_table[0][i]=0;
color_table[1][i]=0;
color_table[2][i]=0;
transp = i;
continue;
}
if (XParseColor(dpy, cmap, xpm.colorTable[i].c_color, &xcolor)) {
color_table[0][i] = xcolor.red>>8;
color_table[1][i] = xcolor.green>>8;
color_table[2][i] = xcolor.blue>>8;
} else {
color_table[0][i]=0xbe;
color_table[1][i]=0xbe;
color_table[2][i]=0xbe;
}
}
memset(image->data[3], 255, xpm.width*xpm.height);
/* convert pixmap to RImage */
p = (int*)xpm.data;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
for (i=0; i<xpm.width*xpm.height; i++) {
if (*p==transp)
*a=0;
a++;
*(r++)=color_table[0][*p];
*(g++)=color_table[1][*p];
*(b++)=color_table[2][*p];
p++;
}
for(i=0; i<3; i++) {
free(color_table[i]);
}
XpmFreeXpmImage(&xpm);
return image;
}
#endif /* USE_XPM */

199
wrlib/xutil.c Normal file
View File

@@ -0,0 +1,199 @@
/* xutil.c - utility functions for X
*
* Raster graphics library
*
* Copyright (c) 1997 Alfredo K. Kojima
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#ifdef XSHM
#include <sys/ipc.h>
#include <sys/shm.h>
#endif /* XSHM */
#include "wraster.h"
#ifdef XSHM
static int shmError;
static int (*oldErrorHandler)();
static int
errorHandler(Display *dpy, XErrorEvent *err)
{
shmError=1;
if(err->error_code!=BadAccess)
(*oldErrorHandler)(dpy, err);
return 0;
}
#endif
RXImage*
RCreateXImage(RContext *context, int depth, unsigned width, unsigned height)
{
RXImage *rximg;
rximg = malloc(sizeof(RXImage));
if (!rximg) {
sprintf(RErrorString, "out of memory trying to create XImage");
return NULL;
}
#ifndef XSHM
rximg->image = XCreateImage(context->dpy, context->visual, depth,
ZPixmap, 0, NULL, width, height, 8, 0);
if (!rximg->image) {
free(rximg);
sprintf(RErrorString, "error creating XImage");
return NULL;
}
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
if (!rximg->image->data) {
XDestroyImage(rximg->image);
free(rximg);
sprintf(RErrorString, "out of memory trying to create XImage");
return NULL;
}
#else /* XSHM */
if (!context->attribs->use_shared_memory) {
retry_without_shm:
rximg->is_shared = 0;
rximg->image = XCreateImage(context->dpy, context->visual, depth,
ZPixmap, 0, NULL, width, height, 8, 0);
if (!rximg->image) {
free(rximg);
sprintf(RErrorString, "error creating XImage");
return NULL;
}
rximg->image->data = malloc(rximg->image->bytes_per_line*height);
if (!rximg->image->data) {
XDestroyImage(rximg->image);
free(rximg);
sprintf(RErrorString, "out of memory trying to create XImage");
return NULL;
}
} else {
rximg->is_shared = 1;
rximg->image = XShmCreateImage(context->dpy, context->visual, depth,
ZPixmap, NULL, &rximg->info, width,
height);
rximg->info.shmid = shmget(IPC_PRIVATE,
rximg->image->bytes_per_line*height,
IPC_CREAT|0770);
if (rximg->info.shmid < 0) {
context->attribs->use_shared_memory = 0;
perror("wrlib:could not allocate shared memory segment:");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
rximg->info.shmaddr = shmat(rximg->info.shmid, 0, 0);
if (rximg->info.shmaddr == (void*)-1) {
context->attribs->use_shared_memory = 0;
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib:shmctl:");
perror("wrlib:could not allocate shared memory");
XDestroyImage(rximg->image);
goto retry_without_shm;
}
shmError = 0;
XSync(context->dpy, False);
oldErrorHandler = XSetErrorHandler(errorHandler);
XShmAttach(context->dpy, &rximg->info);
XSync(context->dpy, False);
XSetErrorHandler(oldErrorHandler);
rximg->image->data = rximg->info.shmaddr;
/* rximg->image->obdata = &(rximg->info);*/
if (shmError) {
context->attribs->use_shared_memory = 0;
XDestroyImage(rximg->image);
if (shmdt(rximg->info.shmaddr) < 0)
perror("wrlib:shmdt:");
if (shmctl(rximg->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib:shmctl:");
printf("wrlib:error attaching shared memory segment to XImage\n");
goto retry_without_shm;
}
}
#endif /* XSHM */
return rximg;
}
void
RDestroyXImage(RContext *context, RXImage *rximage)
{
#ifndef XSHM
XDestroyImage(rximage->image);
#else /* XSHM */
if (rximage->is_shared) {
XSync(context->dpy, False);
XShmDetach(context->dpy, &rximage->info);
XDestroyImage(rximage->image);
if (shmdt(rximage->info.shmaddr) < 0)
perror("wrlib:shmdt:");
if (shmctl(rximage->info.shmid, IPC_RMID, 0) < 0)
perror("wrlib:shmctl:");
} else {
XDestroyImage(rximage->image);
}
#endif
free(rximage);
}
void
RPutXImage(RContext *context, Drawable d, GC gc, RXImage *ximage, int src_x,
int src_y, int dest_x, int dest_y,
unsigned int width, unsigned int height)
{
#ifndef XSHM
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
dest_y, width, height);
#else
if (ximage->is_shared) {
XShmPutImage(context->dpy, d, gc, ximage->image, src_x, src_y,
dest_x, dest_y, width, height, False);
} else {
XPutImage(context->dpy, d, gc, ximage->image, src_x, src_y, dest_x,
dest_y, width, height);
}
XFlush(context->dpy);
#endif /* XSHM */
}