Initial revision
authorKoichi KAMICHI <kamichi@fonts.jp>
Tue, 3 Feb 2004 16:11:30 +0000 (16:11 +0000)
committerKoichi KAMICHI <kamichi@fonts.jp>
Tue, 3 Feb 2004 16:11:30 +0000 (16:11 +0000)
17 files changed:
kagecgi/.DS_Store [new file with mode: 0644]
kagecgi/COPYING [new file with mode: 0644]
kagecgi/Makefile [new file with mode: 0755]
kagecgi/error.png [new file with mode: 0755]
kagecgi/kage.h [new file with mode: 0755]
kagecgi/kagecd.c [new file with mode: 0755]
kagecgi/kagecgi.c [new file with mode: 0755]
kagecgi/kagecgi.h [new file with mode: 0755]
kagecgi/kagechar.c [new file with mode: 0755]
kagecgi/kagecomb.c [new file with mode: 0755]
kagecgi/kagedb.c [new file with mode: 0755]
kagecgi/kagedf.c [new file with mode: 0755]
kagecgi/kageeg.c [new file with mode: 0755]
kagecgi/kageic.c [new file with mode: 0755]
kagecgi/kagepng.c [new file with mode: 0755]
kagecgi/kagepoly.c [new file with mode: 0755]
kagecgi/kagetool.c [new file with mode: 0755]

diff --git a/kagecgi/.DS_Store b/kagecgi/.DS_Store
new file mode 100644 (file)
index 0000000..1a57a1e
Binary files /dev/null and b/kagecgi/.DS_Store differ
diff --git a/kagecgi/COPYING b/kagecgi/COPYING
new file mode 100644 (file)
index 0000000..a52b16e
--- /dev/null
@@ -0,0 +1,341 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, 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 software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, 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 redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+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 give any other recipients of the Program a copy of this License
+along with the Program.
+
+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 Program or any portion
+of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+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 Program, 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 Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) 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; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, 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 executable.  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.
+
+If distribution of executable or 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 counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program 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.
+
+  5. 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 Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program 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.
+
+  7. 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 Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program 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 Program.
+
+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.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program 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.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+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 Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, 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
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  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 program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kagecgi/Makefile b/kagecgi/Makefile
new file mode 100755 (executable)
index 0000000..1e88ed3
--- /dev/null
@@ -0,0 +1,37 @@
+#\r
+#\r
+# CC=gcc -g\r
+CC= gcc -Wall\r
+\r
+VERSION=0.0.1\r
+\r
+#for cygwin with glib gdk gtk\r
+#CFLAGS= -I/usr/local/include -I/usr/local/include/glib-2.0 -I/usr/local/include/glib-2.0/glib -I/usr/local/include/glib-2.0/gobject -I/usr/local/include/gtk-2.0 -I/usr/local/include/gtk-2.0/gtk -I/usr/local/include/gtk-2.0/gdk -I/usr/local/include/gtk-2.0/gdk-pixbuf -I/usr/local/lib/glib-2.0/include -I/usr/local/lib/gtk-2.0/include -I/usr/local/include/pango-1.0 -I/usr/local/include/atk-1.0\r
+#LIBS= -lpng -ldb -L/usr/local/lib -lglib-2.0 -lgtk-win32-2.0 -lgdk-win32-2.0 -lgthread-2.0 -lpangowin32-1.0 -lgobject-2.0 -lgmodule-2.0 -lpangoft2-1.0 -lpango-1.0 -latk-1.0 -lgdk_pixbuf-2.0\r
+\r
+#for cygwin with glib\r
+#CFLAGS= -I/usr/local/include -I/usr/local/include/glib-2.0 -I/usr/local/include/glib-2.0/glib -I/usr/local/lib/glib-2.0/include\r
+#LIBS= -L/usr/local/lib -lpng -ldb -lglib-2.0\r
+\r
+#for linux\r
+CFLAGS= -I/usr/local/include -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/X11R6/include\r
+LIBS= -L/usr/local/lib -lpng -ldb -lglib-2.0 -L/usr/X11R6/lib -lX11\r
+\r
+kage.cgi: kagecgi.o kagepng.o kagedf.o kagecd.o kageic.o kagepoly.o kagedb.o kageeg.o kagecomb.o kagechar.o kagetool.o\r
+       $(CC) $(CFLAGS) -o kage.cgi kagecgi.o kagepng.o kagedf.o kagecd.o kageic.o kagepoly.o kagedb.o kageeg.o kagecomb.o kagechar.o kagetool.o $(LIBS)\r
+\r
+kagecgi.o: kagecgi.c\r
+kagedf.o: kagedf.c\r
+kagecd.o: kagecd.c\r
+kageic.o: kageic.c\r
+kagepoly.o: kagepoly.c\r
+kagedb.o: kagedb.c\r
+kageeg.o: kageeg.c\r
+kagechar.o: kagechar.c\r
+kagecomb.o: kagecomb.c\r
+kagetool.o: kagetool.c\r
+kagepng.o: kagepng.c\r
+\r
+clean:\r
+       \rm -r -f *.o *~ *.exe *.cgi *.stackdump\r
+\r
diff --git a/kagecgi/error.png b/kagecgi/error.png
new file mode 100755 (executable)
index 0000000..4c3a4d2
Binary files /dev/null and b/kagecgi/error.png differ
diff --git a/kagecgi/kage.h b/kagecgi/kage.h
new file mode 100755 (executable)
index 0000000..b11c5c6
--- /dev/null
@@ -0,0 +1,57 @@
+//kage.h\r
+//\r
+#include <X11/Xlib.h>\r
+#include <X11/Xutil.h>\r
+#include <math.h>\r
+\r
+#ifndef _KAGE_H_\r
+#define _KAGE_H_\r
+\r
+int kShotai;\r
+#define kMincho 0\r
+#define kGothic 1\r
+\r
+#define kMage 10\r
+#define kRate 20\r
+#define kResolution (1000 / kRate + 1) * 2\r
+#define kMinWidthY 2\r
+#define kMinWidthT 6\r
+#define kWidth 5\r
+#define kKakato 3 //has KAKATO = 2, no KAKATO = 1\r
+#define kKasane 3\r
+#define kMixdot (kWidth * 2) * (kWidth * 2 - 1)\r
+\r
+#define kMaxIDSSequenceLength 16\r
+#define kMaxIDCLength 16\r
+#define kMaxStrokeDataLength 256 // over 12(digits per integer with +/- flag) * 11(columns) + 1(line end)\r
+\r
+struct kPoint{\r
+       int X;\r
+       int Y;\r
+};\r
+\r
+XPoint xpoly[kResolution];\r
+\r
+struct kPoint poly[kResolution];\r
+struct kPoint poly2[3];\r
+struct kPoint poly3[5];\r
+struct kPoint poly4[4];\r
+\r
+struct EDGE {\r
+    struct EDGE *next;\r
+    long yTop, yBot;\r
+    long xNowWhole, xNowNum, xNowDen, xNowDir;\r
+    long xNowNumStep;\r
+};\r
+\r
+#define SGN(a) ( (a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ) )\r
+\r
+//kagedf.c\r
+void dfDrawFont(int, int, int, int, int, int, int, int, int, int, int);\r
+//kagecd.c\r
+void cdDrawCurve(int, int, int, int, int, int, int, int);\r
+void cdDrawLine(int, int, int, int, int, int);\r
+//kageic.c\r
+void icPolygon(struct kPoint *, int);\r
+\r
+#endif\r
diff --git a/kagecgi/kagecd.c b/kagecgi/kagecd.c
new file mode 100755 (executable)
index 0000000..93fc8e2
--- /dev/null
@@ -0,0 +1,1087 @@
+//kagecd.c\r
+//\r
+#include "kage.h"\r
+\r
+void cdDrawCurve(int x1, int y1,\r
+       int x2, int y2,\r
+       int x3, int y3,\r
+       int a1, int a2){\r
+\r
+       double rad, t;\r
+       double x, y, v;\r
+       double ix, iy, ia, ib, ir;\r
+       int ox1, oy1, ox2, oy2;\r
+       int count, tt;\r
+       int delta;\r
+       double deltad;\r
+       double XX, XY, YX, YY;\r
+       \r
+       if(kShotai == kMincho){ // mincho\r
+       switch(a1){\r
+       case 0:\r
+       case 7:\r
+               delta = -1 * kMinWidthY * 0.5;\r
+               break;\r
+       case 1:\r
+       case 2:\r
+       case 6:\r
+       case 22:\r
+               delta = 0;\r
+               break;\r
+       case 12:\r
+       case 32:\r
+               delta = kMinWidthY;\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+       \r
+       if(x1 == x2){\r
+               if(y1 < y2){ y1 = y1 - delta; }\r
+               else{ y1 = y1 + delta; }\r
+       }\r
+       else if(y1 == y2){\r
+               if(x1 < x2){ x1 = x1 - delta; }\r
+               else{ x1 = x1 + delta; }\r
+       }\r
+       else{\r
+               rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+               if(x1 < x2){ v = 1; } else{ v = -1; }\r
+               x1 = x1 - delta * cos(rad) * v;\r
+               y1 = y1 - delta * sin(rad) * v;\r
+       }\r
+       \r
+       switch(a2){\r
+       case 0:\r
+       case 1:\r
+       case 8:\r
+       case 7:\r
+       case 9:\r
+       case 15:\r
+       case 14:\r
+       case 17:\r
+       case 5:\r
+               delta = 0;\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+       \r
+       if(x2 == x3){\r
+               if(y2 < y3){ y3 = y3 + delta; }\r
+               else{ y3 = y3 - delta; }\r
+       }\r
+       else if(y2 == y3){\r
+               if(x2 < x3){ x3 = x3 + delta; }\r
+               else{ x3 = x3 - delta; }\r
+       }\r
+       else{\r
+               rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+               if(x2 < x3){ v = 1; } else{ v = -1; }\r
+               x3 = x3 + delta * cos(rad) * v;\r
+               y3 = y3 + delta * sin(rad) * v;\r
+       }\r
+       \r
+       count = 0;\r
+       \r
+       for(tt = 0; tt <= 1000; tt = tt + kRate){\r
+               t = (double)(tt) / 1000;\r
+               \r
+               //calculate a dot\r
+               x = ((1.0 - t) * (1.0 - t) * x1 + 2.0 * t * (1.0 - t) * x2 + t * t * x3);\r
+               y = ((1.0 - t) * (1.0 - t) * y1 + 2.0 * t * (1.0 - t) * y2 + t * t * y3);\r
+               \r
+               //KATAMUKI of vector by BIBUN\r
+               ix = (x1 - 2.0 * x2 + x3) * 2.0 * t + (-2.0 * x1 + 2.0 * x2);\r
+               iy = (y1 - 2.0 * y2 + y3) * 2.0 * t + (-2.0 * y1 + 2.0 * y2);\r
+               \r
+               //line SUICHOKU by vector\r
+               if(ix != 0 && iy != 0){\r
+                       ir = atan(iy / ix * -1.0);\r
+                       ia = sin(ir) * (double)(kMinWidthT);\r
+                       ib = cos(ir) * (double)(kMinWidthT);\r
+               }\r
+               else if(ix == 0){\r
+                       ia = kMinWidthT;\r
+                       ib = 0;\r
+               }\r
+               else{\r
+                       ia = 0;\r
+                       ib = kMinWidthT;\r
+               }\r
+               \r
+               if(a1 == 7 && a2 != 17){ deltad = sqrt(t); }\r
+               else if(a2 == 7 && a1 != 17){ deltad = sqrt(1.0 - t); }\r
+               else if(a1 == 7 && a2 == 17){ deltad = sqrt(t / 2); }\r
+               else if(a1 == 17 && a2 != 7){ deltad = sqrt(t / 2 + 0.5); }\r
+               else if(a1 != 7 && a2 == 17){ deltad = sqrt(1.0 - t / 2); }\r
+               else if(a1 == 17 && a2 == 7){ deltad = sqrt(0.5 - t / 2); }\r
+               else{ deltad = 1; }\r
+               ia = ia * deltad;\r
+               ib = ib * deltad;\r
+               \r
+               //swap if two lines are crossing\r
+               if(((x + ia) - ox1) * ((x + ia) - ox1) +\r
+                       ((y + ib) - oy1) * ((y + ib) - oy1) >\r
+                       ((x - ia) - ox1) * ((x - ia) - ox1) +\r
+                       ((y - ib) - oy1) * ((y - ib) - oy1) && count != 0){\r
+                       ia = ia * -1;\r
+                       ib = ib * -1;\r
+               }\r
+               \r
+               //copy as an old point\r
+               ox1 = x + ia;\r
+               oy1 = y + ib;\r
+               ox2 = x - ia;\r
+               oy2 = y - ib;\r
+               \r
+               //copy to polygon structuer\r
+               poly[count].X = x + ia;\r
+               poly[count].Y = y + ib;\r
+               poly[(1000 / kRate + 1) * 2 - 1 - count].X = x - ia;\r
+               poly[(1000 / kRate + 1) * 2 - 1 - count].Y = y - ib;\r
+               count += 1;\r
+       }\r
+       \r
+       icPolygon(poly, (1000 / kRate + 1) * 2);\r
+       \r
+       //process for head of stroke\r
+       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+       XX = sin(rad) * v;\r
+       XY = cos(rad) * v * -1;\r
+       YX = cos(rad) * v;\r
+       YY = sin(rad) * v;\r
+       \r
+       if(a1 == 12){\r
+               if(x1 == x2){\r
+                       poly2[0].X = x1 - kMinWidthT;\r
+                       poly2[0].Y = y1;\r
+                       poly2[1].X = x1 + kMinWidthT;\r
+                       poly2[1].Y = y1;\r
+                       poly2[2].X = x1 - kMinWidthT;\r
+                       poly2[2].Y = y1 - kMinWidthT;\r
+                       icPolygon(poly2, 3);\r
+               }\r
+               else{\r
+                       poly2[0].X = x1 - kMinWidthT * XX;\r
+                       poly2[0].Y = y1 - kMinWidthT * XY;\r
+                       poly2[1].X = x1 + kMinWidthT * XX;\r
+                       poly2[1].Y = y1 + kMinWidthT * XY;\r
+                       poly2[2].X = x1 - kMinWidthT * XX - kMinWidthT * YX;\r
+                       poly2[2].Y = y1 - kMinWidthT * XY - kMinWidthT * YY;\r
+                       icPolygon(poly2, 3);\r
+               }\r
+       }\r
+       \r
+       if(a1 == 0){\r
+               if(y1 <= y3){ //from up to bottom\r
+                       if(x1 == x2){\r
+                               poly2[0].X = x1 - kMinWidthT;\r
+                               poly2[0].Y = y1;\r
+                               poly2[1].X = x1 + kMinWidthT;\r
+                               poly2[1].Y = y1;\r
+                               poly2[2].X = x1 - kMinWidthT;\r
+                               poly2[2].Y = y1 - kMinWidthY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       else{\r
+                               poly2[0].X = x1 - kMinWidthT * XX;\r
+                               poly2[0].Y = y1 - kMinWidthT * XY;\r
+                               poly2[1].X = x1 + kMinWidthT * XX;\r
+                               poly2[1].Y = y1 + kMinWidthT * XY;\r
+                               poly2[2].X = x1 - kMinWidthT * XX - kMinWidthY * YX;\r
+                               poly2[2].Y = y1 - kMinWidthT * XY - kMinWidthY * YY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+               }\r
+               else{ //bottom to up\r
+                       if(x1 == x2){ //is it right?\r
+                               poly2[0].X = x1 - kMinWidthT;\r
+                               poly2[0].Y = y1;\r
+                               poly2[1].X = x1 + kMinWidthT;\r
+                               poly2[1].Y = y1;\r
+                               poly2[2].X = x1 - kMinWidthT;\r
+                               poly2[2].Y = y1 + kMinWidthY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       else{\r
+                               poly2[0].X = x1 - kMinWidthT * XX;\r
+                               poly2[0].Y = y1 - kMinWidthT * XY;\r
+                               poly2[1].X = x1 + kMinWidthT * XX;\r
+                               poly2[1].Y = y1 + kMinWidthT * XY;\r
+                               poly2[2].X = x1 + kMinWidthT * XX - kMinWidthY * YX;\r
+                               poly2[2].Y = y1 + kMinWidthT * XY - kMinWidthY * YY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+               }\r
+       }\r
+       \r
+       if(a1 == 22){ //box's up-right corner, any time same degree\r
+               poly3[0].X = x1 - kMinWidthT;\r
+               poly3[0].Y = y1 - kMinWidthY;\r
+               poly3[1].X = x1;\r
+               poly3[1].Y = y1 - kMinWidthY - kWidth;\r
+               poly3[2].X = x1 + kMinWidthT + kWidth;\r
+               poly3[2].Y = y1 + kMinWidthY;\r
+               poly3[3].X = x1 + kMinWidthT;\r
+               poly3[3].Y = y1 + kMinWidthT;\r
+               poly3[4].X = x1 - kMinWidthT;\r
+               poly3[4].Y = y1;\r
+               icPolygon(poly3, 5);\r
+       }\r
+       \r
+       if(a1 == 0){ //beginning of the stroke\r
+               if(y1 <= y3){ //from up to bottom\r
+                       if(x1 == x2){\r
+                               poly2[0].X = x1 + kMinWidthT;\r
+                               poly2[0].Y = y1 + kMinWidthY * 0.5;\r
+                               poly2[1].X = x1 + kMinWidthT + kMinWidthT * 0.5;\r
+                               poly2[1].Y = y1 + kMinWidthY * 0.5 + kMinWidthY;\r
+                               poly2[2].X = x1 + kMinWidthT;\r
+                               poly2[2].Y = y1 + kMinWidthY * 0.5 + kMinWidthY * 2;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       else{\r
+                               poly2[0].X = x1 + kMinWidthT * XX + (kMinWidthY * 0.5) * YX;\r
+                               poly2[0].Y = y1 + kMinWidthT * XY + (kMinWidthY * 0.5) * YY;\r
+                               poly2[1].X = x1 + (kMinWidthT + kMinWidthT * 0.5) * XX + (kMinWidthY * 0.5 + kMinWidthY) * YX;\r
+                               poly2[1].Y = y1 + (kMinWidthT + kMinWidthT * 0.5) * XY + (kMinWidthY * 0.5 + kMinWidthY) * YY;\r
+                               poly2[2].X = x1 + kMinWidthT * XX + (kMinWidthY * 0.5 + kMinWidthY * 2) * YX;\r
+                               poly2[2].Y = y1 + kMinWidthT * XY + (kMinWidthY * 0.5 + kMinWidthY * 2) * YY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+               }\r
+               else{ //from bottom to up\r
+                       if(x1 == x2){ //is it right?\r
+                               poly2[0].X = x1 + kMinWidthT;\r
+                               poly2[0].Y = y1 - kMinWidthY * 0.5;\r
+                               poly2[1].X = x1 + kMinWidthT + kMinWidthT * 0.5;\r
+                               poly2[1].Y = y1 - kMinWidthY * 0.5 - kMinWidthY;\r
+                               poly2[2].X = x1 + kMinWidthT;\r
+                               poly2[2].Y = y1 - kMinWidthY * 0.5 - kMinWidthY * 2;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       else //SETSUGOUMEN GA KAKERUNODE HOKYOU\r
+                               poly3[0].X = x1 - (kMinWidthT - 1) * XX + (kMinWidthY * 0.5) * YX;\r
+                               poly3[0].Y = y1 - (kMinWidthT - 1) * XY + (kMinWidthY * 0.5) * YY;\r
+                               poly3[1].X = x1 - (kMinWidthT - 0) * XX + (kMinWidthY * 0.5) * YX;\r
+                               poly3[1].Y = y1 - (kMinWidthT - 0) * XY + (kMinWidthY * 0.5) * YY;\r
+                               poly3[2].X = x1 - (kMinWidthT + kMinWidthT * 0.5) * XX + (kMinWidthY * 0.5 + kMinWidthY) * YX;\r
+                               poly3[2].Y = y1 - (kMinWidthT + kMinWidthT * 0.5) * XY + (kMinWidthY * 0.5 + kMinWidthY) * YY;\r
+                               poly3[3].X = x1 - (kMinWidthT - 0) * XX + (kMinWidthY * 0.5 + kMinWidthY * 2) * YX;\r
+                               poly3[3].Y = y1 - (kMinWidthT - 0) * XY + (kMinWidthY * 0.5 + kMinWidthY * 2) * YY;\r
+                               poly3[4].X = x1 - (kMinWidthT - 1) * XX + (kMinWidthY * 0.5 + kMinWidthY * 2) * YX;\r
+                               poly3[4].Y = y1 - (kMinWidthT - 1) * XY + (kMinWidthY * 0.5 + kMinWidthY * 2) * YY;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+               }\r
+               \r
+               //process for tail\r
+               rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+               if(x2 < x3){ v = 1; } else{ v = -1; }\r
+               YX = sin(rad) * v * -1;\r
+               YY = cos(rad) * v;\r
+               XX = cos(rad) * v;\r
+               XY = sin(rad) * v;\r
+               \r
+               if(a2 == 1 || a2 == 8 || a2 == 15){ //the last filled circle\r
+                       if(x2 == x3){\r
+                               poly3[0].X = x3 - kMinWidthT;\r
+                               poly3[0].Y = y3;\r
+                               poly3[1].X = x3 - kMinWidthT * 0.6;\r
+                               poly3[1].Y = y3 + kMinWidthT * 0.6;\r
+                               poly3[2].X = x3;\r
+                               poly3[2].Y = y3 + kMinWidthT;\r
+                               poly3[3].X = x3 + kMinWidthT * 0.6;\r
+                               poly3[3].Y = y3 + kMinWidthT * 0.6;\r
+                               poly3[4].X = x3 + kMinWidthT;\r
+                               poly3[4].Y = y3;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+                       else if(y2 == y3){\r
+                               poly3[0].X = x3;\r
+                               poly3[0].Y = y3 - kMinWidthT;\r
+                               poly3[1].X = x3 + kMinWidthT * 0.6;\r
+                               poly3[1].Y = y3 - kMinWidthT * 0.6;\r
+                               poly3[2].X = x3 + kMinWidthT;\r
+                               poly3[2].Y = y3;\r
+                               poly3[3].X = x3 + kMinWidthT * 0.6;\r
+                               poly3[3].Y = y3 + kMinWidthT * 0.6;\r
+                               poly3[4].X = x3;\r
+                               poly3[4].Y = y3 + kMinWidthT;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+                       else{\r
+                               poly3[0].X = x3 + sin(rad) * kMinWidthT * v;\r
+                               poly3[0].Y = y3 - cos(rad) * kMinWidthT * v;\r
+                               poly3[1].X = x3 + cos(rad) * kMinWidthT * 0.8 * v + sin(rad) * kMinWidthT * 0.6 * v;\r
+                               poly3[1].Y = y3 + sin(rad) * kMinWidthT * 0.8 * v - cos(rad) * kMinWidthT * 0.6 * v;\r
+                               poly3[2].X = x3 + cos(rad) * kMinWidthT * v;\r
+                               poly3[2].Y = y3 + sin(rad) * kMinWidthT * v;\r
+                               poly3[3].X = x3 + cos(rad) * kMinWidthT * 0.8 * v - sin(rad) * kMinWidthT * 0.6 * v;\r
+                               poly3[3].Y = y3 + sin(rad) * kMinWidthT * 0.8 * v + cos(rad) * kMinWidthT * 0.6 * v;\r
+                               poly3[4].X = x3 - sin(rad) * kMinWidthT * v;\r
+                               poly3[4].Y = y3 + cos(rad) * kMinWidthT * v;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+               }\r
+               \r
+               if(a2 == 17){ //the last filled half circle\r
+                       if(x2 == x3){\r
+                               poly3[0].X = x3 - kMinWidthT * 0.5;\r
+                               poly3[0].Y = y3;\r
+                               poly3[1].X = x3 - kMinWidthT * 0.6 * 0.5;\r
+                               poly3[1].Y = y3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[2].X = x3;\r
+                               poly3[2].Y = y3 + kMinWidthT * 0.5;\r
+                               poly3[3].X = x3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[3].Y = y3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[4].X = x3 + kMinWidthT * 0.5;\r
+                               poly3[4].Y = y3;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+                       else if(y2 == y3){\r
+                               poly3[0].X = x3;\r
+                               poly3[0].Y = y3 - kMinWidthT * 0.5;\r
+                               poly3[1].X = x3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[1].Y = y3 - kMinWidthT * 0.6 * 0.5;\r
+                               poly3[2].X = x3 + kMinWidthT * 0.5;\r
+                               poly3[2].Y = y3;\r
+                               poly3[3].X = x3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[3].Y = y3 + kMinWidthT * 0.6 * 0.5;\r
+                               poly3[4].X = x3;\r
+                               poly3[4].Y = y3 + kMinWidthT * 0.5;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+                       else{\r
+                               poly3[0].X = x3 + sin(rad) * kMinWidthT * 0.5 * v;\r
+                               poly3[0].Y = y3 - cos(rad) * kMinWidthT * 0.5 * v;\r
+                               poly3[1].X = x3 + cos(rad) * kMinWidthT * 0.8 * 0.5 * v + sin(rad) * kMinWidthT * 0.6 * 0.5 * v;\r
+                               poly3[1].Y = y3 + sin(rad) * kMinWidthT * 0.8 * 0.5 * v - cos(rad) * kMinWidthT * 0.6 * 0.5 * v;\r
+                               poly3[2].X = x3 + cos(rad) * kMinWidthT * 0.5 * v;\r
+                               poly3[2].Y = y3 + sin(rad) * kMinWidthT * 0.5 * v;\r
+                               poly3[3].X = x3 + cos(rad) * kMinWidthT * 0.5 * 0.8 * v - sin(rad) * kMinWidthT * 0.6 * 0.5 * v;\r
+                               poly3[3].Y = y3 + sin(rad) * kMinWidthT * 0.5 * 0.8 * v + cos(rad) * kMinWidthT * 0.6 * 0.5 * v;\r
+                               poly3[4].X = x3 - sin(rad) * kMinWidthT * 0.5 * v;\r
+                               poly3[4].Y = y3 + cos(rad) * kMinWidthT * 0.5 * v;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+               }\r
+               \r
+               if(a2 == 9){\r
+                       if(y2 == y3){\r
+                               poly2[0].X = x3;\r
+                               poly2[0].Y = y3 + kMinWidthT;\r
+                               poly2[1].X = x3;\r
+                               poly2[1].Y = y3 - kMinWidthT;\r
+                               poly2[2].X = x3 + kMinWidthT;\r
+                               poly2[2].Y = y3 - kMinWidthT;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       else{\r
+                               poly2[0].X = x3 + kMinWidthT * YX;\r
+                               poly2[0].Y = y3 + kMinWidthT * YY;\r
+                               poly2[1].X = x3 - kMinWidthT * YX;\r
+                               poly2[1].Y = y3 - kMinWidthT * YY;\r
+                               poly2[2].X = x3 + kMinWidthT * XX - kMinWidthT * YX;\r
+                               poly2[2].Y = y3 + kMinWidthT * XY - kMinWidthT * YY;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+               }\r
+               \r
+               if(a2 == 15){ //jump up\r
+                       if(y2 == y3){\r
+                               poly4[0].X = x3;\r
+                               poly4[0].Y = y3 - kMinWidthT + 1;\r
+                               poly4[1].X = x3 + 2;\r
+                               poly4[1].Y = y3 - kMinWidthT - kWidth * 5;\r
+                               poly4[2].X = x3;\r
+                               poly4[2].Y = y3 - kMinWidthT - kWidth * 5;\r
+                               poly4[3].X = x3 - kMinWidthT;\r
+                               poly4[3].Y = y3 - kMinWidthT + 1;\r
+                               icPolygon(poly4, 4);\r
+                       }\r
+                       else{\r
+                               poly4[0].X = x3 + (kMinWidthT - 1) * sin(rad) * v;\r
+                               poly4[0].Y = y3 - (kMinWidthT - 1) * cos(rad) * v;\r
+                               poly4[1].X = x3 + 2 * cos(rad) * v + (kMinWidthT + kWidth * 5) * sin(rad) * v;\r
+                               poly4[1].Y = y3 + 2 * sin(rad) * v - (kMinWidthT + kWidth * 5) * cos(rad) * v;\r
+                               poly4[2].X = x3 + (kMinWidthT + kWidth * 5) * sin(rad) * v;\r
+                               poly4[2].Y = y3 - (kMinWidthT + kWidth * 5) * cos(rad) * v;\r
+                               poly4[3].X = x3 + (kMinWidthT - 1) * sin(rad) * v - kMinWidthT * cos(rad) * v;\r
+                               poly4[3].Y = y3 - (kMinWidthT - 1) * cos(rad) * v - kMinWidthT * sin(rad) * v;\r
+                               icPolygon(poly4, 4);\r
+                       }\r
+               }\r
+               \r
+               if(a2 == 14){ //jump to left, allways go left\r
+                       poly4[0].X = x3;\r
+                       poly4[0].Y = y3;\r
+                       poly4[1].X = x3;\r
+                       poly4[1].Y = y3 - kMinWidthT;\r
+                       poly4[2].X = x3 - kWidth * 4;\r
+                       poly4[2].Y = y3 - kMinWidthT;\r
+                       poly4[3].X = x3 - kWidth * 4;\r
+                       poly4[3].Y = y3 - kMinWidthT * 0.5;\r
+                       icPolygon(poly4, 4);\r
+               }\r
+       }\r
+       else{ //gothic\r
+               if(a1 % 10 == 2){\r
+                       if(x1 == x2){\r
+                               if(y1 < y2){ y1 = y1 - kWidth; } else{ y1 = y1 + kWidth; }\r
+                       }\r
+                       else if(y1 == y2){\r
+                               if(x1 < x2){ x1 = x1 - kWidth; } else{ x1 = x1 + kWidth; }\r
+                       }\r
+                       else{\r
+                               rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                               if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                               x1 = x1 - kWidth * cos(rad) * v;\r
+                               y1 = y1 - kWidth * sin(rad) * v;\r
+                       }\r
+               }\r
+               \r
+               if(a1 % 10 == 3){\r
+                       if(x1 == x2){\r
+                               if(y1 < y2){\r
+                                        y1 = y1 - kWidth * kKakato;\r
+                               }\r
+                       else{\r
+                                y1 = y1 + kWidth * kKakato;\r
+                       }\r
+               }\r
+               else if(y1 == y2){\r
+                       if(x1 < x2){\r
+                               x1 = x1 - kWidth * kKakato;\r
+                       }\r
+                       else{\r
+                               x1 = x1 + kWidth * kKakato;\r
+                       }\r
+               }\r
+               else{\r
+                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                       x1 = x1 - kWidth * cos(rad) * v * kKakato;\r
+                       y1 = y1 - kWidth * sin(rad) * v * kKakato;\r
+                       }\r
+               }\r
+               if(a2 % 10 == 2){\r
+                       if(x2 == x3){\r
+                               if(y2 < y3){ y3 = y3 + kWidth; } else{ y3 = y3 - kWidth; }\r
+                       }\r
+                       else if(y2 == y3){\r
+                               if(x2 < x3){ x3 = x3 + kWidth; } else{ x3 = x3 - kWidth; }\r
+                       }\r
+                       else{\r
+                               rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                               if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                               x3 = x3 + kWidth * cos(rad) * v;\r
+                               y3 = y3 + kWidth * sin(rad) * v;\r
+                       }\r
+               }\r
+               \r
+               if(a2 % 10 == 3){\r
+                       if(x2 == x3){\r
+                               if(y2 < y3){\r
+                                       y3 = y3 + kWidth * kKakato;\r
+                               }\r
+                               else{\r
+                                       y3 = y3 - kWidth * kKakato;\r
+                               }\r
+                       }\r
+                       else if(y2 == y3){\r
+                               if(x2 < x3){\r
+                                       x3 = x3 + kWidth * kKakato;\r
+                               }\r
+                               else{\r
+                                       x3 = x3 - kWidth * kKakato;\r
+                               }\r
+                       }\r
+                       else{\r
+                               rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                               if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                               x3 = x3 + kWidth * cos(rad) * v * kKakato;\r
+                               y3 = y3 + kWidth * sin(rad) * v * kKakato;\r
+                       }\r
+               }\r
+               \r
+               count = 0;\r
+               \r
+               for(tt = 0; tt <= 1000; tt = tt + kRate){\r
+                       t = (double)tt / 1000;\r
+                       \r
+                       //calculating each point\r
+                       x = ((1.0 - t) * (1.0 - t) * x1 + 2.0 * t * (1.0 - t) * x2 + t * t * x3);\r
+                       y = ((1.0 - t) * (1.0 - t) * y1 + 2.0 * t * (1.0 - t) * y2 + t * t * y3);\r
+                       \r
+                       //SESSEN NO KATAMUKI NO KEISAN(BIBUN)\r
+                       ix = (x1 - 2.0 * x2 + x3) * 2.0 * t + (-2.0 * x1 + 2.0 * x2);\r
+                       iy = (y1 - 2.0 * y2 + y3) * 2.0 * t + (-2.0 * y1 + 2.0 * y2);\r
+                       \r
+                       //SESSEN NI SUICHOKU NA CHOKUSEN NO KEISAN\r
+                       if(kShotai == kMincho){ //always false ?\r
+                               if(ix != 0 && iy != 0){\r
+                                       ir = atan(iy / ix * -1.0);\r
+                                       ia = sin(ir) * (double)kMinWidthT;\r
+                                       ib = cos(ir) * (double)kMinWidthT;\r
+                               }\r
+                               else if(ix == 0){\r
+                                       ia = kMinWidthT;\r
+                                       ib = 0;\r
+                               }\r
+                               else{\r
+                                       ia = 0;\r
+                                       ib = kMinWidthT;\r
+                               }\r
+                               ia = ia * sqrt(1.0 - t);\r
+                               ib = ib * sqrt(1.0 - t);\r
+                       }\r
+                       else{\r
+                               if(ix != 0 && iy != 0){\r
+                                       ir = atan(iy / ix * -1.0);\r
+                                       ia = sin(ir) * (double)kWidth;\r
+                                       ib = cos(ir) * (double)kWidth;\r
+                               }\r
+                               else if(ix == 0){\r
+                                       ia = kWidth;\r
+                                       ib = 0;\r
+                               }\r
+                               else{\r
+                                       ia = 0;\r
+                                       ib = kWidth;\r
+                               }\r
+                       }\r
+                       \r
+                       //if it is crossing, swap each other\r
+                       if(((x + ia) - ox1) * ((x + ia) - ox1) +\r
+                               ((y + ib) - oy1) * ((y + ib) - oy1) >\r
+                               ((x - ia) - ox1) * ((x - ia) - ox1) +\r
+                               ((y - ib) - oy1) * ((y - ib) - oy1) && count != 0){\r
+                               ia = ia * -1;\r
+                               ib = ib * -1;\r
+                       }\r
+                       \r
+                       //save old points for calculate crossing\r
+                       ox1 = x + ia;\r
+                       oy1 = y + ib;\r
+                       ox2 = x - ia;\r
+                       oy2 = y - ib;\r
+                       \r
+                       //save to polygon\r
+                       poly[count].X = x + ia;\r
+                       poly[count].Y = y + ib;\r
+                       poly[(1000 / kRate + 1) * 2 - 1 - count].X = x - ia;\r
+                       poly[(1000 / kRate + 1) * 2 - 1 - count].Y = y - ib;\r
+                       count += 1;\r
+               }\r
+               \r
+               icPolygon(poly, (1000 / kRate + 1) * 2);\r
+       }\r
+}\r
+\r
+void cdDrawLine(int tx1, int ty1, int tx2, int ty2, int ta1, int ta2){\r
+       double rad;\r
+       int v, x1, y1, x2, y2, a1, a2;\r
+       double XX, XY, YX, YY;\r
+       \r
+       if(kShotai == kMincho){ //mincho\r
+               x1 = tx1;\r
+               y1 = ty1;\r
+               x2 = tx2;\r
+               y2 = ty2;\r
+               a1 = ta1;\r
+               a2 = ta2;\r
+               \r
+               if(x1 == x2){ //if TATE stroke, use y-axis\r
+                       switch(a1){\r
+                       case 0:\r
+                               poly[0].X = x1 - kMinWidthT;\r
+                               poly[0].Y = y1 - kMinWidthY / 2;\r
+                               poly[3].X = x1 + kMinWidthT;\r
+                               poly[3].Y = y1 + kMinWidthY / 2;\r
+                               break;\r
+                       case 1:\r
+                       case 6:\r
+                       case 22:\r
+                               poly[0].X = x1 - kMinWidthT;\r
+                               poly[0].Y = y1;\r
+                               poly[3].X = x1 + kMinWidthT;\r
+                               poly[3].Y = y1;\r
+                               break;\r
+                       case 12:\r
+                               poly[0].X = x1 - kMinWidthT;\r
+                               poly[0].Y = y1 - kMinWidthY - kMinWidthT;\r
+                               poly[3].X = x1 + kMinWidthT;\r
+                               poly[3].Y = y1 - kMinWidthY;\r
+                               break;\r
+                       case 32:\r
+                               poly[0].X = x1 - kMinWidthT;\r
+                               poly[0].Y = y1 - kMinWidthY;\r
+                               poly[3].X = x1 + kMinWidthT;\r
+                               poly[3].Y = y1 - kMinWidthY;\r
+                               break;\r
+                       }\r
+                       \r
+                       switch(a2){\r
+                       case 0:\r
+                               if(a1 == 6){ //KAGI's tail\r
+                                       poly[1].X = x2 - kMinWidthT;\r
+                                       poly[1].Y = y2;\r
+                                       poly[2].X = x2 + kMinWidthT;\r
+                                       poly[2].Y = y2;\r
+                               }\r
+                               else{\r
+                                       poly[1].X = x2 - kMinWidthT;\r
+                                       poly[1].Y = y2 + kMinWidthT / 2;\r
+                                       poly[2].X = x2 + kMinWidthT;\r
+                                       poly[2].Y = y2 - kMinWidthT / 2;\r
+                               }\r
+                               break;\r
+                       case 1:\r
+                               poly[1].X = x2 - kMinWidthT;\r
+                               poly[1].Y = y2;\r
+                               poly[2].X = x2 + kMinWidthT;\r
+                               poly[2].Y = y2;\r
+                               break;\r
+                       case 13:\r
+                               poly[1].X = x2 - kMinWidthT;\r
+                               poly[1].Y = y2 + kWidth * kKakato + kMinWidthT;\r
+                               poly[2].X = x2 + kMinWidthT;\r
+                               poly[2].Y = y2 + kWidth * kKakato;\r
+                               break;\r
+                       case 23:\r
+                               poly[1].X = x2 - kMinWidthT;\r
+                               poly[1].Y = y2 + kWidth * kKakato * 0.5 + kMinWidthT;\r
+                               poly[2].X = x2 + kMinWidthT;\r
+                               poly[2].Y = y2 + kWidth * kKakato * 0.5;\r
+                               break;\r
+                       case 32:\r
+                               poly[1].X = x2 - kMinWidthT;\r
+                               poly[1].Y = y2 + kMinWidthY;\r
+                               poly[2].X = x2 + kMinWidthT;\r
+                               poly[2].Y = y2 + kMinWidthY;\r
+                               break;\r
+                       }\r
+                       \r
+                       icPolygon(poly, 4);\r
+                       \r
+                       if(a1 == 22){ //box's right top corner\r
+                               poly3[0].X = x1 - kMinWidthT;\r
+                               poly3[0].Y = y1 - kMinWidthY;\r
+                               poly3[1].X = x1;\r
+                               poly3[1].Y = y1 - kMinWidthY - kWidth;\r
+                               poly3[2].X = x1 + kMinWidthT + kWidth;\r
+                               poly3[2].Y = y1 + kMinWidthY;\r
+                               poly3[3].X = x1 + kMinWidthT;\r
+                               poly3[3].Y = y1 + kMinWidthT;\r
+                               poly3[4].X = x1 - kMinWidthT;\r
+                               poly3[4].Y = y1;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+                       \r
+                       if(a1 == 0){ //beginning of the stroke\r
+                               poly2[0].X = x1 + kMinWidthT;\r
+                               poly2[0].Y = y1 + kMinWidthY * 0.5;\r
+                               poly2[1].X = x1 + kMinWidthT + kMinWidthT * 0.5;\r
+                               poly2[1].Y = y1 + kMinWidthY * 0.5 + kMinWidthY;\r
+                               poly2[2].X = x1 + kMinWidthT;\r
+                               poly2[2].Y = y1 + kMinWidthY * 0.5 + kMinWidthY * 2;\r
+                               icPolygon(poly2, 3);\r
+                       }\r
+                       \r
+                       if((a1 == 6 && a2 == 0) || a2 == 1){ //KAGI NO YOKO BOU NO SAIGO NO MARU\r
+                               poly3[0].X = x2 - kMinWidthT;\r
+                               poly3[0].Y = y2;\r
+                               poly3[1].X = x2 - kMinWidthT * 0.6;\r
+                               poly3[1].Y = y2 + kMinWidthT * 0.6;\r
+                               poly3[2].X = x2;\r
+                               poly3[2].Y = y2 + kMinWidthT;\r
+                               poly3[3].X = x2 + kMinWidthT * 0.6;\r
+                               poly3[3].Y = y2 + kMinWidthT * 0.6;\r
+                               poly3[4].X = x2 + kMinWidthT;\r
+                               poly3[4].Y = y2;\r
+                               icPolygon(poly3, 5);\r
+                       }\r
+               }\r
+               else if(y1 == y2){ //if it is YOKO stroke, use x-axis\r
+                       if(a1 == 6){ //if it is KAGI's YOKO stroke, get bold\r
+                               poly[0].X = x1;\r
+                               poly[0].Y = y1 - kMinWidthT;\r
+                               poly[1].X = x2;\r
+                               poly[1].Y = y2 - kMinWidthT;\r
+                               poly[2].X = x2;\r
+                               poly[2].Y = y2 + kMinWidthT;\r
+                               poly[3].X = x1;\r
+                               poly[3].Y = y1 + kMinWidthT;\r
+                               icPolygon(poly, 4);\r
+                               \r
+                               if(a2 == 1 || a2 == 0 || a2 == 5){\r
+                                       //KAGI NO YOKO BOU NO SAIGO NO MARU\r
+                                       poly3[0].X = x2;\r
+                                       poly3[0].Y = y2 - kMinWidthT;\r
+                                       poly3[1].X = x2 + kMinWidthT * 0.6;\r
+                                       poly3[1].Y = y2 - kMinWidthT * 0.6;\r
+                                       poly3[2].X = x2 + kMinWidthT;\r
+                                       poly3[2].Y = y2;\r
+                                       poly3[3].X = x2 + kMinWidthT * 0.6;\r
+                                       poly3[3].Y = y2 + kMinWidthT * 0.6;\r
+                                       poly3[4].X = x2;\r
+                                       poly3[4].Y = y2 + kMinWidthT;\r
+                                       icPolygon(poly3, 5);\r
+                               }\r
+                               \r
+                               if(a2 == 5){\r
+                                       //KAGI NO YOKO BOU NO HANE\r
+                                       poly[0].X = x2;\r
+                                       poly[0].Y = y2 - kMinWidthT + 1;\r
+                                       poly[1].X = x2 + 2;\r
+                                       poly[1].Y = y2 - kMinWidthT - kWidth * 5;\r
+                                       poly[2].X = x2;\r
+                                       poly[2].Y = y2 - kMinWidthT - kWidth * 5;\r
+                                       poly[3].X = x2 - kMinWidthT;\r
+                                       poly[3].Y = y2 - kMinWidthT + 1;\r
+                                       icPolygon(poly, 4);\r
+                               }\r
+                       }\r
+                       else{\r
+                               switch(a1){\r
+                               case 0:\r
+                                       poly[0].X = x1;\r
+                                       poly[0].Y = y1 - kMinWidthY;\r
+                                       poly[3].X = x1;\r
+                                       poly[3].Y = y1 + kMinWidthY;\r
+                                       break;\r
+                               case 2:\r
+                                       poly[0].X = x1 - kMinWidthT;\r
+                                       poly[0].Y = y1 - kMinWidthY;\r
+                                       poly[3].X = x1 - kMinWidthT;\r
+                                       poly[3].Y = y1 + kMinWidthY;\r
+                                       break;\r
+                               }\r
+                               \r
+                               switch(a2){\r
+                               case 0:\r
+                                       poly[1].X = x2;\r
+                                       poly[1].Y = y2 - kMinWidthY;\r
+                                       poly[2].X = x2;\r
+                                       poly[2].Y = y2 + kMinWidthY;\r
+                                       break;\r
+                               case 2:\r
+                                       poly[1].X = x2 + kMinWidthT;\r
+                                       poly[1].Y = y2 - kMinWidthY;\r
+                                       poly[2].X = x2 + kMinWidthT;\r
+                                       poly[2].Y = y2 + kMinWidthY;\r
+                               }\r
+                               \r
+                               icPolygon(poly, 4);\r
+                               \r
+                               //UROKO\r
+                               if(a2 == 0){\r
+                                       poly2[0].X = x2;\r
+                                       poly2[0].Y = y2 - kMinWidthY;\r
+                                       poly2[1].X = x2 - 24;\r
+                                       poly2[1].Y = y2;\r
+                                       poly2[2].X = x2 - 12;\r
+                                       poly2[2].Y = y2 - 12;\r
+                                       icPolygon(poly2, 3);\r
+                               }\r
+                       }\r
+               }\r
+               else{ //for others, use x-axis\r
+                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                       if((abs(y2 - y1) < abs(x2 - x1)) && (a1 != 6) && (a2 != 6)){ //ASAI KAUDO\r
+                               switch(a1){ //must be 0 or 2\r
+                               case 0:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthY;\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthY;\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthY;\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthY;\r
+                                       break;\r
+                               case 2:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthY - kMinWidthT * cos(rad);\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthY - kMinWidthT * sin(rad);\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthY - kMinWidthT * cos(rad);\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthY - kMinWidthT * sin(rad);\r
+                                       break;\r
+                               }\r
+                               \r
+                               switch(a2){ //must be 0 or 2\r
+                               case 0:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthY;\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthY;\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthY;\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthY;\r
+                                       break;\r
+                               case 2:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthY + kMinWidthT * cos(rad);\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthY + kMinWidthT * sin(rad);\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthY + kMinWidthT * cos(rad);\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthY + kMinWidthT * sin(rad);\r
+                               }\r
+                               \r
+                               icPolygon(poly, 4);\r
+                               \r
+                               //UROKO\r
+                               if(a2 == 0){\r
+                                       poly2[0].X = x2 + sin(rad) * kMinWidthY;\r
+                                       poly2[0].Y = y2 - cos(rad) * kMinWidthY;\r
+                                       poly2[1].X = x2 - cos(rad) * 24;\r
+                                       poly2[1].Y = y2 - sin(rad) * 24;\r
+                                       poly2[2].X = x2 - cos(rad) * 12 + sin(rad) * 12;\r
+                                       poly2[2].Y = y2 - sin(rad) * 12 - cos(rad) * 12;\r
+                                       icPolygon(poly2, 3);\r
+                               }\r
+                       }\r
+                       \r
+                       else{ //KAKUDO GA FUKAI or KAGI NO YOKO BOU\r
+                               if(x1 > x2){ v = -1; } else{ v = 1; }\r
+                               switch(a1){\r
+                               case 0:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthT * v + kMinWidthY * cos(rad) * 0.5 * v;\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthT * v + kMinWidthY * sin(rad) * 0.5 * v;\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthT * v - kMinWidthY * cos(rad) * 0.5 * v;\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthT * v - kMinWidthY * sin(rad) * 0.5 * v;\r
+                                       break;\r
+                               case 1:\r
+                               case 6:\r
+                               case 22:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthT * v;\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthT * v;\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthT * v;\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthT * v;\r
+                                       break;\r
+                               case 12:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthT * v - kMinWidthY * cos(rad) * v;\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthT * v - kMinWidthY * sin(rad) * v;\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthT * v - (kMinWidthT + kMinWidthY) * cos(rad) * v;\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthT * v - (kMinWidthT + kMinWidthY) * sin(rad) * v;\r
+                                       break;\r
+                               case 32:\r
+                                       poly[0].X = x1 + sin(rad) * kMinWidthT * v - kMinWidthY * cos(rad) * v;\r
+                                       poly[0].Y = y1 - cos(rad) * kMinWidthT * v - kMinWidthY * sin(rad) * v;\r
+                                       poly[3].X = x1 - sin(rad) * kMinWidthT * v - kMinWidthY * cos(rad) * v;\r
+                                       poly[3].Y = y1 + cos(rad) * kMinWidthT * v - kMinWidthY * sin(rad) * v;\r
+                                       break;\r
+                               }\r
+                               \r
+                               switch(a2){\r
+                               case 0:\r
+                                       if(a1 == 6){\r
+                                               poly[1].X = x2 + sin(rad) * kMinWidthT * v;\r
+                                               poly[1].Y = y2 - cos(rad) * kMinWidthT * v;\r
+                                               poly[2].X = x2 - sin(rad) * kMinWidthT * v;\r
+                                               poly[2].Y = y2 + cos(rad) * kMinWidthT * v;\r
+                                       }\r
+                                       else{\r
+                                               poly[1].X = x2 + sin(rad) * kMinWidthT * v - kMinWidthT * 0.5 * cos(rad) * v;\r
+                                               poly[1].Y = y2 - cos(rad) * kMinWidthT * v - kMinWidthT * 0.5 * sin(rad) * v;\r
+                                               poly[2].X = x2 - sin(rad) * kMinWidthT * v + kMinWidthT * 0.5 * cos(rad) * v;\r
+                                               poly[2].Y = y2 + cos(rad) * kMinWidthT * v + kMinWidthT * 0.5 * sin(rad) * v;\r
+                                       }\r
+                                       break;\r
+                               case 1:\r
+                               case 5:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthT * v;\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthT * v;\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthT * v;\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthT * v;\r
+                                       break;\r
+                               case 13:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthT * v + kWidth * kKakato * cos(rad) * v;\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthT * v + kWidth * kKakato * sin(rad) * v;\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthT * v + (kWidth * kKakato + kMinWidthT) * cos(rad) * v;\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthT * v + (kWidth * kKakato + kMinWidthT) * sin(rad) * v;\r
+                                       break;\r
+                               case 23:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthT * v + kWidth * kKakato * 0.5 * cos(rad) * v;\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthT * v + kWidth * kKakato * 0.5 * sin(rad) * v;\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthT * v + (kWidth * kKakato * 0.5 + kMinWidthT) * cos(rad) * v;\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthT * v + (kWidth * kKakato * 0.5 + kMinWidthT) * sin(rad) * v;\r
+                                       break;\r
+                               case 32:\r
+                                       poly[1].X = x2 + sin(rad) * kMinWidthT * v + kMinWidthY * cos(rad) * v;\r
+                                       poly[1].Y = y2 - cos(rad) * kMinWidthT * v + kMinWidthY * sin(rad) * v;\r
+                                       poly[2].X = x2 - sin(rad) * kMinWidthT * v + kMinWidthY * cos(rad) * v;\r
+                                       poly[2].Y = y2 + cos(rad) * kMinWidthT * v + kMinWidthY * sin(rad) * v;\r
+                                       break;\r
+                               }\r
+                               \r
+                               icPolygon(poly, 4);\r
+                               \r
+                               if((a1 == 6) && (a2 == 0 || a2 == 5)){ //KAGI NO YOKO BOU NO SAIGO NO MARU\r
+                                       poly3[0].X = x2 + sin(rad) * kMinWidthT * v;\r
+                                       poly3[0].Y = y2 - cos(rad) * kMinWidthT * v;\r
+                                       poly3[1].X = x2 + cos(rad) * kMinWidthT * 0.8 * v + sin(rad) * kMinWidthT * 0.6 * v;\r
+                                       poly3[1].Y = y2 + sin(rad) * kMinWidthT * 0.8 * v - cos(rad) * kMinWidthT * 0.6 * v;\r
+                                       poly3[2].X = x2 + cos(rad) * kMinWidthT * v;\r
+                                       poly3[2].Y = y2 + sin(rad) * kMinWidthT * v;\r
+                                       poly3[3].X = x2 + cos(rad) * kMinWidthT * 0.8 * v - sin(rad) * kMinWidthT * 0.6 * v;\r
+                                       poly3[3].Y = y2 + sin(rad) * kMinWidthT * 0.8 * v + cos(rad) * kMinWidthT * 0.6 * v;\r
+                                       poly3[4].X = x2 - sin(rad) * kMinWidthT * v;\r
+                                       poly3[4].Y = y2 + cos(rad) * kMinWidthT * v;\r
+                                       icPolygon(poly3, 5);\r
+                               }\r
+                               \r
+                               if(a1 == 6 && a2 == 5){\r
+                                       //KAGI NO YOKO BOU NO HANE\r
+                                       poly[0].X = x2 + (kMinWidthT - 1) * sin(rad) * v;\r
+                                       poly[0].Y = y2 - (kMinWidthT - 1) * cos(rad) * v;\r
+                                       poly[1].X = x2 + 2 * cos(rad) * v + (kMinWidthT + kWidth * 5) * sin(rad) * v;\r
+                                       poly[1].Y = y2 + 2 * sin(rad) * v - (kMinWidthT + kWidth * 5) * cos(rad) * v;\r
+                                       poly[2].X = x2 + (kMinWidthT + kWidth * 5) * sin(rad) * v;\r
+                                       poly[2].Y = y2 - (kMinWidthT + kWidth * 5) * cos(rad) * v;\r
+                                       poly[3].X = x2 + (kMinWidthT - 1) * sin(rad) * v - kMinWidthT * cos(rad) * v;\r
+                                       poly[3].Y = y2 - (kMinWidthT - 1) * cos(rad) * v - kMinWidthT * sin(rad) * v;\r
+                                       icPolygon(poly, 4);\r
+                               }\r
+                               \r
+                               if(a1 == 22){ //SHIKAKU MIGIUE UROKO NANAME DEMO MASSUGU MUKI\r
+                                       poly3[0].X = x1 - kMinWidthT;\r
+                                       poly3[0].Y = y1 - kMinWidthY;\r
+                                       poly3[1].X = x1;\r
+                                       poly3[1].Y = y1 - kMinWidthY - kWidth;\r
+                                       poly3[2].X = x1 + kMinWidthT + kWidth;\r
+                                       poly3[2].Y = y1 + kMinWidthY;\r
+                                       poly3[3].X = x1 + kMinWidthT;\r
+                                       poly3[3].Y = y1 + kMinWidthT;\r
+                                       poly3[4].X = x1 - kMinWidthT;\r
+                                       poly3[4].Y = y1;\r
+                                       icPolygon(poly3, 5);\r
+                               }\r
+                               \r
+                               XX = sin(rad) * v;\r
+                               XY = cos(rad) * v * -1;\r
+                               YX = cos(rad) * v;\r
+                               YY = sin(rad) * v;\r
+                               \r
+                               if(a1 == 0){ //beginning of the storke\r
+                                       poly2[0].X = x1 + kMinWidthT * XX + (kMinWidthY * 0.5) * YX;\r
+                                       poly2[0].Y = y1 + kMinWidthT * XY + (kMinWidthY * 0.5) * YY;\r
+                                       poly2[1].X = x1 + (kMinWidthT + kMinWidthT * 0.5) * XX + (kMinWidthY * 0.5 + kMinWidthY) * YX;\r
+                                       poly2[1].Y = y1 + (kMinWidthT + kMinWidthT * 0.5) * XY + (kMinWidthY * 0.5 + kMinWidthY) * YY;\r
+                                       poly2[2].X = x1 + kMinWidthT * XX + (kMinWidthY * 0.5 + kMinWidthY * 2) * YX;\r
+                                       poly2[2].Y = y1 + kMinWidthT * XY + (kMinWidthY * 0.5 + kMinWidthY * 2) * YY;\r
+                                       icPolygon(poly2, 3);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       else{ //gothic\r
+               if(tx1 == tx2){ //if TATE stroke, use y-axis\r
+                       if(ty1 > ty2){\r
+                               x1 = tx2;\r
+                               y1 = ty2;\r
+                               x2 = tx1;\r
+                               y2 = ty1;\r
+                               a1 = ta2;\r
+                               a2 = ta1;\r
+                       }\r
+                       else{\r
+                               x1 = tx1;\r
+                               y1 = ty1;\r
+                               x2 = tx2;\r
+                               y2 = ty2;\r
+                               a1 = ta1;\r
+                               a2 = ta2;\r
+                       }\r
+                       \r
+                       if(a1 % 10 == 2){ y1 = y1 - kWidth; }\r
+                       if(a2 % 10 == 2){ y2 = y2 + kWidth; }\r
+                       if(a1 % 10 == 3){ y1 = y1 - kWidth * kKakato; }\r
+                       if(a2 % 10 == 3){ y2 = y2 + kWidth * kKakato; }\r
+                       \r
+                       poly[0].X = x1 - kWidth;\r
+                       poly[0].Y = y1;\r
+                       poly[1].X = x2 - kWidth;\r
+                       poly[1].Y = y2;\r
+                       poly[2].X = x2 + kWidth;\r
+                       poly[2].Y = y2;\r
+                       poly[3].X = x1 + kWidth;\r
+                       poly[3].Y = y1;\r
+                       \r
+                       icPolygon(poly, 4);\r
+               }\r
+               else if(ty1 == ty2){ //if YOKO stroke, use x-axis\r
+                       if(tx1 > tx2){\r
+                               x1 = tx2;\r
+                               y1 = ty2;\r
+                               x2 = tx1;\r
+                               y2 = ty1;\r
+                               a1 = ta2;\r
+                               a2 = ta1;\r
+                       }\r
+                       else{\r
+                               x1 = tx1;\r
+                               y1 = ty1;\r
+                               x2 = tx2;\r
+                               y2 = ty2;\r
+                               a1 = ta1;\r
+                               a2 = ta2;\r
+                       }\r
+                       if(a1 % 10 == 2){ x1 = x1 - kWidth; }\r
+                       if(a2 % 10 == 2){ x2 = x2 + kWidth; }\r
+                       if(a1 % 10 == 3){ x1 = x1 - kWidth * kKakato; }\r
+                       if(a2 % 10 == 3){ x2 = x2 + kWidth * kKakato; }\r
+                       \r
+                       poly[0].X = x1;\r
+                       poly[0].Y = y1 - kWidth;\r
+                       poly[1].X = x2;\r
+                       poly[1].Y = y2 - kWidth;\r
+                       poly[2].X = x2;\r
+                       poly[2].Y = y2 + kWidth;\r
+                       poly[3].X = x1;\r
+                       poly[3].Y = y1 + kWidth;\r
+                       \r
+                       icPolygon(poly, 4);\r
+               }\r
+               else{ //for others, use x-axis\r
+                       if(tx1 > tx2){\r
+                               x1 = tx2;\r
+                               y1 = ty2;\r
+                               x2 = tx1;\r
+                               y2 = ty1;\r
+                               a1 = ta2;\r
+                               a2 = ta1;\r
+                       }\r
+                       else{\r
+                               x1 = tx1;\r
+                               y1 = ty1;\r
+                               x2 = tx2;\r
+                               y2 = ty2;\r
+                               a1 = ta1;\r
+                               a2 = ta2;\r
+                       }\r
+                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                       if(a1 % 10 == 2){\r
+                               x1 = x1 - kWidth * cos(rad);\r
+                               y1 = y1 - kWidth * sin(rad);\r
+                       }\r
+                       if(a2 % 10 == 2){\r
+                               x2 = x2 + kWidth * cos(rad);\r
+                               y2 = y2 + kWidth * sin(rad);\r
+                       }\r
+                       if(a1 % 10 == 3){\r
+                               x1 = x1 - kWidth * cos(rad) * kKakato;\r
+                               y1 = y1 - kWidth * sin(rad) * kKakato;\r
+                       }\r
+                       if(a2 % 10 == 3){\r
+                               x2 = x2 + kWidth * cos(rad) * kKakato;\r
+                               y2 = y2 + kWidth * sin(rad) * kKakato;\r
+                       }\r
+                       \r
+                       //SUICHOKU NO ICHI ZURASHI HA sin TO cos NO IREKAE + x-axis MAINASU KA\r
+                       poly[0].X = x1 + sin(rad) * kWidth;\r
+                       poly[0].Y = y1 - cos(rad) * kWidth;\r
+                       poly[1].X = x2 + sin(rad) * kWidth;\r
+                       poly[1].Y = y2 - cos(rad) * kWidth;\r
+                       poly[2].X = x2 - sin(rad) * kWidth;\r
+                       poly[2].Y = y2 + cos(rad) * kWidth;\r
+                       poly[3].X = x1 - sin(rad) * kWidth;\r
+                       poly[3].Y = y1 + cos(rad) * kWidth;\r
+                       \r
+                       icPolygon(poly, 4);\r
+               }\r
+       }\r
+}\r
diff --git a/kagecgi/kagecgi.c b/kagecgi/kagecgi.c
new file mode 100755 (executable)
index 0000000..6fce983
--- /dev/null
@@ -0,0 +1,193 @@
+//kagecgi.c\r
+//\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <png.h>\r
+#include <glib.h>\r
+#include "kage.h"\r
+#include "kagecgi.h"\r
+\r
+int main(int argc, char *argv[]){\r
+       GString *tmp1, *tmp2, *test1, *test2, *filename;\r
+       FILE *err, *fp;\r
+       char errbuf[errorFileSize];\r
+       char *pos, *cur;\r
+       int dummy;\r
+       int i;\r
+\r
+       dummy = initDB();\r
+\r
+       //set default\r
+       kShotai = kMincho;\r
+//     kShotai = kGothic;\r
+//     kDesign = 0; //jp\r
+       kSize = 200;\r
+       kType = 0; //png\r
+       kInput = 0; //ids or direct\r
+       kResultText = g_string_new("");\r
+       kMode = 0;\r
+       \r
+       //set some param by request\r
+//     tmp1 = g_string_new((gchar *)argv[1]);\r
+       tmp1 = g_string_new((gchar *)getenv("QUERY_STRING"));\r
+       pos = tmp1->str;\r
+       \r
+       //separate token\r
+       if(tmp1->len != 0){\r
+               while(1){\r
+                       cur = strchr(pos, '&');\r
+                       tmp2 = g_string_new(pos);\r
+                       if(cur != NULL) g_string_set_size(tmp2, cur - pos);\r
+                       //got request string\r
+//                     if(strncmp(tmp2->str, "design=jp", 9) == 0) kDesign = 0;\r
+//                     else if(strncmp(tmp2->str, "design=cs", 9) == 0) kDesign = 10;\r
+//                     else if(strncmp(tmp2->str, "design=ct", 9) == 0) kDesign = 11;\r
+//                     else if(strncmp(tmp2->str, "design=kr", 9) == 0) kDesign = 20;\r
+//                     else if(strncmp(tmp2->str, "design=vn", 9) == 0) kDesign = 30;\r
+//                     else if(strncmp(tmp2->str, "design=un", 9) == 0) kDesign = 40;\r
+//                     else if(strncmp(tmp2->str, "shotai=mincho", 13) == 0) kShotai = kMincho;\r
+                       if(strncmp(tmp2->str, "shotai=mincho", 13) == 0) kShotai = kMincho;\r
+                       else if(strncmp(tmp2->str, "shotai=gothic", 13) == 0) kShotai = kGothic;\r
+                       else if(strncmp(tmp2->str, "shotai=skeleton", 15) == 0) kShotai = kGothic;\r
+                       else if(strncmp(tmp2->str, "type=png", 8) == 0) kType = 0;\r
+                       else if(strncmp(tmp2->str, "type=svg", 8) == 0) kType = 1;\r
+                       else if(strncmp(tmp2->str, "type=eps", 8) == 0) kType = 2;\r
+                       else if(strncmp(tmp2->str, "type=raw", 8) == 0) kType = 3;\r
+                       else if(strncmp(tmp2->str, "input=ids", 9) == 0) kInput = 0;\r
+                       else if(strncmp(tmp2->str, "input=directwithadjust", 22) == 0) kInput = 2;\r
+                       else if(strncmp(tmp2->str, "input=direct", 12) == 0) kInput = 1;\r
+                       else if(strncmp(tmp2->str, "size=24", 7) == 0) kSize = 24;\r
+                       else if(strncmp(tmp2->str, "size=200", 8) == 0) kSize = 200;\r
+                       else test1 = g_string_new(tmp2->str);\r
+                       if(cur == NULL) break;\r
+                       pos = cur + 1;\r
+               }\r
+       }\r
+       else{ // redirected request\r
+               kInput = 0;\r
+               tmp1 = g_string_new((gchar *)getenv("REDIRECT_URL"));\r
+               pos = tmp1->str;\r
+               while(1){\r
+                       cur = strchr(pos, '/');\r
+                       tmp2 = g_string_new(pos);\r
+                       if(cur != NULL) g_string_set_size(tmp2, cur - pos);\r
+                       //got request string\r
+//                     if(strncmp(tmp2->str, "jp", 2) == 0) kDesign = 0;\r
+//                     else if(strncmp(tmp2->str, "cs", 2) == 0) kDesign = 10;\r
+//                     else if(strncmp(tmp2->str, "ct", 2) == 0) kDesign = 11;\r
+//                     else if(strncmp(tmp2->str, "kr", 2) == 0) kDesign = 20;\r
+//                     else if(strncmp(tmp2->str, "vn", 2) == 0) kDesign = 30;\r
+//                     else if(strncmp(tmp2->str, "un", 2) == 0) kDesign = 40;\r
+//                     else if(strncmp(tmp2->str, "mincho", 6) == 0) kShotai = kMincho;\r
+                       if(strncmp(tmp2->str, "mincho", 6) == 0) kShotai = kMincho;\r
+                       else if(strncmp(tmp2->str, "gothic", 6) == 0) kShotai = kGothic;\r
+                       else if(strncmp(tmp2->str, "skeleton", 8) == 0) kShotai = kGothic;\r
+                       else if(strncmp(tmp2->str, "v0.4", 4) == 0);\r
+                       else test1 = g_string_new(tmp2->str);\r
+                       if(cur == NULL) break;\r
+                       pos = cur + 1;\r
+               }\r
+               if(strncmp(test1->str + test1->len - 4, ".png", 4) == 0) kType = 0;\r
+               if(strncmp(test1->str + test1->len - 4, ".svg", 4) == 0) kType = 1;\r
+               if(strncmp(test1->str + test1->len - 4, ".eps", 4) == 0) kType = 2;\r
+               if(strncmp(test1->str + test1->len - 4, ".raw", 4) == 0) kType = 3;\r
+               g_string_set_size(test1, test1->len - 4);\r
+       }\r
+       \r
+       //clear result buffer\r
+       test2 = g_string_new("");\r
+       if(kType == 2){\r
+               g_string_append(kResultText, "%!PS-Adobe-3.0 EPSF-3.0\n");\r
+               g_string_append(kResultText, "%%BoundingBox: 0 -208 1024 816\n");\r
+               g_string_append(kResultText, "%%Pages: 0\n");\r
+               g_string_append(kResultText, "%%Title: ");\r
+               g_string_append(kResultText, test1->str);\r
+               g_string_append(kResultText, "\n");\r
+               g_string_append(kResultText, "%%Creator: KAGE System\n");\r
+               g_string_append(kResultText, "%%CreationDate: 00:00 1-1-2004\n");\r
+               g_string_append(kResultText, "%%EndComments\n");\r
+               g_string_append(kResultText, "%%EndProlog\n");\r
+               g_string_append(kResultText, "%%Page \"");\r
+               g_string_append(kResultText, test1->str);\r
+               g_string_append(kResultText, "\" 1\n");\r
+               g_string_append(kResultText, "newpath\n");\r
+       }\r
+       kageCanvas = initPng(canvasWidth, canvasHeight);\r
+       if(kInput == 0) generateGlyph(test1, test2);\r
+       else{\r
+         convert99(test1, test2);\r
+         //      g_string_append(test2, test1->str);\r
+       }\r
+\r
+       if(kType == 0){ //png(image)\r
+               if(test2->len != 0){\r
+                 if(kInput != 1){ //0 and 2\r
+                   test2 = CalcSizes(test2, 1);\r
+                 }\r
+                       DrawBox();\r
+                       drawGlyph(test2, 0);\r
+                       //output to file\r
+                       filename = g_string_new(pngFilePath);\r
+//                     if(kDesign == 0) g_string_append(filename, "jp/");\r
+//                     else if(kDesign == 10) g_string_append(filename, "cs/");\r
+//                     else if(kDesign == 11) g_string_append(filename, "ct/");\r
+//                     else if(kDesign == 20) g_string_append(filename, "kr/");\r
+//                     else if(kDesign == 30) g_string_append(filename, "vn/");\r
+//                     else if(kDesign == 40) g_string_append(filename, "un/");\r
+                       if(kShotai == kMincho) g_string_append(filename, "mincho/");\r
+                       else if(kShotai == kGothic) g_string_append(filename, "gothic/");//skeleton??\r
+                       g_string_append(filename, test1->str);\r
+                       g_string_append(filename, ".png");\r
+                       \r
+//skip for adjustment mode\r
+//                     fp = fopen(filename->str, "w");\r
+//                     writePng(pngWidth, pngHeight, kageCanvas, fp);\r
+//                     fclose(fp);\r
+                       //output to stdout\r
+                       fprintf(stdout, "Content-type: image/png\n\n");\r
+                       writePng(pngWidth, pngHeight, kageCanvas, stdout);\r
+                       //done\r
+                       closePng(pngWidth, pngHeight, kageCanvas);\r
+               }\r
+               else{\r
+                       err = fopen("error.png", "r");\r
+                       fread(errbuf, sizeof(char), errorFileSize, err);\r
+               //      printf("An error occurred.\r\n");\r
+                       fprintf(stdout, "Content-type: image/png\n\n");\r
+                       fwrite(errbuf, sizeof(char), errorFileSize, stdout);\r
+                       fclose(err);\r
+               }\r
+       }\r
+       else if(kType == 1){ //svg(vector graphics)\r
+       }\r
+       else if(kType == 2){ //eps(vector graphics)\r
+               if(test2->len != 0){\r
+                       test2 = CalcSizes(test2, 1);\r
+                       kMode = 1;\r
+                       drawGlyph(test2, 0);\r
+                       g_string_append(kResultText, "fill\n");\r
+                       g_string_append(kResultText, "%%EOF\n");\r
+                       fprintf(stdout, "Content-type: application/postscript\n\n");\r
+                       fprintf(stdout, "%s", kResultText->str);\r
+               }\r
+               else{\r
+                       fprintf(stdout, "Content-type: text/plain\n\n");\r
+                       fprintf(stdout, "An error occurred.");\r
+               }\r
+       }\r
+       else{ //raw(text)\r
+               if(test2->len != 0){\r
+                       fprintf(stdout, "Content-type: text/plain\n\n");\r
+                       fprintf(stdout, "result=%s", test2->str);\r
+               }\r
+               else{\r
+                       fprintf(stdout, "Content-type: text/plain\n\n");\r
+                       fprintf(stdout, "result=nodata");\r
+               }\r
+       }\r
+       dummy = closeDB();\r
+       \r
+       return 0;\r
+}\r
+\r
diff --git a/kagecgi/kagecgi.h b/kagecgi/kagecgi.h
new file mode 100755 (executable)
index 0000000..36dad00
--- /dev/null
@@ -0,0 +1,85 @@
+//kagecgi.h\r
+//\r
+\r
+#include <db1/db.h>\r
+//#include <db2/db_185.h>\r
+\r
+#include <png.h>\r
+#include <glib.h>\r
+#include "kage.h"\r
+\r
+#ifndef _KAGECGI_H_\r
+#define _KAGECGI_H_\r
+\r
+// define for localhost environment\r
+#define errorFileSize 4009\r
+#define errorFileName "error.png"\r
+#define pngFilePath "/var/www/fontsjp/v0.4/"\r
+#define databaseFileName "../../kagedb/wiki"\r
+\r
+#define kBaseline 188\r
+#define pngWidth 200\r
+#define pngHeight 200\r
+#define canvasWidth 400\r
+#define canvasHeight 400\r
+\r
+#define min(x1,x2) ((x1) > (x2))? (x2):(x1)\r
+#define max(x1,x2) ((x1) > (x2))? (x1):(x2)\r
+\r
+DB *kDatabase;\r
+\r
+FILE *debug;\r
+\r
+png_bytepp kageCanvas;\r
+\r
+int kDesign;\r
+int kSize;\r
+int kType;\r
+int kInput;\r
+GString *kResultText;\r
+int kMode;\r
+\r
+void generateGlyph(const GString *in, GString *out);\r
+void searchPartsData(const GString *in, GString *out);\r
+void searchAliasData(const GString *in, GString *out);\r
+void searchCacheData(const GString *in, GString *out);\r
+void doCombine(const GString *in, GString *out);\r
+void drawGlyph(const GString *in, const int mode);\r
+\r
+int isIDS(const GString *in);\r
+void divideInto2(const GString *in, GString *partIDS1, GString *partIDS3);\r
+void divideInto3(const GString *in, GString *partIDS1, GString *partIDS2, GString *partIDS3);\r
+void addStrokeWithTransform(const GString *stroke, const int num, const int *tf, GString *out, int mode);\r
+void convertArray(int *buf, GString *out, int size, int mode);\r
+int * convertStroke(const char *in, int *a, int *size);\r
+void convert99(const GString *in, GString *out);\r
+void convert99calc(const char *in, GString *out);\r
+\r
+void DotsWidth(int *dlx, int *drx);\r
+void DotsHeight(int *dly, int *dry);\r
+void PartsWidth(const GString *in, int *lx, int *rx);\r
+void PartsHeight(const GString *in, int *ly, int *ry);\r
+GString * CalcSizes(const GString *in, int mode);\r
+void DrawBox();\r
+void CalcOptions(const GString *in, int *mitsudo, int *flag, double *yoko, double *tate);\r
+void DoDrawParts(const GString *in, const int lx1, const double rf1, const int ly1, const double rfy1);\r
+void DoDrawMixFont(const GString *in1, const int lx1, const double rf1, const GString *in2, const int lx2, const double rf2, const int ly1, const double rfy1, const int ly2, const double rfy2);\r
+\r
+void combineYoko2(const GString *parts1, const GString *parts3, int *result);\r
+void combineYoko3(const GString *parts1, const GString *parts2, const GString *parts3, int *result);\r
+void combineTate2(const GString *parts1, const GString *parts3, int *result);\r
+void combineTate3(const GString *parts1, const GString *parts2, const GString *parts3, int *result);\r
+void combineHame2(const GString *parts1, const GString *parts3, int *result);\r
+\r
+int initDB();\r
+int closeDB();\r
+void searchPartsData(const GString *in, GString *out);\r
+void searchAliasData(const GString *in, GString *out);\r
+\r
+png_bytepp initPng(int width, int height);\r
+int closePng(int width, int height, png_bytepp canvas);\r
+int writePng(int width, int height, png_bytepp image, FILE *fp);\r
+\r
+void fillPolygon(struct kPoint *p, int number, int col, unsigned char **image);\r
+\r
+#endif\r
diff --git a/kagecgi/kagechar.c b/kagecgi/kagechar.c
new file mode 100755 (executable)
index 0000000..daa2d25
--- /dev/null
@@ -0,0 +1,397 @@
+//kagechar.c\r
+//\r
+\r
+#include <glib.h>\r
+#include <stdlib.h>\r
+#include "kagecgi.h"\r
+#include "kage.h"\r
+\r
+int isIDS(const GString *in){\r
+       //check IDC "u2ff*"\r
+       if(strncmp(in->str, "u2ff", 4) == 0){\r
+               //check the last char\r
+               if('0' <= (in->str)[4] && (in->str)[4] <= 'a') return TRUE;\r
+       }\r
+       return FALSE;\r
+}\r
+\r
+void divideInto2(const GString *in, GString *partIDS1, GString *partIDS3){\r
+       GString *buffer[16];\r
+       char tmp[kMaxIDCLength + 1];\r
+       int i, counter, pointer, flag;\r
+       \r
+       g_string_set_size(partIDS1, 0);\r
+       \r
+       counter = 0;\r
+       pointer = 0;\r
+       for(i = 0; i < in->len; i++){\r
+               if((in->str)[i] == '.'){\r
+                       strncpy(tmp, (in->str) + pointer, i - pointer);\r
+                       tmp[i - pointer] = '\0';\r
+                       buffer[counter] = g_string_new(tmp);\r
+                       counter++;\r
+                       pointer = i + 1;\r
+               }\r
+       }\r
+       strncpy(tmp, (in->str) + pointer, i - pointer);\r
+       tmp[i - pointer] = '\0';\r
+       buffer[counter] = g_string_new(tmp);\r
+       counter++;\r
+       \r
+       //reject over-length of IDS\r
+       if(counter > kMaxIDSSequenceLength) return;\r
+       \r
+       //1st scan\r
+       pointer = 1;\r
+       flag = 0;\r
+       while(flag >= 0 && pointer < counter){\r
+               g_string_append(partIDS1, (buffer[pointer])->str);\r
+               g_string_append(partIDS1, ".");\r
+               if(strncmp((buffer[pointer])->str, "u2ff", 4) == 0){\r
+                       switch (((buffer[pointer])->str)[4]){\r
+                               case '0':\r
+                               case '1':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                               case 'a':\r
+                               case 'b':\r
+                                       flag++;\r
+                                       break;\r
+                               case '2':\r
+                               case '3':\r
+                                       flag = flag + 2;\r
+                                       break;\r
+                       }\r
+               }\r
+               else flag--;\r
+               pointer++;\r
+       }\r
+       g_string_erase(partIDS1, partIDS1->len - 1, 1);\r
+       \r
+       //2nd scan\r
+       flag = 0;\r
+       while(flag >= 0 && pointer < counter){\r
+               g_string_append(partIDS3, (buffer[pointer])->str);\r
+               g_string_append(partIDS3, ".");\r
+               if(strncmp((buffer[pointer])->str, "u2ff", 4) == 0){\r
+                       switch (((buffer[pointer])->str)[4]){\r
+                               case '0':\r
+                               case '1':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                               case 'a':\r
+                               case 'b':\r
+                                       flag++;\r
+                                       break;\r
+                               case '2':\r
+                               case '3':\r
+                                       flag = flag + 2;\r
+                                       break;\r
+                       }\r
+               }\r
+               else flag--;\r
+               pointer++;\r
+       }\r
+       g_string_erase(partIDS3, partIDS3->len - 1, 1);\r
+}\r
+\r
+void divideInto3(const GString *in, GString *partIDS1, GString *partIDS2, GString *partIDS3){\r
+       GString *buffer[16];\r
+       char tmp[kMaxIDCLength + 1];\r
+       int i, counter, pointer, flag;\r
+       \r
+       g_string_set_size(partIDS1, 0);\r
+       \r
+       counter = 0;\r
+       pointer = 0;\r
+       for(i = 0; i < in->len; i++){\r
+               if((in->str)[i] == '.'){\r
+                       strncpy(tmp, (in->str) + pointer, i - pointer);\r
+                       tmp[i - pointer] = '\0';\r
+                       buffer[counter] = g_string_new(tmp);\r
+                       counter++;\r
+                       pointer = i + 1;\r
+               }\r
+       }\r
+       strncpy(tmp, (in->str) + pointer, i - pointer);\r
+       tmp[i - pointer] = '\0';\r
+       buffer[counter] = g_string_new(tmp);\r
+       counter++;\r
+       \r
+       //reject over-length of IDS\r
+       if(counter > kMaxIDSSequenceLength) return;\r
+       \r
+       //1st scan\r
+       pointer = 1;\r
+       flag = 0;\r
+       while(flag >= 0 && pointer < counter){\r
+               g_string_append(partIDS1, (buffer[pointer])->str);\r
+               g_string_append(partIDS1, ".");\r
+               if(strncmp((buffer[pointer])->str, "u2ff", 4) == 0){\r
+                       switch (((buffer[pointer])->str)[4]){\r
+                               case '0':\r
+                               case '1':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                               case 'a':\r
+                               case 'b':\r
+                                       flag++;\r
+                                       break;\r
+                               case '2':\r
+                               case '3':\r
+                                       flag = flag + 2;\r
+                                       break;\r
+                       }\r
+               }\r
+               else flag--;\r
+               pointer++;\r
+       }\r
+       g_string_erase(partIDS1, partIDS1->len - 1, 1);\r
+       \r
+       //2nd scan\r
+       flag = 0;\r
+       while(flag >= 0 && pointer < counter){\r
+               g_string_append(partIDS2, (buffer[pointer])->str);\r
+               g_string_append(partIDS2, ".");\r
+               if(strncmp((buffer[pointer])->str, "u2ff", 4) == 0){\r
+                       switch (((buffer[pointer])->str)[4]){\r
+                               case '0':\r
+                               case '1':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                               case 'a':\r
+                               case 'b':\r
+                                       flag++;\r
+                                       break;\r
+                               case '2':\r
+                               case '3':\r
+                                       flag = flag + 2;\r
+                                       break;\r
+                       }\r
+               }\r
+               else flag--;\r
+               pointer++;\r
+       }\r
+       g_string_erase(partIDS2, partIDS2->len - 1, 1);\r
+       \r
+       //3rd scan\r
+       flag = 0;\r
+       while(flag >= 0 && pointer < counter){\r
+               g_string_append(partIDS3, (buffer[pointer])->str);\r
+               g_string_append(partIDS3, ".");\r
+               if(strncmp((buffer[pointer])->str, "u2ff", 4) == 0){\r
+                       switch (((buffer[pointer])->str)[4]){\r
+                               case '0':\r
+                               case '1':\r
+                               case '4':\r
+                               case '5':\r
+                               case '6':\r
+                               case '7':\r
+                               case '8':\r
+                               case '9':\r
+                               case 'a':\r
+                               case 'b':\r
+                                       flag++;\r
+                                       break;\r
+                               case '2':\r
+                               case '3':\r
+                                       flag = flag + 2;\r
+                                       break;\r
+                       }\r
+               }\r
+               else flag--;\r
+               pointer++;\r
+       }\r
+       g_string_erase(partIDS3, partIDS3->len - 1, 1);\r
+}\r
+\r
+void addStrokeWithTransform(const GString *stroke, const int num, const int *tf, GString *out, int mode){\r
+       int *buf, i, size;\r
+       GString *tmp;\r
+       \r
+       tmp = g_string_new("");\r
+       buf = convertStroke(stroke->str, buf, &size);\r
+       \r
+       for(i = 0; i < size; i++){\r
+               if(buf[i * 11 + 0] != 0 && buf[i * 11 + 0] != 99){\r
+                       buf[i * 11 + 3] =\r
+                        tf[(num - 1) * 4 + 0] + buf[i * 11 + 3] * (tf[(num - 1) * 4 + 2] - tf[(num - 1) * 4 + 0]) / pngWidth;\r
+                       buf[i * 11 + 5] =\r
+                        tf[(num - 1) * 4 + 0] + buf[i * 11 + 5] * (tf[(num - 1) * 4 + 2] - tf[(num - 1) * 4 + 0]) / pngWidth;\r
+                       buf[i * 11 + 7] =\r
+                        tf[(num - 1) * 4 + 0] + buf[i * 11 + 7] * (tf[(num - 1) * 4 + 2] - tf[(num - 1) * 4 + 0]) / pngWidth;\r
+                       buf[i * 11 + 9] =\r
+                        tf[(num - 1) * 4 + 0] + buf[i * 11 + 9] * (tf[(num - 1) * 4 + 2] - tf[(num - 1) * 4 + 0]) / pngWidth;\r
+                       buf[i * 11 + 4] =\r
+                        tf[(num - 1) * 4 + 1] + buf[i * 11 + 4] * (tf[(num - 1) * 4 + 3] - tf[(num - 1) * 4 + 1]) / pngHeight;\r
+                       buf[i * 11 + 6] =\r
+                        tf[(num - 1) * 4 + 1] + buf[i * 11 + 6] * (tf[(num - 1) * 4 + 3] - tf[(num - 1) * 4 + 1]) / pngHeight;\r
+                       buf[i * 11 + 8] =\r
+                        tf[(num - 1) * 4 + 1] + buf[i * 11 + 8] * (tf[(num - 1) * 4 + 3] - tf[(num - 1) * 4 + 1]) / pngHeight;\r
+                       buf[i * 11 + 10] =\r
+                        tf[(num - 1) * 4 + 1] + buf[i * 11 + 10] * (tf[(num - 1) * 4 + 3] - tf[(num - 1) * 4 + 1]) / pngHeight;\r
+               }\r
+       }\r
+       convertArray(buf, tmp, size, mode);\r
+       if(out->len != 0) g_string_append(out, "$");\r
+       g_string_append(out, tmp->str);\r
+       \r
+       free((void *)buf);\r
+}\r
+\r
+void convertArray(int *buf, GString *out, int size, int mode){\r
+       int i;\r
+       char tmp[kMaxStrokeDataLength];\r
+       \r
+       for(i = 0; i < size; i++){\r
+               if(!(mode == 1 && (buf[i * 11 + 0] == 0 || buf[i * 11 + 0] == 99))){\r
+                       sprintf(tmp, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d$",\r
+                        buf[i * 11 + 0],\r
+                        buf[i * 11 + 1],\r
+                        buf[i * 11 + 2],\r
+                        buf[i * 11 + 3],\r
+                        buf[i * 11 + 4],\r
+                        buf[i * 11 + 5],\r
+                        buf[i * 11 + 6],\r
+                        buf[i * 11 + 7],\r
+                        buf[i * 11 + 8],\r
+                        buf[i * 11 + 9],\r
+                        buf[i * 11 + 10]);\r
+                       g_string_append(out, tmp);\r
+               }\r
+       }\r
+       g_string_erase(out, (out->len - 1), 1);\r
+}\r
+\r
+int * convertStroke(const char *in, int *a, int *size){\r
+       int i, counter, pointer;\r
+       int a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10;\r
+       char tmp[kMaxStrokeDataLength + 1];\r
+       \r
+       a = (int *)malloc(0);\r
+       counter = 0;\r
+       pointer = 0;\r
+       for(i = 0; i < strlen(in); i++){\r
+               if(in[i] == '$'){\r
+                       strncpy(tmp, &in[pointer], i - pointer);\r
+                       tmp[i - pointer] = '\0';\r
+                       a = (int *)realloc(a, sizeof(int) * 11 * (counter + 1));\r
+                       sscanf(tmp, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",\r
+                        &a0,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8,&a9,&a10);\r
+                       a[counter * 11 + 0] = a0;\r
+                       a[counter * 11 + 1] = a1;\r
+                       a[counter * 11 + 2] = a2;\r
+                       a[counter * 11 + 3] = a3;\r
+                       a[counter * 11 + 4] = a4;\r
+                       a[counter * 11 + 5] = a5;\r
+                       a[counter * 11 + 6] = a6;\r
+                       a[counter * 11 + 7] = a7;\r
+                       a[counter * 11 + 8] = a8;\r
+                       a[counter * 11 + 9] = a9;\r
+                       a[counter * 11 + 10] = a10;\r
+                       counter++;\r
+                       pointer = i + 1;\r
+               }\r
+       }\r
+       strncpy(tmp, &in[pointer], i - pointer);\r
+       tmp[i - pointer] = '\0';\r
+       a = (int *)realloc(a, sizeof(int) * 11 * (counter + 1));\r
+                       sscanf(tmp, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",\r
+                        &a0,&a1,&a2,&a3,&a4,&a5,&a6,&a7,&a8,&a9,&a10);\r
+                       a[counter * 11 + 0] = a0;\r
+                       a[counter * 11 + 1] = a1;\r
+                       a[counter * 11 + 2] = a2;\r
+                       a[counter * 11 + 3] = a3;\r
+                       a[counter * 11 + 4] = a4;\r
+                       a[counter * 11 + 5] = a5;\r
+                       a[counter * 11 + 6] = a6;\r
+                       a[counter * 11 + 7] = a7;\r
+                       a[counter * 11 + 8] = a8;\r
+                       a[counter * 11 + 9] = a9;\r
+                       a[counter * 11 + 10] = a10;\r
+               counter++;\r
+       *(size) = counter;\r
+       return a;\r
+}\r
+\r
+void convert99(const GString *in, GString *out){\r
+       int i, pointer;\r
+       char tmp[kMaxStrokeDataLength + 1];\r
+       GString *buf;\r
+       \r
+       g_string_set_size(out, 0);\r
+       buf = g_string_new("");\r
+       pointer = 0;\r
+       for(i = 0; i < in->len; i++){\r
+               if((in->str)[i] == '$'){\r
+                       strncpy(tmp, in->str + pointer, i - pointer);\r
+                       tmp[i - pointer] = '\0';\r
+                       if(strncmp(tmp, "99:", 3) == 0){\r
+                               convert99calc(tmp, buf);\r
+                               if(buf->len == 0){\r
+                                       g_string_set_size(out, 0);\r
+                                       return;\r
+                               }\r
+                               g_string_append(out, buf->str);\r
+                       }\r
+                       else g_string_append(out, tmp);\r
+                       g_string_append(out, "$");\r
+                       \r
+                       pointer = i + 1;\r
+               }\r
+       }\r
+       strncpy(tmp, in->str + pointer, i - pointer);\r
+       tmp[i - pointer] = '\0';\r
+       if(strncmp(tmp, "99:", 3) == 0){\r
+               convert99calc(tmp, buf);\r
+               if(buf->len == 0){\r
+                       g_string_set_size(out, 0);\r
+                       return;\r
+               }\r
+               g_string_append(out, buf->str);\r
+       }\r
+       else g_string_append(out, tmp);\r
+}\r
+\r
+void convert99calc(const char *in, GString *out){\r
+       GString *buf1, *buf2;\r
+       int a1,x1,y1,x2,y2,option,option2;\r
+       char pname[kMaxStrokeDataLength];\r
+       int tf[12];\r
+       char *end;\r
+       \r
+       g_string_set_size(out, 0);\r
+       buf2 = g_string_new("");\r
+       \r
+       //get parts data\r
+       sscanf(in, "%d:%d:%d:%d:%d:%d:%d:%s",\r
+               &a1,&option,&option2,&x1,&y1,&x2,&y2,pname);\r
+       //end = strchr(pname, ':');\r
+       //*end = '\0';\r
+       buf1 = g_string_new(pname);\r
+       generateGlyph(buf1, buf2);\r
+       if(buf2->len == 0) return;\r
+       \r
+       //convert\r
+       tf[0] = x1;\r
+       tf[1] = y1;\r
+       tf[2] = x2;\r
+       tf[3] = y2;\r
+       addStrokeWithTransform(buf2, 1, tf, out, 1);\r
+}\r
diff --git a/kagecgi/kagecomb.c b/kagecgi/kagecomb.c
new file mode 100755 (executable)
index 0000000..d90f0e0
--- /dev/null
@@ -0,0 +1,400 @@
+//kagecomb.c\r
+//\r
+#include <glib.h>\r
+#include <math.h>\r
+#include <stdlib.h>\r
+#include "kagecgi.h"\r
+#include "kage.h"\r
+\r
+void combineYoko2(const GString *parts1, const GString *parts3, int *result){\r
+    int f, g, h, i, j, k, l;\r
+    int flg_boxL, flg_boxR;\r
+    int Xside, YsideLa, YsideLb, YsideRa, YsideRb, YheightL, YnanameL, YsmallL;\r
+    int pxL, pxR, pyL, pyR;\r
+    double prL, prR, pryL, pryR, rL, rR, rTemp;\r
+    int lxL, rxL, lxR, rxR;\r
+    int dlyL, dryL, dlyR, dryR;\r
+    int chk_y1, chk_y2;\r
+    int mitsuL, mitsuR;\r
+    double yokoL, tateL, yokoR, tateR;\r
+       int *buf, strokes;\r
+       int tempShotai;\r
+       \r
+       //initialize\r
+    pxL = 0;\r
+    pyL = 0;\r
+    prL = 1.0;\r
+    pryL = 1.0;\r
+    pxR = 0;\r
+    pyR = 0;\r
+    prR = 1.0;\r
+    pryR = 1.0;\r
+       \r
+    YsideLa = 0;\r
+    YsideLb = 0;\r
+    YsideRa = 0;\r
+    YsideRb = 0;\r
+       YnanameL = 0;\r
+    YheightL = pngWidth * 0.9;\r
+       \r
+       tempShotai = kShotai;\r
+       kShotai = kGothic;\r
+       \r
+    CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);\r
+    CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);\r
+       \r
+       //left parts Y-axis processing #1\r
+    //if its upper and bottom are flat\r
+    if(flg_boxL % 8 / 4 != 0) YsideLa++;\r
+    if(flg_boxL % 16 / 8 != 0) YsideLb++;\r
+       \r
+    //if its goes right-up\r
+       if(flg_boxL % 1024 / 512 == 0){\r
+           j = 0;\r
+               buf = convertStroke(parts1->str, buf, &strokes);\r
+               for(i = 0; i < strokes; i++) if(buf[i * 11 + 0] / 10 == 1) j++;\r
+           free(buf);\r
+           l = 0;\r
+           if(j != 0){\r
+                       YsideLb++;\r
+               YnanameL++;\r
+               }\r
+       }\r
+    YheightL = YheightL - (YsideLa + YsideLb) * 2 * kWidth;\r
+       \r
+       //left parts Y-axis processing #2\r
+    YsmallL = 0;\r
+       if(flg_boxL % 1024 / 512 == 0){\r
+               YsmallL = 1;\r
+           if(flg_boxL % 16 / 8 != 0 && flg_boxL % 8 / 4 != 0 && tateL <= 4) YheightL = (double)YheightL * (max(0.65, tateL * 0.22));\r
+               else if(flg_boxL % 16 / 8 != 0 && tateL <= 3) YheightL = (double)YheightL * 0.8;\r
+       else if(YnanameL != 0 && flg_boxL % 8 / 4 != 0 && tateL <= 4) YheightL = (double)YheightL * (max(0.65, tateL * 0.22));\r
+           else if(YnanameL != 0 && tateL <= 3) YheightL = (double)YheightL * 0.8;\r
+           else YsmallL = 0;\r
+       }\r
+       \r
+       //left parts Y-axis processing #3\r
+    DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
+    DotsHeight(&dlyL, &dryL);\r
+    pryL = (double)YheightL / (dryL - dlyL);\r
+       \r
+    if(YsmallL != 0){\r
+        if(flg_boxL % 8 / 4 != 0) pyL = kBaseline - (double)pngWidth * 0.9 + 6 * kWidth - dlyL * pryL;\r
+        else pyL = kBaseline - (double)pngWidth * 0.9 + 2 * kWidth - dlyL * pryL;\r
+    }\r
+    else{\r
+        if(flg_boxL % 16 / 8 != 0 || YnanameL != 0) pyL = kBaseline - 2 * kWidth - dryL * pryL;\r
+        else pyL = kBaseline - dryL * pryL;\r
+    }\r
+       \r
+       //right parts Y-axis processing #1\r
+    if(flg_boxR % 8 / 4 != 0) YsideRa++;\r
+    if(flg_boxR % 16 / 8 != 0) YsideRb++;\r
+       \r
+    DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
+       DotsHeight(&dlyR, &dryR);\r
+       \r
+       if(flg_boxR % 512 / 256 != 0 && flg_boxR % 1024 / 512 == 0){\r
+               pryR = pngWidth * 0.9 * 0.8 / (dryR - dlyR);\r
+               pyR = kBaseline - pngWidth * 0.9 + 6 * kWidth - dlyR * pryR;\r
+       }\r
+       else{\r
+               pryR = ((double)pngWidth * 0.9 - (YsideRa + YsideRb) * 2 * kWidth) / (dryR - dlyR);\r
+               pyR = kBaseline - dryR * pryR;\r
+               if(flg_boxR % 16 / 8 != 0) pyR = pyR - 2 * kWidth;\r
+       }\r
+       \r
+       //calculate ratio\r
+       rL = yokoL;\r
+       rR = yokoR;\r
+       \r
+       if(flg_boxL % 2 / 1 != 0) rL = rL * 0.7;\r
+       if(flg_boxL % 4 / 2 != 0) rL = rL * 0.7;\r
+       if(flg_boxR % 2 / 1 != 0) rR = rR * 0.7;\r
+       if(flg_boxR % 4 / 2 != 0) rR = rR * 0.7;\r
+       \r
+       rL = pow(rL, 0.6);\r
+       rR = pow(rR, 0.6);\r
+       \r
+       rR = rR * 1.05;\r
+       \r
+       rTemp = rL + rR;\r
+       rL = rL / rTemp;\r
+       rR = rR / rTemp;\r
+       \r
+//    if(r < 0.3) r = 0.3;\r
+//    else if(r > 0.7) r = 0.7;\r
+       \r
+    prL = rL;\r
+    prR = rR;\r
+       \r
+       //calculate width of each parts #1\r
+       Xside = 0;\r
+    if(flg_boxL % 2 / 1 != 0) Xside++;\r
+    if(flg_boxR % 4 / 2 != 0) Xside++;\r
+       \r
+//    DrawBox();\r
+//    drawGlyph(parts1, 1);\r
+//    DotsWidth(&lxL, &rxL);\r
+//    DrawBox();\r
+//    drawGlyph(parts3, 1);\r
+//    DotsWidth(&lxR, &rxR);\r
+    PartsWidth(parts1, &lxL, &rxL);\r
+    PartsWidth(parts3, &lxR, &rxR);\r
+    g = 0;\r
+       \r
+       //calculate width of each parts #2\r
+//    pxL = kWidth * 2 + (pngWidth - kWidth * 2 * 2) * prL * 0.5 - (lxL + rxL) / 2 * prL;\r
+//    pxR = kWidth * 2 + (pngWidth - kWidth * 2 * 2) * prL + kWidth * 2 * 2 + (pngWidth - kWidth * 2 * 2) * prR * 0.5 - (lxR + rxR) / 2 * prR;\r
+    pxL = pngWidth * prL * 0.5 - (lxL + rxL) / 2 * prL;\r
+    pxR = pngWidth * prL + kWidth * 4 + pngWidth * prR * 0.5 - (lxR + rxR) / 2 * prR;\r
+       \r
+    DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
+       \r
+       //count dots for check crossing over\r
+       DotsHeight(&chk_y1, &chk_y2);\r
+       k = 0;\r
+       for(i = 0; i < pngWidth * 1.1; i++){\r
+               for(j = chk_y1; j <= chk_y2; j++){\r
+                       if(kageCanvas[j][i] == 0) k++;\r
+               }\r
+       }\r
+       l = k;\r
+       \r
+       //get close both parts\r
+       h = pxR;\r
+       while(k - l < kMixdot && g < kWidth * (kKasane + 4)){\r
+               g = g + 2;\r
+               f = pxR - g;\r
+        DoDrawMixFont(parts1, pxL, prL, parts3, f, prR, pyL, pryL, pyR, pryR);\r
+               \r
+        l = 0;\r
+        for(i = 0; i < pngWidth * 1.1; i++){\r
+            for(j = chk_y1; j <= chk_y2; j++){\r
+                if(kageCanvas[j][i] == 0) l++;\r
+            }\r
+        }\r
+    }\r
+    pxR = f;\r
+    if(flg_boxR % 256 / 128 != 0) pxR = pxR + kWidth * 12;\r
+    if(flg_boxR % 64 / 32 != 0) pxR = pxR + kWidth * 8;\r
+    else if(k - l > pngWidth * 0.4) pxR = pxR + kWidth * 5;\r
+    else pxR = pxR + kWidth * 3;\r
+       \r
+       //set results\r
+       result[0] = pxL;\r
+       result[1] = pyL;\r
+       result[2] = pxL + pngWidth * prL;\r
+       result[3] = pyL + pngWidth * pryL;\r
+       result[8] = pxR;\r
+       result[9] = pyR;\r
+       result[10] = pxR + pngWidth * prR;\r
+       result[11] = pyR + pngWidth * pryR;\r
+       \r
+       kShotai = tempShotai;\r
+}\r
+\r
+void combineYoko3(const GString *parts1, const GString *parts2, const GString *parts3, int *result){\r
+       //not yet\r
+}\r
+\r
+void combineTate2(const GString *parts1, const GString *parts3, int *result){\r
+    int f, g, h, i, j, k, l;\r
+    int flg_boxL, flg_boxR;\r
+    int pxL, pxR, pyL, pyR;\r
+    double prL, prR, pryL, pryR, rL, rR, rTemp;\r
+    int lxL, rxL, lxR, rxR;\r
+    int lyL, ryL, lyR, ryR;\r
+    int dlxL, drxL, dlxR, drxR;\r
+    int chk_x1, chk_x2;\r
+    int mitsuL, mitsuR;\r
+    double yokoL, tateL, yokoR, tateR;\r
+       int *buf, strokes;\r
+       int tempShotai;\r
+       \r
+       //initialize\r
+    pxL = 0;\r
+    pyL = 0;\r
+    prL = 1.0;\r
+    pryL = 1.0;\r
+    pxR = 0;\r
+    pyR = 0;\r
+    prR = 1.0;\r
+    pryR = 1.0;\r
+       \r
+       tempShotai = kShotai;\r
+       kShotai = kGothic;\r
+       \r
+    CalcOptions(parts1, &mitsuL, &flg_boxL, &yokoL, &tateL);\r
+    CalcOptions(parts3, &mitsuR, &flg_boxR, &yokoR, &tateR);\r
+       \r
+       //calculate ratio\r
+       rL = tateL;\r
+       rR = tateR;\r
+       \r
+       if(flg_boxL % 8 / 4 != 0) rL = rL * 0.7;\r
+       if(flg_boxL % 16 / 8 != 0) rL = rL * 0.7;\r
+       if(flg_boxR % 8 / 4 != 0) rR = rR * 0.7;\r
+       if(flg_boxR % 16 / 8 != 0) rR = rR * 0.7;\r
+       \r
+       rL = pow(rL, 0.8);\r
+       rR = pow(rR, 0.8);\r
+       \r
+       rR = rR * 1.1;\r
+       \r
+       rTemp = rL + rR;\r
+       rL = rL / rTemp;\r
+       rR = rR / rTemp;\r
+       \r
+//    if(r < 0.3) r = 0.3;\r
+//    else if(r > 0.7) r = 0.7;\r
+       \r
+    pryL = rL;\r
+    pryR = rR;\r
+       \r
+       //calucurate size of X-axis\r
+    PartsWidth(parts1, &lxL, &rxL);\r
+    PartsWidth(parts3, &lxR, &rxR);\r
+    PartsHeight(parts1, &lyL, &ryL);\r
+    PartsHeight(parts3, &lyR, &ryR);\r
+       \r
+       //left parts\r
+    if(flg_boxL % 64 / 32 != 0){\r
+               buf = convertStroke(parts1->str, buf, &strokes);\r
+               for(i = 0; i < strokes; i++){\r
+                       if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4]; // center line\r
+        }\r
+        k = max(j - lxL, rxL - j);// k : distance from center line\r
+        prL = (kSize * 0.9 * 0.5) / k;\r
+        if(k == j - lxL) pxL = 0;\r
+        else pxL = kSize * 0.5 - j * prL;\r
+    }\r
+    else if(flg_boxL % 2 / 1 != 0 && flg_boxL % 4 / 2 != 0 && flg_boxL % 32 / 16 == 0){\r
+        prL = min(1.0, (double)yokoL * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
+        DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
+        DotsWidth(&dlxL, &drxL);\r
+        pxL = (kSize / 2 - (dlxL + drxL) / 2);\r
+    }\r
+    else if(flg_boxL % 128 / 64 != 0){\r
+        prL = 0.77;\r
+        DoDrawParts(parts1, pxL, prL, pyL, pryL);\r
+        DotsWidth(&dlxL, &drxL);\r
+        pxL = (kSize / 2 - (dlxL + drxL) / 2);\r
+    }\r
+    else if(flg_boxL % 2 / 1 != 0 && flg_boxL % 32 / 16 == 0){\r
+        prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
+               pxL = kWidth * 4;\r
+    }\r
+    else if(flg_boxL % 4 / 2 != 0 && flg_boxL % 32 / 16 == 0){\r
+        prL = (kSize * 0.9 - kWidth * 4) / (rxL - lxL);\r
+        pxL = (kSize*0.05+kWidth*2) - lxL * prL;\r
+    }\r
+       \r
+       //right parts\r
+    if(flg_boxR % 64 / 32 != 0){\r
+               buf = convertStroke(parts3->str, buf, &strokes);\r
+               for(i = 0; i < strokes; i++){\r
+                       if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4]; // center line\r
+        }\r
+        k = max(j - lxR, rxR - j);// k : distance from center line\r
+        prR = (kSize * 0.9 * 0.5) / k;\r
+        if(k == j - lxR) pxR = 0;\r
+               else pxR = kSize * 0.5 - j * prR;\r
+       }\r
+       else if(flg_boxR % 2 / 1 != 0 && flg_boxR % 4 / 2 != 0 && flg_boxR % 32 / 16 == 0){\r
+               prR = min(1.0, (double)yokoR * 0.1 + 0.5) - ((kWidth * 6) / (kSize * 0.9));\r
+               DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
+               DotsWidth(&dlxR, &drxR);\r
+               pxR = (kSize / 2 - (dlxR + drxR) / 2);\r
+       }\r
+       else if(flg_boxR % 128 / 64 != 0){\r
+               prR = 0.77;\r
+               DoDrawParts(parts3, pxR, prR, pyR, pryR);\r
+               DotsWidth(&dlxR, &drxR);\r
+               pxR = (kSize / 2 - (dlxR + drxR) / 2);\r
+       }\r
+       else if(flg_boxR % 2 / 1 != 0 && flg_boxR % 32 / 16 == 0){\r
+               prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
+//            pxR = width * 4;\r
+               pxR = (kSize*0.05+kWidth*3) - lxR * prR;\r
+       }\r
+       else if(flg_boxR % 4 / 2 != 0 && flg_boxR % 32 / 16 == 0){\r
+               prR = (kSize * 0.9 - kWidth * 4) / (rxR - lxR);\r
+//            pxR = (size*0.05+width*2) - lxR * prR;\r
+               pxR = (kSize*0.05+kWidth*1) - lxR * prR;\r
+       }\r
+       \r
+       g = 0;\r
+       \r
+       //calculate width of each parts\r
+       pyL = kWidth * 1.5 + (kSize - kWidth * 1.5 * 4) * pryL * 0.5 - (lyL + ryL) / 2 * pryL;\r
+       pyR = kWidth * 1.5 + (kSize - kWidth * 1.5 * 4) * pryL + kWidth * 1.5 * 2 + (kSize - kWidth * 1.5 * 4) * pryR * 0.5 - (lyR + ryR) / 2 * pryR;\r
+       \r
+       DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, pyR, pryR);\r
+       \r
+       //count dots for check crossing over\r
+       DotsWidth(&chk_x1, &chk_x2);\r
+       k = 0;\r
+       for(i = 0; i < pngWidth * 1.1; i++){\r
+               for(j = chk_x1; j <= chk_x2; j++){\r
+                       if(kageCanvas[i][j] == 0) k++;\r
+               }\r
+       }\r
+       l = k;\r
+       \r
+       //get close both parts\r
+       h = pyR;\r
+       while(k - l < kMixdot && g < kWidth * (kKasane + 4)){\r
+               g = g + 2;\r
+               f = pyR - g;\r
+        DoDrawMixFont(parts1, pxL, prL, parts3, pxR, prR, pyL, pryL, f, pryR);\r
+               \r
+        l = 0;\r
+        for(i = 0; i < pngWidth * 1.1; i++){\r
+            for(j = chk_x1; j <= chk_x2; j++){\r
+                if(kageCanvas[i][j] == 0) l++;\r
+            }\r
+        }\r
+    }\r
+    pyR = f;\r
+    if(k - l > pngWidth * 0.4) pyR = pyR + kWidth * 5;\r
+    else pyR = pyR + kWidth * 3;\r
+       \r
+       //set results\r
+       result[0] = pxL;\r
+       result[1] = pyL;\r
+       result[2] = pxL + pngWidth * prL;\r
+       result[3] = pyL + pngWidth * pryL;\r
+       result[8] = pxR;\r
+       result[9] = pyR;\r
+       result[10] = pxR + pngWidth * prR;\r
+       result[11] = pyR + pngWidth * pryR;\r
+       \r
+       kShotai = tempShotai;\r
+}\r
+\r
+void combineTate3(const GString *parts1, const GString *parts2, const GString *parts3, int *result){\r
+  //not yet\r
+}\r
+\r
+void combineHame2(const GString *parts1, const GString *parts3, int *result){\r
+  int i;\r
+  int *buf, strokes;\r
+\r
+  //set results\r
+  result[0] = 0;\r
+  result[1] = 0;\r
+  result[2] = 200;\r
+  result[3] = 200;\r
+  buf = convertStroke(parts1->str, buf, &strokes);\r
+  for(i = 0; i < strokes; i++){\r
+    if(buf[i * 11 + 0] == 9){\r
+\r
+      result[8] = buf[i * 11 + 3];\r
+      result[9] = buf[i * 11 + 4];\r
+      result[10] = buf[i * 11 + 5];\r
+      result[11] = buf[i * 11 + 6];\r
+    }\r
+  }\r
+       //not yet\r
+}\r
diff --git a/kagecgi/kagedb.c b/kagecgi/kagedb.c
new file mode 100755 (executable)
index 0000000..21cd2ba
--- /dev/null
@@ -0,0 +1,123 @@
+//kagedb.c\r
+//\r
+\r
+#include <db1/db.h>\r
+//#include <db2/db_185.h>\r
+\r
+#include <sys/fcntl.h>\r
+#include <glib.h>\r
+#include "kagecgi.h"\r
+#include "kage.h"\r
+\r
+int initDB(){\r
+       kDatabase = dbopen(databaseFileName, O_RDWR|O_CREAT, 0666, DB_HASH, NULL);\r
+       return 0;\r
+}\r
+\r
+int closeDB(){\r
+       kDatabase->close(kDatabase);\r
+       return 0;\r
+}\r
+\r
+void searchPartsData(const GString *in, GString *out){\r
+       DBT dbkey, dbdata;\r
+       char *start, *end;\r
+       GString *temp, *temp2;\r
+       \r
+       //cut off the end '-0000' if 'in' end with it\r
+       temp = g_string_new(in->str);\r
+//     if(strncmp(temp->str + temp->len - 5, "-0000", 5) == 0) g_string_set_size(temp, temp->len - 5);\r
+       if((temp->str)[0] == 'u'){\r
+               if(strncmp(temp->str + temp->len - 4, "-j00", 4) == 0) g_string_set_size(temp, temp->len - 4);\r
+               else if(strncmp(temp->str + temp->len - 4, "-g00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-t00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-k00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-v00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-u00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+       }\r
+       \r
+       memset(&dbkey,0,sizeof(DBT));\r
+       memset(&dbdata,0,sizeof(DBT));\r
+       dbkey.data = temp->str;\r
+       dbkey.size = temp->len;\r
+       g_string_set_size(out, 0);\r
+       temp2 = g_string_new("");\r
+       kDatabase->get(kDatabase, &dbkey, &dbdata, 0);\r
+       if(dbdata.size != 0){\r
+               //first:search selected shotai\r
+               if(kShotai == kMincho) start = strstr(dbdata.data, ",mincho,");\r
+               else start = strstr(dbdata.data, ",gothic,");\r
+               if(start != NULL){\r
+                       start = strchr((start+8), ',');\r
+                       if(start != NULL){\r
+                               start = strchr((start+1), ',');\r
+                               if(start != NULL){\r
+                                       end = strchr((start+1), ',');\r
+                                       if(end != NULL){\r
+                                               g_string_append_len(temp2, (start+1), end - start - 2 + 1);\r
+                                               convert99(temp2, out);\r
+                                               return;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               //second:search another shotai\r
+               if(kShotai == kMincho) start = strstr(dbdata.data, ",gothic,");\r
+               else start = strstr(dbdata.data, ",mincho,");\r
+               if(start != NULL){\r
+                       start = strchr((start+8), ',');\r
+                       if(start != NULL){\r
+                               start = strchr((start+1), ',');\r
+                               if(start != NULL){\r
+                                       end = strchr((start+1), ',');\r
+                                       if(end != NULL){\r
+                                               g_string_append_len(temp2, (start+1), end - start - 2 + 1);\r
+                                               convert99(temp2, out);\r
+                                               return;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+void searchAliasData(const GString *in, GString *out){\r
+       DBT dbkey, dbdata;\r
+       char *start, *end;\r
+       GString *temp;\r
+       \r
+       //cut off the end '-0000' if 'in' end with it\r
+       temp = g_string_new(in->str);\r
+//     if(strncmp(temp->str + temp->len - 5, "-0000", 5) == 0) g_string_set_size(temp, temp->len - 5);\r
+       if((temp->str)[0] == 'u'){\r
+               if(strncmp(temp->str + temp->len - 4, "-j00", 4) == 0) g_string_set_size(temp, temp->len - 4);\r
+               else if(strncmp(temp->str + temp->len - 4, "-g00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-t00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-k00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-v00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+               else if(strncmp(temp->str + temp->len - 4, "-u00", 4) == 0) g_string_set_size(temp, temp->len - 2);\r
+       }\r
+       \r
+       memset(&dbkey,0,sizeof(DBT));\r
+       memset(&dbdata,0,sizeof(DBT));\r
+       dbkey.data = temp->str;\r
+       dbkey.size = temp->len;\r
+       g_string_set_size(out, 0);\r
+       kDatabase->get(kDatabase, &dbkey, &dbdata, 0);\r
+       if(dbdata.size != 0){\r
+               start = strstr(dbdata.data, ",linkto,");\r
+               if(start != NULL){\r
+                       start = strchr((start+8), ',');\r
+                       if(start != NULL){\r
+                               start = strchr((start+1), ',');\r
+                               if(start != NULL){\r
+                                       end = strchr((start+1), ',');\r
+                                       if(end != NULL){\r
+                                               g_string_append_len(out, (start+1), end - start - 2 + 1);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
diff --git a/kagecgi/kagedf.c b/kagecgi/kagedf.c
new file mode 100755 (executable)
index 0000000..079c432
--- /dev/null
@@ -0,0 +1,356 @@
+//kagedf.c\r
+//\r
+#include "kage.h"\r
+\r
+void dfDrawFont(int a1, int a2, int a3,\r
+       int x1, int y1,\r
+       int x2, int y2,\r
+       int x3, int y3,\r
+       int x4, int y4){\r
+       int tx1, tx2, tx3, tx4, ty1, ty2, ty3, ty4, v;\r
+       double rad;\r
+       \r
+       if(kShotai == kMincho){\r
+               switch(a1 % 100){\r
+               case 0:\r
+                       break;\r
+       case 1:\r
+               if(a3 == 4){\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, x2 - kMage, y2, 1, 14);\r
+               }\r
+               else{\r
+                               cdDrawLine(x1, y1, x2, y2, a2, a3);\r
+               }\r
+               break;\r
+       case 2:\r
+       case 12:\r
+               if(a3 == 4){\r
+                               if(x2 == x3){\r
+                                       tx1 = x3;\r
+                                       ty1 = y3 - kMage;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       tx1 = x3 - kMage;\r
+                                       ty1 = y3;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x3 - kMage * cos(rad) * v;\r
+                                       ty1 = y3 - kMage * sin(rad) * v;\r
+                               }\r
+                               cdDrawCurve(x1, y1, x2, y2, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x3, y3, x3 - kMage, y3, 1, 14);\r
+               }\r
+               else if(a3 == 5){\r
+                               cdDrawCurve(x1, y1, x2, y2, x3, y3, a2, 15);\r
+               }\r
+               else{\r
+                               cdDrawCurve(x1, y1, x2, y2, x3, y3, a2, a3);\r
+               }\r
+               break;\r
+               case 3:\r
+               if(a3 == 5){\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               if(x2 == x3){\r
+                                       if(y2 < y3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2;\r
+                                       ty2 = y2 + kMage * v;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       if(x2 < x3){ v = 1; } else { v = -1; }\r
+                                       tx2 = x2 + kMage * v;\r
+                                       ty2 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * cos(rad) * v;\r
+                                       ty2 = y2 + kMage * sin(rad) * v;\r
+                               }\r
+                               tx3 = x3 - kMage;\r
+                               ty3 = y3;\r
+                               tx4 = x3 + kMage * 0.5;\r
+                               ty4 = y3 - kMage * 2;\r
+                               \r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, tx2, ty2, 1, 1);\r
+                               cdDrawLine(tx2, ty2, tx3, ty3, 6, 5); // bolder by force\r
+                       }\r
+                       else{\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else { v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               if(x2 == x3){\r
+                                       if(y2 < y3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2;\r
+                                       ty2 = y2 + kMage * v;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * v;\r
+                                       ty2 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * cos(rad) * v;\r
+                                       ty2 = y2 + kMage * sin(rad) * v;\r
+                               }\r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, tx2, ty2, 1, 1);\r
+                               cdDrawLine(tx2, ty2, x3, y3, 6, a3); // bolder by force\r
+                       }\r
+               break;\r
+           case 6:\r
+               if(a3 == 5){\r
+                               tx1 = x4 - kMage;\r
+                               ty1 = y4;\r
+                               tx2 = x4 + kMage * 0.5;\r
+                               ty2 = y4 - kMage * 2;\r
+                               if(a2 == 7 || a3 == 7){\r
+                                       cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 17);\r
+                                       cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, x4, y4, 17, 15);\r
+                               }\r
+                               else{\r
+                                       cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 8);\r
+                                       cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, x4, y4, 1, 15);\r
+                               }\r
+                       }\r
+                       else{\r
+                               if(a2 == 7 || a3 == 7){\r
+                                       cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 17);\r
+                                       cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, x4, y4, 17, a3);\r
+                               }\r
+                               else{\r
+                                       cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 8);\r
+                                       cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, x4, y4, 1, a3);\r
+                               }\r
+                       }\r
+                       break;\r
+       case 7:\r
+         cdDrawLine(x1, y1, x2, y2, a2, 1);\r
+         cdDrawCurve(x2, y2, x3, y3, x4, y4, 1, 7);\r
+         break;\r
+       case 9: // may not be exist\r
+         break;\r
+       default:\r
+         break;\r
+       }\r
+       }\r
+    \r
+    else{ // gothic\r
+       switch(a1 % 100){\r
+       case 0:\r
+               break;\r
+       case 1:\r
+               if(a3 == 4){\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, x2 - kMage * 2, y2 - kMage * 0.5, 1, 0);\r
+               }\r
+               else{\r
+                               cdDrawLine(x1, y1, x2, y2, a2, a3);\r
+               }\r
+                       break;\r
+       case 2:\r
+       case 12:\r
+               if(a3 == 4){\r
+                               if(x2 == x3){\r
+                                       tx1 = x3;\r
+                                       ty1 = y3 - kMage;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       tx1 = x3 - kMage;\r
+                                       ty1 = y3;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x3 - kMage * cos(rad) * v;\r
+                                       ty1 = y3 - kMage * sin(rad) * v;\r
+                               }\r
+                               cdDrawCurve(x1, y1, x2, y2, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x3, y3, x3 - kMage * 2, y3 - kMage * 0.5, 1, 0);\r
+               }\r
+               else if(a3 == 5){\r
+                               tx1 = x3 + kMage;\r
+                               ty1 = y3;\r
+                               tx2 = tx1 + kMage * 0.5;\r
+                               ty2 = y3 - kMage * 2;\r
+                               cdDrawCurve(x1, y1, x2, y2, x3, y3, a2, 1);\r
+                               cdDrawCurve(x3, y3, tx1, ty1, tx2, ty2, 1, 0);\r
+               }\r
+               else{\r
+                               cdDrawCurve(x1, y1, x2, y2, x3, y3, a2, a3);\r
+               }\r
+               break;\r
+       case 3:\r
+               if(a3 == 5){\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               if(x2 == x3){\r
+                                       if(y2 < y3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2;\r
+                                       ty2 = y2 + kMage * v;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * v;\r
+                                       ty2 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * cos(rad) * v;\r
+                                       ty2 = y2 + kMage * sin(rad) * v;\r
+                               }\r
+                               tx3 = x3 - kMage;\r
+                               ty3 = y3;\r
+                               tx4 = x3 + kMage * 0.5;\r
+                               ty4 = y3 - kMage * 2;\r
+                               \r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, tx2, ty2, 1, 1);\r
+                               cdDrawLine(tx2, ty2, tx3, ty3, 1, 1);\r
+                               cdDrawCurve(tx3, ty3, x3, y3, tx4, ty4, 1, 0);\r
+               }\r
+               else{\r
+                               if(x1 == x2){\r
+                                       if(y1 < y2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2;\r
+                                       ty1 = y2 - kMage * v;\r
+                               }\r
+                               else if(y1 == y2){\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * v;\r
+                                       ty1 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y2 - y1) / (double)(x2 - x1));\r
+                                       if(x1 < x2){ v = 1; } else{ v = -1; }\r
+                                       tx1 = x2 - kMage * cos(rad) * v;\r
+                                       ty1 = y2 - kMage * sin(rad) * v;\r
+                               }\r
+                               if(x2 == x3){\r
+                                       if(y2 < y3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2;\r
+                                       ty2 = y2 + kMage * v;\r
+                               }\r
+                               else if(y2 == y3){\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * v;\r
+                                       ty2 = y2;\r
+                               }\r
+                               else{\r
+                                       rad = atan((double)(y3 - y2) / (double)(x3 - x2));\r
+                                       if(x2 < x3){ v = 1; } else{ v = -1; }\r
+                                       tx2 = x2 + kMage * cos(rad) * v;\r
+                                       ty2 = y2 + kMage * sin(rad) * v;\r
+                               }\r
+                               \r
+                               cdDrawLine(x1, y1, tx1, ty1, a2, 1);\r
+                               cdDrawCurve(tx1, ty1, x2, y2, tx2, ty2, 1, 1);\r
+                               cdDrawLine(tx2, ty2, x3, y3, 1, a3);\r
+               }\r
+               break;\r
+       case 6:\r
+               if(a3 == 5){\r
+                               tx1 = x4 - kMage;\r
+                               ty1 = y4;\r
+                               tx2 = x4 + kMage * 0.5;\r
+                               ty2 = y4 - kMage * 2;\r
+                               cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 1);\r
+                               cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, tx1, ty1, 1, 1);\r
+                               cdDrawCurve(tx1, ty1, x4, y4, tx2, ty2, 1, 0);\r
+               }\r
+               else{\r
+                               cdDrawCurve(x1, y1, x2, y2, (x2 + x3) / 2, (y2 + y3) / 2, a2, 1);\r
+                               cdDrawCurve((x2 + x3) / 2, (y2 + y3) / 2, x3, y3, x4, y4, 1, a3);\r
+               }\r
+               break;\r
+       case 7:\r
+               cdDrawLine(x1, y1, x2, y2, a2, 1);\r
+               cdDrawCurve(x2, y2, x3, y3, x4, y4, 1, a3);\r
+               break;\r
+       case 9: // may not be exist\r
+               break;\r
+       default:\r
+                       break;\r
+               }\r
+       }\r
+}\r
diff --git a/kagecgi/kageeg.c b/kagecgi/kageeg.c
new file mode 100755 (executable)
index 0000000..7fb3613
--- /dev/null
@@ -0,0 +1,306 @@
+//kageeg.c\r
+//\r
+\r
+#include <db1/db.h>\r
+//#include <db2/db_185.h>\r
+\r
+#include <glib.h>\r
+#include <stdlib.h>\r
+#include "kagecgi.h"\r
+#include "kage.h"\r
+\r
+void generateGlyphByIDS(const GString *in, GString *out, int flag){\r
+       GString *tmp1, *tmp2, *tmp3, *tmp4;\r
+       \r
+       //pass this method if 'in' is not UCS parts\r
+       if((in->str)[0] != 'u'){\r
+               generateGlyph(in, out);\r
+               return;\r
+       }\r
+       //pass this method if 'in' is place-variant-flag defined\r
+       if(in->len < 5 && 7 < in->len){\r
+               generateGlyph(in, out);\r
+               return;\r
+       }\r
+       \r
+       tmp1 = g_string_new(in->str);\r
+       tmp2 = g_string_new(in->str);\r
+//     tmp3 = g_string_new(in->str);\r
+//     tmp4 = g_string_new(in->str);\r
+       \r
+       //append design flag\r
+//     if(kDesign == 10) g_string_append(tmp1, "-10");\r
+//     else if(kDesign == 11) g_string_append(tmp1, "-11");\r
+//     else if(kDesign == 20) g_string_append(tmp1, "-20");\r
+//     else if(kDesign == 30) g_string_append(tmp1, "-30");\r
+//     else if(kDesign == 40) g_string_append(tmp1, "-40");\r
+//     else g_string_append(tmp1, "-00");\r
+//     if(kDesign == 10) g_string_append(tmp2, "-10");\r
+//     else if(kDesign == 11) g_string_append(tmp2, "-11");\r
+//     else if(kDesign == 20) g_string_append(tmp2, "-20");\r
+//     else if(kDesign == 30) g_string_append(tmp2, "-30");\r
+//     else if(kDesign == 40) g_string_append(tmp2, "-40");\r
+//     else g_string_append(tmp2, "-00");\r
+//     g_string_append(tmp3, "-00");\r
+//     g_string_append(tmp4, "-00");\r
+       \r
+       //append place flag\r
+       if(1 <= flag && flag <= 7){\r
+               if(tmp1->len != 7) g_string_append(tmp1, "-");\r
+               if(flag == 1) g_string_append(tmp1, "01");\r
+               else if(flag == 2) g_string_append(tmp1, "02");\r
+               else if(flag == 3) g_string_append(tmp1, "03");\r
+               else if(flag == 4) g_string_append(tmp1, "04");\r
+               else if(flag == 5) g_string_append(tmp1, "05");\r
+               else if(flag == 6) g_string_append(tmp1, "06");\r
+       }\r
+\r
+//     g_string_append(tmp2, "00");\r
+//     if(flag == 1) g_string_append(tmp3, "01");\r
+//     else if(flag == 2) g_string_append(tmp3, "02");\r
+//     else if(flag == 3) g_string_append(tmp3, "03");\r
+//     else if(flag == 4) g_string_append(tmp3, "04");\r
+//     else if(flag == 5) g_string_append(tmp3, "05");\r
+//     else if(flag == 6) g_string_append(tmp3, "06");\r
+//     else g_string_append(tmp3, "00");\r
+//     g_string_append(tmp4, "00");\r
+       \r
+       generateGlyph(tmp1, out);\r
+       if(out->len != 0) return;\r
+       generateGlyph(tmp2, out);\r
+       if(out->len != 0) return;\r
+//     generateGlyph(tmp3, out);\r
+//     if(out->len != 0) return;\r
+//     generateGlyph(tmp4, out);\r
+       return;\r
+}\r
+\r
+void generateGlyph(const GString *in, GString *out){\r
+       GString *tmp, *in2;\r
+       tmp = g_string_new("");\r
+       g_string_set_size(out, 0);\r
+       \r
+//     in2 = g_string_new(in->str);\r
+       \r
+       //1st search\r
+//     if(*(in2->str) == 'u' && (in2->len == 4 || in2->len == 5)){\r
+//             //append design flag\r
+//             if(kDesign == 10) g_string_append(in2, "-1000");\r
+//             else if(kDesign == 11) g_string_append(in2, "-1100");\r
+//             else if(kDesign == 20) g_string_append(in2, "-2000");\r
+//             else if(kDesign == 30) g_string_append(in2, "-3000");\r
+//             else if(kDesign == 40) g_string_append(in2, "-4000");\r
+//             else g_string_append(in2, "-0000");\r
+               \r
+               //search from parts(1st)\r
+//             searchPartsData(in2, tmp);\r
+//             if(tmp->len != 0){\r
+//                     g_string_assign(out, tmp->str);\r
+//                     return;\r
+//             }\r
+               \r
+               //search from alias(1st)\r
+//             searchAliasData(in2, tmp);\r
+//             if(tmp->len != 0){\r
+//                     generateGlyph(tmp, out);\r
+//                     if(out->len == 0) return;\r
+//                     //save to cache ... not yet\r
+//                     return;\r
+//             }\r
+//     }\r
+       \r
+       //2nd search\r
+       //search from parts(2nd)\r
+       searchPartsData(in, tmp);\r
+       if(tmp->len != 0){\r
+               g_string_assign(out, tmp->str);\r
+               return;\r
+       }\r
+       \r
+       //search from alias(2nd)\r
+       searchAliasData(in, tmp);\r
+       if(tmp->len != 0){\r
+               generateGlyph(tmp, out);\r
+               if(out->len == 0) return;\r
+               //save to cache ... not yet\r
+               return;\r
+       }\r
+       \r
+       //check if its IDS\r
+       if(isIDS(in)){\r
+               doCombine(in, out);\r
+               if(out->len == 0) return;\r
+               //save to cache ... not yet\r
+               return;\r
+       }\r
+}\r
+\r
+void doCombine(const GString *in, GString *out){\r
+       GString *partIDS1, *partIDS2, *partIDS3;\r
+       GString *partStroke1, *partStroke2, *partStroke3;\r
+       int result[12];\r
+       \r
+       partIDS1 = g_string_new("");\r
+       partIDS2 = g_string_new("");\r
+       partIDS3 = g_string_new("");\r
+       partStroke1 = g_string_new("");\r
+       partStroke2 = g_string_new("");\r
+       partStroke3 = g_string_new("");\r
+       \r
+       g_string_set_size(out, 0);\r
+       \r
+       //check first IDC\r
+       if(strncmp(in->str, "u2ff", 4) != 0) return;\r
+       //switch by combine types\r
+       switch((in->str)[4]){\r
+               case '0':\r
+                       divideInto2(in, partIDS1, partIDS3);\r
+                       if(partIDS1->len == 0) return;\r
+                       //ready each parts\r
+                       generateGlyphByIDS(partIDS1, partStroke1, 1);\r
+                       if(partStroke1->len == 0) return;\r
+                       partStroke1 = CalcSizes(partStroke1, 0);\r
+                       generateGlyphByIDS(partIDS3, partStroke3, 2);\r
+                       if(partStroke3->len == 0) return;\r
+                       partStroke3 = CalcSizes(partStroke3, 0);\r
+                       break;\r
+               case '1':\r
+                       divideInto2(in, partIDS1, partIDS3);\r
+                       if(partIDS1->len == 0) return;\r
+                       //ready each parts\r
+                       generateGlyphByIDS(partIDS1, partStroke1, 3);\r
+                       if(partStroke1->len == 0) return;\r
+                       partStroke1 = CalcSizes(partStroke1, 0);\r
+                       generateGlyphByIDS(partIDS3, partStroke3, 4);\r
+                       if(partStroke3->len == 0) return;\r
+                       partStroke3 = CalcSizes(partStroke3, 0);\r
+                       break;\r
+               case '4':\r
+               case '5':\r
+               case '6':\r
+               case '7':\r
+               case '8':\r
+               case '9':\r
+               case 'a':\r
+//             case 'b':\r
+                       divideInto2(in, partIDS1, partIDS3);\r
+                       if(partIDS1->len == 0) return;\r
+                       //ready each parts\r
+                       generateGlyphByIDS(partIDS1, partStroke1, 5);\r
+                       if(partStroke1->len == 0) return;\r
+                       partStroke1 = CalcSizes(partStroke1, 0);\r
+                       generateGlyphByIDS(partIDS3, partStroke3, 6);\r
+                       if(partStroke3->len == 0) return;\r
+                       partStroke3 = CalcSizes(partStroke3, 0);\r
+                       break;\r
+               case '2':\r
+                       divideInto3(in, partIDS1, partIDS2, partIDS3);\r
+                       if(partIDS1->len == 0) return;\r
+                       //ready each parts\r
+                       generateGlyphByIDS(partIDS1, partStroke1, 1);\r
+                       if(partStroke1->len == 0) return;\r
+                       partStroke1 = CalcSizes(partStroke1, 0);\r
+                       generateGlyphByIDS(partIDS2, partStroke2, 1);\r
+                       if(partStroke2->len == 0) return;\r
+                       partStroke2 = CalcSizes(partStroke2, 0);\r
+                       generateGlyphByIDS(partIDS3, partStroke3, 2);\r
+                       if(partStroke3->len == 0) return;\r
+                       partStroke3 = CalcSizes(partStroke3, 0);\r
+                       break;\r
+               case '3':\r
+                       divideInto3(in, partIDS1, partIDS2, partIDS3);\r
+                       if(partIDS1->len == 0) return;\r
+                       //ready each parts\r
+                       generateGlyphByIDS(partIDS1, partStroke1, 3);\r
+                       if(partStroke1->len == 0) return;\r
+                       partStroke1 = CalcSizes(partStroke1, 0);\r
+                       generateGlyphByIDS(partIDS2, partStroke2, 3);\r
+                       if(partStroke2->len == 0) return;\r
+                       partStroke2 = CalcSizes(partStroke2, 0);\r
+                       generateGlyphByIDS(partIDS3, partStroke3, 4);\r
+                       if(partStroke3->len == 0) return;\r
+                       partStroke3 = CalcSizes(partStroke3, 0);\r
+                       break;\r
+       }\r
+       switch((in->str)[4]){\r
+               case '0':\r
+                       combineYoko2(partStroke1, partStroke3, result);\r
+                       break;\r
+               case '1':\r
+                       combineTate2(partStroke1, partStroke3, result);\r
+                       break;\r
+               case '2':\r
+                       combineYoko3(partStroke1, partStroke2, partStroke3, result);\r
+                       break;\r
+               case '3':\r
+                       combineTate3(partStroke1, partStroke2, partStroke3, result);\r
+                       break;\r
+               case '4':\r
+               case '5':\r
+               case '6':\r
+               case '7':\r
+               case '8':\r
+               case '9':\r
+               case 'a':\r
+//             case 'b':\r
+                       combineHame2(partStroke1, partStroke3, result);\r
+                       break;\r
+       }\r
+       switch((in->str)[4]){\r
+               case '0':\r
+               case '1':\r
+               case '4':\r
+               case '5':\r
+               case '6':\r
+               case '7':\r
+               case '8':\r
+               case '9':\r
+               case 'a':\r
+//             case 'b':\r
+                       addStrokeWithTransform(partStroke1, 1, result, out, 1);\r
+                       addStrokeWithTransform(partStroke3, 3, result, out, 1);\r
+                       break;\r
+               case '2':\r
+               case '3':\r
+                       addStrokeWithTransform(partStroke1, 1, result, out, 1);\r
+                       addStrokeWithTransform(partStroke2, 2, result, out, 1);\r
+                       addStrokeWithTransform(partStroke3, 3, result, out, 1);\r
+                       break;\r
+       }\r
+}\r
+\r
+void drawGlyph(const GString *in, const int mode){\r
+       int i, j;\r
+       int *buf;\r
+       buf = convertStroke(in->str, buf, &j);\r
+       for(i = 0; i < j; i++){\r
+               if(mode == 0){ //normal\r
+                       dfDrawFont(buf[i * 11 + 0],\r
+                        buf[i * 11 + 1],\r
+                        buf[i * 11 + 2],\r
+                        buf[i * 11 + 3],\r
+                        buf[i * 11 + 4],\r
+                        buf[i * 11 + 5],\r
+                        buf[i * 11 + 6],\r
+                        buf[i * 11 + 7],\r
+                        buf[i * 11 + 8],\r
+                        buf[i * 11 + 9],\r
+                        buf[i * 11 + 10]);\r
+               }\r
+               else if(mode == 1){ //without decoration\r
+                       dfDrawFont(buf[i * 11 + 0],\r
+                        0,\r
+                        0,\r
+                        buf[i * 11 + 3],\r
+                        buf[i * 11 + 4],\r
+                        buf[i * 11 + 5],\r
+                        buf[i * 11 + 6],\r
+                        buf[i * 11 + 7],\r
+                        buf[i * 11 + 8],\r
+                        buf[i * 11 + 9],\r
+                        buf[i * 11 + 10]);\r
+               }\r
+       }\r
+       free(buf);\r
+}\r
+\r
diff --git a/kagecgi/kageic.c b/kagecgi/kageic.c
new file mode 100755 (executable)
index 0000000..70281dc
--- /dev/null
@@ -0,0 +1,25 @@
+//kageic.c\r
+//\r
+\r
+#include "kage.h"\r
+#include "kagecgi.h"\r
+\r
+void icPolygon(struct kPoint *poly, int number){\r
+       int i;\r
+       char buf[256];\r
+       \r
+       if(kMode == 0){ //normal\r
+               fillPolygon(poly, number, 0, kageCanvas);\r
+       }\r
+       else{ //output for eps\r
+               sprintf(buf, "%d %d moveto\n", poly[0].X * 5, 1000 - (poly[0].Y * 5) - 200);\r
+               g_string_append(kResultText, buf);\r
+               for(i = 1; i < number; i++){\r
+                       sprintf(buf, " %d %d lineto\n", poly[i].X * 5, 1000 - (poly[i].Y * 5) - 200);\r
+                       g_string_append(kResultText, buf);\r
+               }\r
+               sprintf(buf, " %d %d lineto\n", poly[0].X * 5, 1000 - (poly[0].Y * 5) - 200);\r
+               g_string_append(kResultText, buf);\r
+               g_string_append(kResultText, "closepath\n");\r
+       }\r
+}\r
diff --git a/kagecgi/kagepng.c b/kagecgi/kagepng.c
new file mode 100755 (executable)
index 0000000..7080bb7
--- /dev/null
@@ -0,0 +1,84 @@
+//kagepng.c
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+
+png_bytepp initPng(int width, int height){
+       png_bytepp image;
+       int i, j;
+       
+       image = (png_bytepp)malloc(height * sizeof(png_bytep)); 
+       for(j = 0; j < height; j++) image[j] = (png_bytep)malloc(width * sizeof(png_byte));
+       for(i = 0; i < width; i++){
+               for(j = 0; j < height; j++){
+                       image[j][i] = 0xFF;
+               }
+       }
+       return image;
+}
+
+int closePng(int width, int height, png_bytepp image){
+       int i;
+       for(i = 0; i < height; i++) free(image[i]);
+       free(image);
+       return 0;
+}
+
+int writePng(int width, int height, png_bytepp image, FILE *fp){
+       png_structp pPng;
+       png_infop pInfo;
+       png_text pText[5];
+       time_t gmt;
+       png_time pngTime;
+       
+       pPng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+       if(pPng == NULL){
+               return 1;
+       }
+       pInfo = png_create_info_struct(pPng);
+       if(pInfo == NULL){
+               png_destroy_write_struct(&pPng, (png_infopp)NULL);
+               return 1;
+       }
+       if(setjmp(pPng->jmpbuf)){
+               png_destroy_write_struct(&pPng, &pInfo);
+               return 1;
+       }
+       png_init_io(pPng, fp);
+       png_set_filter(pPng, 0, PNG_ALL_FILTERS);
+       png_set_compression_level(pPng, Z_BEST_COMPRESSION);
+       //png_set_IHDR(pPng, pInfo, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+       png_set_IHDR(pPng, pInfo, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+       png_set_gAMA(pPng, pInfo, 1.0);
+       
+       time(&gmt);
+       png_convert_from_time_t(&pngTime, gmt);
+       png_set_tIME(pPng, pInfo, &pngTime);
+       
+       pText[0].key = "Title";
+       pText[0].text = "Kanji glyph generated by KAGE/cgi";
+       pText[0].compression = PNG_TEXT_COMPRESSION_NONE;
+       pText[1].key = "Author";
+       pText[1].text = "KAGE/cgi version 0.4";
+       pText[1].compression = PNG_TEXT_COMPRESSION_NONE;
+       pText[2].key = "Description";
+       pText[2].text = "see more information at http://fonts.jp/";
+       pText[2].compression = PNG_TEXT_COMPRESSION_NONE;
+       pText[3].key = "Creation Time";
+       pText[3].text = png_convert_to_rfc1123(pPng, &pngTime);
+       pText[3].compression = PNG_TEXT_COMPRESSION_NONE;
+       pText[4].key = "Software";
+       pText[4].text = "KAGE/cgi version 0.4";
+       pText[4].compression = PNG_TEXT_COMPRESSION_NONE;
+       png_set_text(pPng, pInfo, pText, 5);
+       
+       png_write_info(pPng, pInfo);
+       png_write_image(pPng, image);
+       png_write_end(pPng, pInfo);
+       png_destroy_write_struct(&pPng, &pInfo);
+       
+       return 0;
+}
+
diff --git a/kagecgi/kagepoly.c b/kagecgi/kagepoly.c
new file mode 100755 (executable)
index 0000000..358148e
--- /dev/null
@@ -0,0 +1,29 @@
+// kagepoly.c\r
+//\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "kagecgi.h"\r
+#include "kage.h"\r
+\r
+void fillPolygon(struct kPoint *p, int number, int col, unsigned char **image){\r
+       int i, ix, iy;\r
+       Region rgn;\r
+       XRectangle rect;\r
+       \r
+       for(i = 0; i < number; i++){\r
+                       xpoly[i].x = p[i].X;\r
+                       xpoly[i].y = p[i].Y;\r
+       }\r
+       rgn = XPolygonRegion(xpoly, number, EvenOddRule);\r
+       XClipBox(rgn, &rect);\r
+       \r
+       for(ix = rect.x ; ix <= rect.x + rect.width; ix++){\r
+               for(iy = rect.y ; iy <= rect.y + rect.height; iy++){\r
+                       if(XPointInRegion(rgn, ix, iy) && ix >= 0 && iy >= 0 && ix < canvasWidth && iy < canvasHeight){\r
+                               image[iy][ix] = col;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
diff --git a/kagecgi/kagetool.c b/kagecgi/kagetool.c
new file mode 100755 (executable)
index 0000000..5c5a96e
--- /dev/null
@@ -0,0 +1,466 @@
+//kagetool.c\r
+//\r
+\r
+#include "kage.h"\r
+#include "kagecgi.h"\r
+#include <stdlib.h>\r
+#include <png.h>\r
+\r
+void DotsWidth(int *dlx, int *drx){\r
+       int i, j;\r
+       \r
+    *dlx = 0;\r
+    *drx = 0;\r
+    for(i = 0; i <= pngWidth && *dlx == 0; i++){\r
+               for(j = 0; j <= pngHeight; j++){\r
+                       if(kageCanvas[j][i] == 0){\r
+                               *dlx = i;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       for(i = pngWidth; i >= 0 && *drx == 0; i--){\r
+               for(j = 0; j <= pngHeight; j++){\r
+                       if(kageCanvas[j][i] == 0){\r
+                               *drx = i;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+void DotsHeight(int *dly, int *dry){\r
+    int i, j;\r
+       \r
+    *dly = 0;\r
+       *dry = 0;\r
+    for(j = 0; j <= pngHeight && *dly == 0; j++){\r
+        for(i = 0; i <= pngWidth; i++){\r
+            if(kageCanvas[j][i] == 0){\r
+                *dly = j;\r
+                break;\r
+            }\r
+        }\r
+    }\r
+       \r
+    for(j = pngHeight; j >= 0 && *dry == 0; j--){\r
+        for(i = 0; i <= pngWidth; i++){\r
+            if(kageCanvas[j][i] == 0){\r
+                *dry = j;\r
+                break;\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void PartsWidth(const GString *in, int *lx, int *rx){\r
+    int i;\r
+       int *buf, strokes;\r
+       \r
+       *lx = 1000; *rx = 0;\r
+       buf = convertStroke(in->str, buf, &strokes);\r
+       \r
+    for(i = 0; i < strokes; i++){\r
+        if(buf[i * 11 + 0] % 10 == 0) continue;\r
+               \r
+        if(*lx > buf[i * 11 + 3]) *lx = buf[i * 11 + 3];\r
+               if(*rx < buf[i * 11 + 3]) *rx = buf[i * 11 + 3];\r
+        if(*lx > buf[i * 11 + 5]) *lx = buf[i * 11 + 5];\r
+        if(*rx < buf[i * 11 + 5]) *rx = buf[i * 11 + 5];\r
+               \r
+        if(buf[i * 11 + 0] % 10 == 2 || buf[i * 11 + 0] % 10 == 3 || buf[i * 11 + 0] % 10 == 8){\r
+               if(*lx > buf[i * 11 + 7]) *lx = buf[i * 11 + 7];\r
+            if(*rx < buf[i * 11 + 7]) *rx = buf[i * 11 + 7];\r
+               }\r
+        if(buf[i * 11 + 0] % 10 == 4 || buf[i * 11 + 0] % 10 == 6 || buf[i * 11 + 0] % 10 == 7){\r
+               if(*lx > buf[i * 11 + 9]) *lx = buf[i * 11 + 9];\r
+               if(*rx < buf[i * 11 + 9]) *rx = buf[i * 11 + 9];\r
+        }\r
+       }\r
+       free(buf);\r
+}\r
+\r
+void PartsHeight(const GString *in, int *ly, int *ry){\r
+    int i;\r
+       int *buf, strokes;\r
+       \r
+       buf = convertStroke(in->str, buf, &strokes);\r
+       *ly = 1000; *ry = 0;\r
+       \r
+    for(i = 0; i < strokes; i++){\r
+        if(buf[i * 11 + 0] % 10 == 0) continue;\r
+               \r
+        if(*ly > buf[i * 11 + 4]) *ly = buf[i * 11 + 4];\r
+               if(*ry < buf[i * 11 + 4]) *ry = buf[i * 11 + 4];\r
+        if(*ly > buf[i * 11 + 6]) *ly = buf[i * 11 + 6];\r
+        if(*ry < buf[i * 11 + 6]) *ry = buf[i * 11 + 6];\r
+               \r
+        if(buf[i * 11 + 0] % 10 == 2 || buf[i * 11 + 0] % 10 == 3 || buf[i * 11 + 0] % 10 == 8){\r
+               if(*ly > buf[i * 11 + 8]) *ly = buf[i * 11 + 8];\r
+            if(*ry < buf[i * 11 + 8]) *ry = buf[i * 11 + 8];\r
+               }\r
+        if(buf[i * 11 + 0] % 10 == 4 || buf[i * 11 + 0] % 10 == 6 || buf[i * 11 + 0] % 10 == 7){\r
+               if(*ly > buf[i * 11 + 10]) *ly = buf[i * 11 + 10];\r
+               if(*ry < buf[i * 11 + 10]) *ry = buf[i * 11 + 10];\r
+        }\r
+       }\r
+       free(buf);\r
+}\r
+\r
+GString * CalcSizes(const GString *in, int mode){\r
+    int i, j, k, basewidth, one_lineX, one_lineY;\r
+    int dlx1, drx1, dly1, dry1;\r
+       int px1, py1;\r
+    double pr1, pry1;\r
+       \r
+    int mitsuT, flg_boxT, widthT, heightT;\r
+    double tateT, yokoT;\r
+    int cutx, cuty;\r
+       \r
+       int *buf, strokes;\r
+       int tf[12];\r
+       GString *out;\r
+       \r
+       out = g_string_new("");\r
+    basewidth = pngWidth * 0.9;\r
+       \r
+    if(mode == 0){\r
+        //temporary adjustment X-axis\r
+        PartsWidth(in, &dlx1, &drx1);\r
+        if(dlx1 == drx1){\r
+            pr1 = 1.0;\r
+            px1 = pngWidth / 2 - dlx1;\r
+            one_lineX = 1;\r
+        }\r
+        else{\r
+            pr1 = (double)basewidth/(drx1 - dlx1);\r
+            px1 = (pngWidth-basewidth)/2 - (double)(dlx1 * pr1);\r
+            one_lineX = 0;\r
+        }\r
+               \r
+        //temporary adjustment Y-axis\r
+        PartsHeight(in, &dly1, &dry1);\r
+        if(dly1 == dry1){\r
+            pry1 = 1.0;\r
+            py1 = pngWidth / 2 - dly1;\r
+            one_lineY = 1;\r
+        }\r
+               else{\r
+            pry1 = (double)basewidth/(dry1 - dly1);\r
+            py1 = (pngWidth-basewidth)/2 - (double)(dly1 * pry1);\r
+            one_lineY = 0;\r
+        }\r
+    }\r
+       else{\r
+        PartsWidth(in, &dlx1, &drx1);\r
+        PartsHeight(in, &dly1, &dry1);\r
+               \r
+        cutx = 0;\r
+        cuty = 0;\r
+               \r
+        CalcOptions(in, &mitsuT, &flg_boxT, &yokoT, &tateT);\r
+               \r
+        widthT = basewidth;\r
+        heightT = basewidth;\r
+               \r
+        if(flg_boxT % 2 / 1 != 0){\r
+            widthT = widthT - kWidth * 3;\r
+            cutx++;\r
+        }\r
+        if(flg_boxT % 4 / 2 != 0){\r
+            widthT = widthT - kWidth * 3;\r
+            cutx++;\r
+        }\r
+        if(flg_boxT % 8 / 4 != 0){\r
+            heightT = heightT - kWidth * 3;\r
+            cuty++;\r
+        }\r
+        if(flg_boxT % 16 / 8 != 0){\r
+            heightT = heightT - kWidth * 3;\r
+            cuty++;\r
+        }\r
+               \r
+        //especially get small the 'mouse'\r
+        if(mode == 2 && flg_boxT % 16 == 15){\r
+            widthT = widthT - kWidth * (max(0, 16 - (int)yokoT * 4));\r
+            heightT = heightT - kWidth * (max(0, 16 - (int)tateT * 4));\r
+               }\r
+        //'dot' as same as 'mouse'\r
+        if(mode == 2 && tateT == 1 && yokoT == 1){\r
+            widthT = pngWidth * 0.9 * 0.5;\r
+            heightT = pngWidth * 0.9 * 0.5;\r
+        }\r
+               \r
+               if(flg_boxT % 64 / 32 != 0){\r
+                       buf = convertStroke(in->str, buf, &strokes);\r
+                       for(i = 0; i < strokes; i++){\r
+                if(buf[i * 11 + 0] == 0) j = buf[i * 11 + 4];// j : center line\r
+            }\r
+            free(buf);\r
+            k = max(j - dlx1, drx1 - j);// k : distance from center line\r
+            pr1 = (basewidth * 0.5) / k;\r
+                       \r
+            if(k == j - dlx1) px1 = 0;\r
+            else px1 = pngWidth * 0.5 - j * pr1;\r
+        }\r
+        else if(dlx1 == drx1){\r
+            pr1 = 1.0;\r
+            px1 = pngWidth / 2 - dlx1;\r
+        }\r
+        else{\r
+            pr1 = (double)widthT/(drx1 - dlx1);\r
+            px1 = pngWidth / 2 - (double)((dlx1 + drx1) / 2 * pr1);\r
+            if(flg_boxT % 2 / 1 != 0 && flg_boxT % 4 / 2 == 0) px1 = px1 + kWidth * 1.5;\r
+            if(flg_boxT % 2 / 1 == 0 && flg_boxT % 4 / 2 != 0) px1 = px1 - kWidth * 1.5;\r
+        }\r
+               \r
+        if(dly1 == dry1){\r
+            pry1 = 1.0;\r
+            py1 = pngWidth / 2 - dly1;\r
+        }\r
+        else{\r
+            pry1 = (double)heightT/(dry1 - dly1);\r
+            py1 = pngWidth / 2 - (double)((dly1 + dry1) / 2 * pry1);\r
+            if(flg_boxT % 8 / 4 != 0 && flg_boxT % 16 / 8 == 0) py1 = py1 + kWidth * 1.5;\r
+            if(flg_boxT % 8 / 4 == 0 && flg_boxT % 16 / 8 != 0) py1 = py1 - kWidth * 1.5;\r
+        }\r
+       }\r
+       \r
+       //generate result\r
+       tf[0] = px1;\r
+       tf[1] = py1;\r
+       tf[2] = px1 + pr1 * 200;\r
+       tf[3] = py1 + pry1 * 200;\r
+       addStrokeWithTransform(in, 1, tf, out, 0);\r
+       return g_string_new(out->str);\r
+}\r
+\r
+void DrawBox(){\r
+       int i, j;\r
+       \r
+       for(i = 0; i < canvasWidth; i++){\r
+               for(j = 0; j < canvasHeight; j++){\r
+                       kageCanvas[j][i] = 0xFF;\r
+               }\r
+       }\r
+}\r
+\r
+void CalcOptions(const GString *in, int *mitsudo, int *flag, double *yoko, double *tate){\r
+    int i, j, k, l, flg;\r
+    int dlx1, drx1, dly1, dry1;\r
+    int kari, mode;\r
+       int tempShotai;\r
+       int *buf, strokes;\r
+       \r
+    *flag = 0;\r
+       \r
+    DrawBox();\r
+    tempShotai = kShotai;\r
+    kShotai = kGothic;\r
+    drawGlyph(in, 1);\r
+    kShotai = tempShotai;\r
+    DotsWidth(&dlx1, &drx1);\r
+    DotsHeight(&dly1, &dry1);\r
+       \r
+       //check left side\r
+    k = 0;\r
+    l = 0;\r
+    for(i = 0; i < pngWidth; i++){\r
+        flg = 0;\r
+        for(j = 0; j < kWidth; j++){\r
+            if(kageCanvas[i][dlx1 + j] == 0) flg = 1;\r
+        }\r
+        if(flg == 1){\r
+               k++;\r
+        }\r
+        else{\r
+            if(k > l) l = k;\r
+            k = 0;\r
+        }\r
+    }\r
+    if(k > l) l = k;\r
+    \r
+    if(l > pngWidth * 0.9 / 4) *flag = *flag | 1;\r
+       \r
+    //check right side\r
+    k = 0;\r
+    l = 0;\r
+    for(i = 0; i < pngWidth; i++){\r
+        flg = 0;\r
+        for(j = 0; j < kWidth; j++){\r
+            if(kageCanvas[i][drx1 - j] == 0) flg = 1;\r
+        }\r
+        if(flg == 1) k++;\r
+        else{\r
+            if(k > l) l = k;\r
+            k = 0;\r
+        }\r
+    }\r
+    if(k > l) l = k;\r
+       \r
+    if(l > pngWidth * 0.9 / 4) *flag = *flag | 2;\r
+       \r
+    //check upper side\r
+    k = 0;\r
+    l = 0;\r
+    for(i = 0; i < pngWidth; i++){\r
+        flg = 0;\r
+               for(j = 0; j < kWidth; j++){\r
+            if(kageCanvas[dly1 + j][i] == 0) flg = 1;\r
+        }\r
+        if(flg == 1) k++;\r
+        else{\r
+            if(k > l) l = k;\r
+            k = 0;\r
+        }\r
+    }\r
+    if(k > l) l = k;\r
+       \r
+    if(l > pngWidth * 0.9 / 4) *flag = *flag | 4;\r
+       \r
+    //check bottom side\r
+    k = 0;\r
+    l = 0;\r
+    for(i = 0; i < pngWidth; i++){\r
+        flg = 0;\r
+        for(j = 0; j < kWidth; j++){\r
+            if(kageCanvas[dry1 - j][i] == 0) flg = 1;\r
+        }\r
+        if(flg == 1) k++;\r
+        else{\r
+            if(k > l) l = k;\r
+            k = 0;\r
+        }\r
+    }\r
+    if(k > l) l = k;\r
+       \r
+    if(l > pngWidth * 0.9 / 4) *flag = *flag | 8;\r
+       \r
+    //count black dots\r
+    *mitsudo = 0;\r
+    for(i = 0; i < pngHeight; i++){\r
+        for(j = 0; j < pngWidth; j++){\r
+            if(kageCanvas[i][j] == 0) *mitsudo += 1;\r
+        }\r
+    }\r
+       \r
+    //calculate X-axis complexity\r
+    *yoko = 0;\r
+    for(i = dly1; i <= dry1; i++){\r
+        mode = 0;\r
+        kari = 0;\r
+        for(j = dlx1; j <= drx1; j++){\r
+                       if(kageCanvas[i][j] == 0 &&\r
+             kageCanvas[i][j+1] == 0 &&\r
+             kageCanvas[i][j+2] == 0){\r
+                if(mode == 0){\r
+                    mode = 1;\r
+                    kari++;\r
+                }\r
+            }\r
+            else if(mode == 1) mode = 0;\r
+        }\r
+        if(kari > *yoko) *yoko = kari;\r
+    }\r
+       \r
+    //calculate Y-axis complexity\r
+    *tate = 0;\r
+    for(i = dlx1; i <= drx1; i++){\r
+        mode = 0;\r
+        kari = 0;\r
+        for(j = dly1; j <= dry1; j++){\r
+            if(kageCanvas[j][i] == 0 &&\r
+             kageCanvas[j+1][i] == 0 &&\r
+             kageCanvas[j+2][i] == 0){\r
+                if(mode == 0){\r
+                    mode = 1;\r
+                    kari++;\r
+                }\r
+            }\r
+            else if(mode == 1) mode = 0;\r
+        }\r
+        if(kari > *tate) *tate = kari;\r
+    }\r
+       \r
+    //use user defined option if it exists\r
+       buf = convertStroke(in->str, buf, &strokes);\r
+       for(i = 0; i < strokes; i++){\r
+        if(buf[i * 11 + 0] % 10 == 0){\r
+            if(buf[i * 11 + 1] != 0){ *yoko = (double)(buf[i * 11 + 1]) * 0.1;fprintf(stderr,"@@@@@\r\n");}\r
+            if(buf[i * 11 + 2] != 0) *tate = (double)(buf[i * 11 + 2]) * 0.1;\r
+            if(buf[i * 11 + 3] != 0) *flag = *flag + buf[i * 11 + 3] * 16;\r
+        }\r
+    }\r
+    free(buf);\r
+}\r
+\r
+void DoDrawParts(const GString *in, const int lx1, const double rf1, const int ly1, const double rfy1){\r
+    int i;\r
+       int *buf, strokes;\r
+       \r
+    DrawBox();\r
+       buf = convertStroke(in->str, buf, &strokes);\r
+       for(i = 0; i < strokes; i++){\r
+               dfDrawFont(buf[i * 11 + 0],\r
+                buf[i * 11 + 1],\r
+                buf[i * 11 + 2],\r
+                buf[i * 11 + 3] * rf1 + lx1,\r
+                buf[i * 11 + 4] * rfy1 + ly1,\r
+                buf[i * 11 + 5] * rf1 + lx1,\r
+                buf[i * 11 + 6] * rfy1 + ly1,\r
+                buf[i * 11 + 7] * rf1 + lx1,\r
+                buf[i * 11 + 8] * rfy1 + ly1,\r
+                buf[i * 11 + 9] * rf1 + lx1,\r
+                buf[i * 11 + 10] * rfy1 + ly1);\r
+    }\r
+       free(buf);\r
+}\r
+\r
+void DoDrawMixFont(const GString *in1,\r
+ const int lx1,\r
+ const double rf1,\r
+ const GString *in2,\r
+ const int lx2,\r
+ const double rf2,\r
+ const int ly1,\r
+ const double rfy1,\r
+ const int ly2,\r
+ const double rfy2){\r
+    int i;\r
+       int *buf, strokes;\r
+       \r
+       DrawBox();\r
+       buf = convertStroke(in1->str, buf, &strokes);\r
+       for(i = 0; i < strokes; i++){\r
+               dfDrawFont(buf[i * 11 + 0],\r
+                buf[i * 11 + 1],\r
+                buf[i * 11 + 2],\r
+                buf[i * 11 + 3] * rf1 + lx1,\r
+                buf[i * 11 + 4] * rfy1 + ly1,\r
+                buf[i * 11 + 5] * rf1 + lx1,\r
+                buf[i * 11 + 6] * rfy1 + ly1,\r
+                buf[i * 11 + 7] * rf1 + lx1,\r
+                buf[i * 11 + 8] * rfy1 + ly1,\r
+                buf[i * 11 + 9] * rf1 + lx1,\r
+                buf[i * 11 + 10] * rfy1 + ly1);\r
+    }\r
+       free(buf);\r
+       \r
+       buf = convertStroke(in2->str, buf, &strokes);\r
+       for(i = 0; i < strokes; i++){\r
+               dfDrawFont(buf[i * 11 + 0],\r
+                buf[i * 11 + 1],\r
+                buf[i * 11 + 2],\r
+                buf[i * 11 + 3] * rf2 + lx2,\r
+                buf[i * 11 + 4] * rfy2 + ly2,\r
+                buf[i * 11 + 5] * rf2 + lx2,\r
+                buf[i * 11 + 6] * rfy2 + ly2,\r
+                buf[i * 11 + 7] * rf2 + lx2,\r
+                buf[i * 11 + 8] * rfy2 + ly2,\r
+                buf[i * 11 + 9] * rf2 + lx2,\r
+                buf[i * 11 + 10] * rfy2 + ly2);\r
+    }\r
+       free(buf);\r
+}\r
+\r