initial code + examples commit
This commit is contained in:
77
README.md
77
README.md
@@ -1,2 +1,75 @@
|
||||
texdoclet
|
||||
=========
|
||||
TeXDoclet
|
||||
=========
|
||||
|
||||
TeXDoclet is a Java doclet implementation that generates a LaTeX file from you Java code documentation.
|
||||
|
||||
The doclet is based on the doclet originally created by Greg Wonderly of
|
||||
[C2 technologies Inc.](http://www.c2-tech.com>) and its revision by Soeren Caspersen of
|
||||
[XO Software](http://www.xosoftware.dk). The project of Greg Wonderly is still available here:
|
||||
<http://java.net/projects/texdoclet>.
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
mvn clean install
|
||||
|
||||
Run
|
||||
---
|
||||
|
||||
Example :
|
||||
|
||||
javadoc -docletpath target/TeXDoclet.jar \
|
||||
-doclet org.stfm.texdoclet.TeXDoclet \
|
||||
-noindex \
|
||||
-tree \
|
||||
-hyperref \
|
||||
-texinit texdoclet_include/preamble.tex \
|
||||
-imagespath ".." \
|
||||
-output texdoclet_output/TeXDoclet.tex \
|
||||
-title "TeXDoclet Java Documentation" \
|
||||
-author "Greg Wonderly \and S\"oren Caspersen \and Stefan Marx" \
|
||||
-sourcepath src/main/java \
|
||||
-subpackages org:com
|
||||
|
||||
See createDocs.sh script in /examples dir how to run.
|
||||
|
||||
Print help :
|
||||
|
||||
javadoc -docletpath target/TeXDoclet.jar -doclet org.stfm.texdoclet.TeXDoclet
|
||||
|
||||
TeXDoclet usage :
|
||||
|
||||
-title <title> A title to use for the generated output document.
|
||||
-subtitle <title> A subtitle for the output document. No -title will result in no title page.
|
||||
-output <outfile> Specifies the output file to write to. If none specified, the default is docs.tex in the current directory.
|
||||
-docclass <class> LaTeX2e document class, `report' is the default.
|
||||
-doctype <type> LaTeX2e document style, `headings' is the default.
|
||||
-classfilter <name> The name of a class implementing the ClassFilter interface.
|
||||
-date <date string> The value to use for the document date.
|
||||
-author <author> Specifies string to use for document Author.
|
||||
-texinit <file> LaTeX2e statements included before \begin{document}.
|
||||
-texsetup <file> LaTeX2e statements included after \begin{document} \maketitle (if title was specified).
|
||||
-texintro <file> LaTeX2e statements included after table of contents
|
||||
-texfinish <file> LaTeX2e statements included before \end{document}.
|
||||
-texpackage <file> LaTeX2e statements included before packages' \chapter.
|
||||
-setup <file> A setup file included before \begin{document}.
|
||||
-twosided Print twosided.
|
||||
-serial Do print Serializable information.
|
||||
-nosummaries Do print summaries of fiels, constructors and methods.
|
||||
-nofieldsummary Do not print field summaries
|
||||
-noconstructorsummary Do not print constructor summaries
|
||||
-noinherited Do not include inherited API information in output.
|
||||
-shortinherited Prints a short inheritance, only the member name (not the whole signature)
|
||||
-noindex Do not create index.
|
||||
-tree Create a class tree.
|
||||
-treeindent <float> Indent <float>cm i the class tree. Default is 1cm.
|
||||
-hyperref Use the hyperref package.
|
||||
-pdfhyperref Use the hyperref package with pdf. Overrides -hypertex
|
||||
-version Includes version-tags
|
||||
-hr Prints horizontal rows in the output (to get a better? view)
|
||||
-include Creates output without latex initiation (writes it in initdocsinclude.tex), titlepage, contents
|
||||
-sectionlevel <level> Specifies the highest level of sections (either "subsection", "section" or "chapter")
|
||||
-imagespath Path to the texdoclet_images dir (absolute or relative to the output document .tex file).
|
||||
|
||||
|
||||
|
||||
|
||||
24
examples/example1_complete_report/createDocs.sh
Executable file
24
examples/example1_complete_report/createDocs.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
mkdir texdoclet_output
|
||||
|
||||
rm texdoclet_output/TeXDoclet.aux
|
||||
|
||||
javadoc -docletpath ../../target/TeXDoclet.jar \
|
||||
-doclet org.stfm.texdoclet.TeXDoclet \
|
||||
-noindex \
|
||||
-tree \
|
||||
-hyperref \
|
||||
-texinit texdoclet_include/preamble.tex \
|
||||
-imagespath ".." \
|
||||
-output texdoclet_output/TeXDoclet.tex \
|
||||
-title "TeXDoclet Java Documentation" \
|
||||
-subtitle "Created with Javadoc TeXDoclet Doclet" \
|
||||
-author "Greg Wonderly \and S\"oren Caspersen \and Stefan Marx" \
|
||||
-sourcepath ../../src/main/java \
|
||||
-subpackages org:com \
|
||||
-shortinherited
|
||||
|
||||
cd texdoclet_output
|
||||
pdflatex TeXDoclet.tex
|
||||
pdflatex TeXDoclet.tex
|
||||
mkdir ../javadoc
|
||||
cp TeXDoclet.pdf ../javadoc
|
||||
31
examples/example2_complete_report/createDocs.sh
Executable file
31
examples/example2_complete_report/createDocs.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# this example demonstrates the use of different .tex inlude files
|
||||
#
|
||||
|
||||
mkdir texdoclet_output
|
||||
|
||||
rm texdoclet_output/TeXDoclet.aux
|
||||
|
||||
javadoc -docletpath ../../target/TeXDoclet.jar \
|
||||
-doclet org.stfm.texdoclet.TeXDoclet \
|
||||
-noindex \
|
||||
-tree \
|
||||
-hyperref \
|
||||
-texsetup texdoclet_include/setup.tex \
|
||||
-texintro texdoclet_include/intro.tex \
|
||||
-texfinish texdoclet_include/finish.tex \
|
||||
-texinit texdoclet_include/preamble.tex \
|
||||
-imagespath ".." \
|
||||
-output texdoclet_output/TeXDoclet.tex \
|
||||
-title "TeXDoclet Java Documentation" \
|
||||
-subtitle "Created with Javadoc TeXDoclet Doclet" \
|
||||
-author "Greg Wonderly \and S\"oren Caspersen \and Stefan Marx" \
|
||||
-sourcepath ../../src/main/java \
|
||||
-subpackages org:com \
|
||||
-sectionlevel section
|
||||
|
||||
cd texdoclet_output
|
||||
pdflatex TeXDoclet.tex
|
||||
pdflatex TeXDoclet.tex
|
||||
mkdir ../javadoc
|
||||
cp TeXDoclet.pdf ../javadoc
|
||||
@@ -0,0 +1,16 @@
|
||||
% ------- textdoclet_include/finish.tex
|
||||
|
||||
% add something here
|
||||
|
||||
% closing for \chapter{TeXDoclet Java Documentation} {
|
||||
}
|
||||
|
||||
\chapter{Finish}{
|
||||
|
||||
(content from file finish.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
|
||||
}
|
||||
% ------- textdoclet_include/finish.tex end
|
||||
@@ -0,0 +1,41 @@
|
||||
% ------- textdoclet_include/intro.tex
|
||||
|
||||
% add something here
|
||||
|
||||
\chapter{Introduction} {
|
||||
|
||||
(content from file intro.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
}
|
||||
\chapter{Foo} {
|
||||
|
||||
(content from file intro.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
}
|
||||
|
||||
\chapter{Bar} {
|
||||
|
||||
(content from file intro.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
|
||||
Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
|
||||
|
||||
Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
|
||||
|
||||
}
|
||||
|
||||
\chapter{TeXDoclet Java Documentation} {
|
||||
|
||||
% ------- textdoclet_include/intro.tex end
|
||||
@@ -0,0 +1,11 @@
|
||||
% ------- textdoclet_include/setup.tex
|
||||
|
||||
% add something here
|
||||
\begin{abstract}
|
||||
(content from file setup.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
\end{abstract}
|
||||
|
||||
% ------- textdoclet_include/setup.tex end
|
||||
25
examples/example3_complete_article/createDocs.sh
Executable file
25
examples/example3_complete_article/createDocs.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
mkdir texdoclet_output
|
||||
|
||||
rm texdoclet_output/TeXDoclet.aux
|
||||
|
||||
javadoc -docletpath ../../target/TeXDoclet.jar \
|
||||
-doclet org.stfm.texdoclet.TeXDoclet \
|
||||
-noindex \
|
||||
-hyperref \
|
||||
-texinit texdoclet_include/preamble.tex \
|
||||
-texsetup texdoclet_include/setup.tex \
|
||||
-texintro texdoclet_include/intro.tex \
|
||||
-texfinish texdoclet_include/finish.tex \
|
||||
-imagespath ".." \
|
||||
-output texdoclet_output/TeXDoclet.tex \
|
||||
-sourcepath ../../src/main/java \
|
||||
-subpackages org:com \
|
||||
-sectionlevel section \
|
||||
-docclass article \
|
||||
-nosummaries
|
||||
|
||||
cd texdoclet_output
|
||||
pdflatex TeXDoclet.tex
|
||||
pdflatex TeXDoclet.tex
|
||||
mkdir ../javadoc
|
||||
cp TeXDoclet.pdf ../javadoc
|
||||
@@ -0,0 +1,18 @@
|
||||
% ------- textdoclet_include/finish.tex
|
||||
|
||||
% add something here
|
||||
|
||||
%\chapter{Finish}{
|
||||
\section{Finish}{
|
||||
%
|
||||
% or without numbering :
|
||||
%
|
||||
%\section*{Finish} {
|
||||
%\addcontentsline{toc}{section}{Finish}
|
||||
(content from file finish.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
|
||||
}
|
||||
% ------- textdoclet_include/finish.tex end
|
||||
@@ -0,0 +1,17 @@
|
||||
% ------- textdoclet_include/intro.tex
|
||||
|
||||
% add something here
|
||||
|
||||
\section{Introduction} {
|
||||
%
|
||||
% or without numbering :
|
||||
%
|
||||
%\section*{Introduction} {
|
||||
%\addcontentsline{toc}{section}{Introduction}
|
||||
(content from file intro.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
}
|
||||
|
||||
% ------- textdoclet_include/intro.tex end
|
||||
@@ -0,0 +1,15 @@
|
||||
% ------- textdoclet_include/preamble.tex
|
||||
|
||||
% add something here
|
||||
|
||||
\date{\today}
|
||||
\title{TeXDoclet Java Documentation\bigskip\\ \Large Created with Javadoc TeXDoclet Doclet}
|
||||
\author{Greg Wonderly \and S\"oren Caspersen \and Stefan Marx}
|
||||
|
||||
%\usepackage{titlesec}
|
||||
%\titlespacing*{\chapter}{0pt}{10pt}{5pt}
|
||||
%\titlespacing*{\section}{0pt}{10pt}{5pt}
|
||||
%\titlespacing*{\subsection}{0pt}{5pt}{3pt}
|
||||
%\titlespacing*{\subsubsection}{0pt}{5pt}{3pt}
|
||||
|
||||
% ------- textdoclet_include/preamble.tex end
|
||||
@@ -0,0 +1,14 @@
|
||||
% ------- textdoclet_include/setup.tex
|
||||
|
||||
% we have to call maketitle here because no title was given in the javadoc -docletpath ../../target/TeXDoclet.jar execution
|
||||
\maketitle
|
||||
|
||||
% add something here
|
||||
\begin{abstract}
|
||||
(content from file setup.tex)
|
||||
\newline
|
||||
\newline
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
\end{abstract}
|
||||
|
||||
% ------- textdoclet_include/setup.tex end
|
||||
36
examples/example4_include/MyDocument.tex
Normal file
36
examples/example4_include/MyDocument.tex
Normal file
@@ -0,0 +1,36 @@
|
||||
\documentclass[11pt,a4paper]{report}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{blindtext}
|
||||
|
||||
% 1. TeXDoclet output include
|
||||
\input{texdoclet_output/TeXDoclet_preamble}
|
||||
|
||||
% use behind of TeXDoclet_preamble.tex because of option clash with pdftex
|
||||
\usepackage{fullpage}
|
||||
\usepackage{hyperref}
|
||||
\hypersetup{
|
||||
colorlinks=true,allcolors=blue,pdfpagemode=UseOutlines,pdfpagelayout=TwoPageRight
|
||||
}
|
||||
\usepackage{hypcap}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\date{\today}
|
||||
\title{TeXDoclet Java Documentation\bigskip\\ \Large Created with Javadoc TeXDoclet Doclet}
|
||||
\author{Greg Wonderly \and S\"oren Caspersen \and Stefan Marx}
|
||||
\maketitle
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\chapter{Foo} {\section{Foo1} {\blindtext}}
|
||||
|
||||
\chapter{Bar} {\section{Bar1} {\blindtext \newline \newline \blindtext }\section{Bar2} {\blindtext}}
|
||||
|
||||
\chapter{TeXdoclet Java Documentation} {
|
||||
% 2. TeXDoclet output include
|
||||
\input{texdoclet_output/TeXDoclet}
|
||||
}
|
||||
|
||||
\chapter{FooBar} {\section{FooBar1} {\blindtext}}
|
||||
|
||||
\end{document}
|
||||
31
examples/example4_include/createDocs.sh
Executable file
31
examples/example4_include/createDocs.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# - this example shows how to use the -include option
|
||||
# - TeXDoclet generated output (TeXDoclet.tex and TeXDoclet_preamble.tex)
|
||||
# is included in another Latex document (MyDocument.tex) here
|
||||
#
|
||||
|
||||
mkdir texdoclet_output
|
||||
|
||||
rm MyDocument.aux
|
||||
rm MyDocument.idx
|
||||
rm MyDocument.out
|
||||
rm MyDocument.toc
|
||||
rm MyDocument.pdf
|
||||
rm texdoclet_output/TeXDoclet.aux
|
||||
rm texdoclet_output/TeXDoclet_preamble.aux
|
||||
|
||||
# -imagespath ".." not needed here because path texdoclet_images is in subdir of MyDocument.tex
|
||||
|
||||
javadoc -docletpath ../../target/TeXDoclet.jar \
|
||||
-doclet org.stfm.texdoclet.TeXDoclet \
|
||||
-tree \
|
||||
-noindex \
|
||||
-hyperref \
|
||||
-output texdoclet_output/TeXDoclet.tex \
|
||||
-sourcepath ../../src/main/java \
|
||||
-subpackages com:org \
|
||||
-include \
|
||||
-sectionlevel section
|
||||
|
||||
pdflatex MyDocument.tex
|
||||
pdflatex MyDocument.tex
|
||||
54
pom.xml
Normal file
54
pom.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.stfm</groupId>
|
||||
<artifactId>texdoclet</artifactId>
|
||||
<version>0.9-SNAPSHOT</version>
|
||||
<name>TexDoclet</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
|
||||
<maven.compiler.source>1.6</maven.compiler.source>
|
||||
<maven.compiler.target>1.6</maven.compiler.target>
|
||||
|
||||
<maven-shade-plugin.version>1.4</maven-shade-plugin.version>
|
||||
<maven-war-plugin.version>2.1.1</maven-war-plugin.version>
|
||||
|
||||
<finalJarName>TeXdoclet</finalJarName>
|
||||
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
||||
<finalName>${finalJarName}</finalName>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>${maven-shade-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<manifestEntries>
|
||||
<Main-Class>org.stfm.texdoclet.TeXDoclet</Main-Class>
|
||||
</manifestEntries>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
621
src/main/java/com/keypoint/PngEncoder.java
Executable file
621
src/main/java/com/keypoint/PngEncoder.java
Executable file
@@ -0,0 +1,621 @@
|
||||
package com.keypoint;
|
||||
|
||||
/**
|
||||
* PngEncoder takes a Java Image object and creates a byte string which can be saved as a PNG file.
|
||||
* The Image is presumed to use the DirectColorModel.
|
||||
*
|
||||
* Thanks to Jay Denny at KeyPoint Software
|
||||
* http://www.keypoint.com/
|
||||
* who let me develop this code on company time.
|
||||
*
|
||||
* You may contact me with (probably very-much-needed) improvements,
|
||||
* comments, and bug fixes at:
|
||||
*
|
||||
* david@catcode.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* A copy of the GNU LGPL may be found at
|
||||
* http://www.gnu.org/copyleft/lesser.html,
|
||||
*
|
||||
* @author J. David Eisenberg
|
||||
* @version 1.4, 31 March 2000
|
||||
*/
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.io.*;
|
||||
|
||||
public class PngEncoder extends Object
|
||||
{
|
||||
/** Constant specifying that alpha channel should be encoded. */
|
||||
public static final boolean ENCODE_ALPHA=true;
|
||||
/** Constant specifying that alpha channel should not be encoded. */
|
||||
public static final boolean NO_ALPHA=false;
|
||||
/** Constants for filters */
|
||||
public static final int FILTER_NONE = 0;
|
||||
public static final int FILTER_SUB = 1;
|
||||
public static final int FILTER_UP = 2;
|
||||
public static final int FILTER_LAST = 2;
|
||||
|
||||
protected byte[] pngBytes;
|
||||
protected byte[] priorRow;
|
||||
protected byte[] leftBytes;
|
||||
protected Image image;
|
||||
protected int width, height;
|
||||
protected int bytePos, maxPos;
|
||||
protected int hdrPos, dataPos, endPos;
|
||||
protected CRC32 crc = new CRC32();
|
||||
protected long crcValue;
|
||||
protected boolean encodeAlpha;
|
||||
protected int filter;
|
||||
protected int bytesPerPixel;
|
||||
protected int compressionLevel;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
*/
|
||||
public PngEncoder()
|
||||
{
|
||||
this( null, false, FILTER_NONE, 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying Image to encode, with no alpha channel encoding.
|
||||
*
|
||||
* @param image A Java Image object which uses the DirectColorModel
|
||||
* @see java.awt.Image
|
||||
*/
|
||||
public PngEncoder( Image image )
|
||||
{
|
||||
this(image, false, FILTER_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying Image to encode, and whether to encode alpha.
|
||||
*
|
||||
* @param image A Java Image object which uses the DirectColorModel
|
||||
* @param encodeAlpha Encode the alpha channel? false=no; true=yes
|
||||
* @see java.awt.Image
|
||||
*/
|
||||
public PngEncoder( Image image, boolean encodeAlpha )
|
||||
{
|
||||
this(image, encodeAlpha, FILTER_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying Image to encode, whether to encode alpha, and filter to use.
|
||||
*
|
||||
* @param image A Java Image object which uses the DirectColorModel
|
||||
* @param encodeAlpha Encode the alpha channel? false=no; true=yes
|
||||
* @param whichFilter 0=none, 1=sub, 2=up
|
||||
* @see java.awt.Image
|
||||
*/
|
||||
public PngEncoder( Image image, boolean encodeAlpha, int whichFilter )
|
||||
{
|
||||
this( image, encodeAlpha, whichFilter, 0 );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class constructor specifying Image source to encode, whether to encode alpha, filter to use, and compression level.
|
||||
*
|
||||
* @param image A Java Image object
|
||||
* @param encodeAlpha Encode the alpha channel? false=no; true=yes
|
||||
* @param whichFilter 0=none, 1=sub, 2=up
|
||||
* @param compLevel 0..9
|
||||
* @see java.awt.Image
|
||||
*/
|
||||
public PngEncoder( Image image, boolean encodeAlpha, int whichFilter,
|
||||
int compLevel)
|
||||
{
|
||||
this.image = image;
|
||||
this.encodeAlpha = encodeAlpha;
|
||||
setFilter( whichFilter );
|
||||
if (compLevel >=0 && compLevel <=9)
|
||||
{
|
||||
this.compressionLevel = compLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image to be encoded
|
||||
*
|
||||
* @param image A Java Image object which uses the DirectColorModel
|
||||
* @see java.awt.Image
|
||||
* @see java.awt.image.DirectColorModel
|
||||
*/
|
||||
public void setImage( Image image )
|
||||
{
|
||||
this.image = image;
|
||||
pngBytes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of bytes that is the PNG equivalent of the current image, specifying whether to encode alpha or not.
|
||||
*
|
||||
* @param encodeAlpha boolean false=no alpha, true=encode alpha
|
||||
* @return an array of bytes, or null if there was a problem
|
||||
*/
|
||||
public byte[] pngEncode( boolean encodeAlpha )
|
||||
{
|
||||
byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 };
|
||||
int i;
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
width = image.getWidth( null );
|
||||
height = image.getHeight( null );
|
||||
this.image = image;
|
||||
|
||||
/*
|
||||
* start with an array that is big enough to hold all the pixels
|
||||
* (plus filter bytes), and an extra 200 bytes for header info
|
||||
*/
|
||||
pngBytes = new byte[((width+1) * height * 3) + 200];
|
||||
|
||||
/*
|
||||
* keep track of largest byte written to the array
|
||||
*/
|
||||
maxPos = 0;
|
||||
|
||||
bytePos = writeBytes( pngIdBytes, 0 );
|
||||
hdrPos = bytePos;
|
||||
writeHeader();
|
||||
dataPos = bytePos;
|
||||
if (writeImageData())
|
||||
{
|
||||
writeEnd();
|
||||
pngBytes = resizeByteArray( pngBytes, maxPos );
|
||||
}
|
||||
else
|
||||
{
|
||||
pngBytes = null;
|
||||
}
|
||||
return pngBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of bytes that is the PNG equivalent of the current image.
|
||||
* Alpha encoding is determined by its setting in the constructor.
|
||||
*
|
||||
* @return an array of bytes, or null if there was a problem
|
||||
*/
|
||||
public byte[] pngEncode()
|
||||
{
|
||||
return pngEncode( encodeAlpha );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha encoding on or off.
|
||||
*
|
||||
* @param encodeAlpha false=no, true=yes
|
||||
*/
|
||||
public void setEncodeAlpha( boolean encodeAlpha )
|
||||
{
|
||||
this.encodeAlpha = encodeAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve alpha encoding status.
|
||||
*
|
||||
* @return boolean false=no, true=yes
|
||||
*/
|
||||
public boolean getEncodeAlpha()
|
||||
{
|
||||
return encodeAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter to use
|
||||
*
|
||||
* @param whichFilter from constant list
|
||||
*/
|
||||
public void setFilter( int whichFilter )
|
||||
{
|
||||
this.filter = FILTER_NONE;
|
||||
if ( whichFilter <= FILTER_LAST )
|
||||
{
|
||||
this.filter = whichFilter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve filtering scheme
|
||||
*
|
||||
* @return int (see constant list)
|
||||
*/
|
||||
public int getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the compression level to use
|
||||
*
|
||||
* @param level 0 through 9
|
||||
*/
|
||||
public void setCompressionLevel( int level )
|
||||
{
|
||||
if ( level >= 0 && level <= 9)
|
||||
{
|
||||
this.compressionLevel = level;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve compression level
|
||||
*
|
||||
* @return int in range 0-9
|
||||
*/
|
||||
public int getCompressionLevel()
|
||||
{
|
||||
return compressionLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase or decrease the length of a byte array.
|
||||
*
|
||||
* @param array The original array.
|
||||
* @param newLength The length you wish the new array to have.
|
||||
* @return Array of newly desired length. If shorter than the
|
||||
* original, the trailing elements are truncated.
|
||||
*/
|
||||
protected byte[] resizeByteArray( byte[] array, int newLength )
|
||||
{
|
||||
byte[] newArray = new byte[newLength];
|
||||
int oldLength = array.length;
|
||||
|
||||
System.arraycopy( array, 0, newArray, 0,
|
||||
Math.min( oldLength, newLength ) );
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of bytes into the pngBytes array.
|
||||
* Note: This routine has the side effect of updating
|
||||
* maxPos, the largest element written in the array.
|
||||
* The array is resized by 1000 bytes or the length
|
||||
* of the data to be written, whichever is larger.
|
||||
*
|
||||
* @param data The data to be written into pngBytes.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
*/
|
||||
protected int writeBytes( byte[] data, int offset )
|
||||
{
|
||||
maxPos = Math.max( maxPos, offset + data.length );
|
||||
if (data.length + offset > pngBytes.length)
|
||||
{
|
||||
pngBytes = resizeByteArray( pngBytes, pngBytes.length +
|
||||
Math.max( 1000, data.length ) );
|
||||
}
|
||||
System.arraycopy( data, 0, pngBytes, offset, data.length );
|
||||
return offset + data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an array of bytes into the pngBytes array, specifying number of bytes to write.
|
||||
* Note: This routine has the side effect of updating
|
||||
* maxPos, the largest element written in the array.
|
||||
* The array is resized by 1000 bytes or the length
|
||||
* of the data to be written, whichever is larger.
|
||||
*
|
||||
* @param data The data to be written into pngBytes.
|
||||
* @param nBytes The number of bytes to be written.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
*/
|
||||
protected int writeBytes( byte[] data, int nBytes, int offset )
|
||||
{
|
||||
maxPos = Math.max( maxPos, offset + nBytes );
|
||||
if (nBytes + offset > pngBytes.length)
|
||||
{
|
||||
pngBytes = resizeByteArray( pngBytes, pngBytes.length +
|
||||
Math.max( 1000, nBytes ) );
|
||||
}
|
||||
System.arraycopy( data, 0, pngBytes, offset, nBytes );
|
||||
return offset + nBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a two-byte integer into the pngBytes array at a given position.
|
||||
*
|
||||
* @param n The integer to be written into pngBytes.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
*/
|
||||
protected int writeInt2( int n, int offset )
|
||||
{
|
||||
byte[] temp = { (byte)((n >> 8) & 0xff),
|
||||
(byte) (n & 0xff) };
|
||||
return writeBytes( temp, offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a four-byte integer into the pngBytes array at a given position.
|
||||
*
|
||||
* @param n The integer to be written into pngBytes.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
*/
|
||||
protected int writeInt4( int n, int offset )
|
||||
{
|
||||
byte[] temp = { (byte)((n >> 24) & 0xff),
|
||||
(byte) ((n >> 16) & 0xff ),
|
||||
(byte) ((n >> 8) & 0xff ),
|
||||
(byte) ( n & 0xff ) };
|
||||
return writeBytes( temp, offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single byte into the pngBytes array at a given position.
|
||||
*
|
||||
* @param n The integer to be written into pngBytes.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
*/
|
||||
protected int writeByte( int b, int offset )
|
||||
{
|
||||
byte[] temp = { (byte) b };
|
||||
return writeBytes( temp, offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string into the pngBytes array at a given position.
|
||||
* This uses the getBytes method, so the encoding used will
|
||||
* be its default.
|
||||
*
|
||||
* @param n The integer to be written into pngBytes.
|
||||
* @param offset The starting point to write to.
|
||||
* @return The next place to be written to in the pngBytes array.
|
||||
* @see java.lang.String#getBytes()
|
||||
*/
|
||||
protected int writeString( String s, int offset )
|
||||
{
|
||||
return writeBytes( s.getBytes(), offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a PNG "IHDR" chunk into the pngBytes array.
|
||||
*/
|
||||
protected void writeHeader()
|
||||
{
|
||||
int startPos;
|
||||
|
||||
startPos = bytePos = writeInt4( 13, bytePos );
|
||||
bytePos = writeString( "IHDR", bytePos );
|
||||
width = image.getWidth( null );
|
||||
height = image.getHeight( null );
|
||||
bytePos = writeInt4( width, bytePos );
|
||||
bytePos = writeInt4( height, bytePos );
|
||||
bytePos = writeByte( 8, bytePos ); // bit depth
|
||||
bytePos = writeByte( (encodeAlpha) ? 6 : 2, bytePos ); // direct model
|
||||
bytePos = writeByte( 0, bytePos ); // compression method
|
||||
bytePos = writeByte( 0, bytePos ); // filter method
|
||||
bytePos = writeByte( 0, bytePos ); // no interlace
|
||||
crc.reset();
|
||||
crc.update( pngBytes, startPos, bytePos-startPos );
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4( (int) crcValue, bytePos );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform "sub" filtering on the given row.
|
||||
* Uses temporary array leftBytes to store the original values
|
||||
* of the previous pixels. The array is 16 bytes long, which
|
||||
* will easily hold two-byte samples plus two-byte alpha.
|
||||
*
|
||||
* @param pixels The array holding the scan lines being built
|
||||
* @param startPos Starting position within pixels of bytes to be filtered.
|
||||
* @param width Width of a scanline in pixels.
|
||||
*/
|
||||
protected void filterSub( byte[] pixels, int startPos, int width )
|
||||
{
|
||||
int i;
|
||||
int offset = bytesPerPixel;
|
||||
int actualStart = startPos + offset;
|
||||
int nBytes = width * bytesPerPixel;
|
||||
int leftInsert = offset;
|
||||
int leftExtract = 0;
|
||||
byte current_byte;
|
||||
|
||||
for (i=actualStart; i < startPos + nBytes; i++)
|
||||
{
|
||||
leftBytes[leftInsert] = pixels[i];
|
||||
pixels[i] = (byte) ((pixels[i] - leftBytes[leftExtract]) % 256);
|
||||
leftInsert = (leftInsert+1) % 0x0f;
|
||||
leftExtract = (leftExtract + 1) % 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform "up" filtering on the given row.
|
||||
* Side effect: refills the prior row with current row
|
||||
*
|
||||
* @param pixels The array holding the scan lines being built
|
||||
* @param startPos Starting position within pixels of bytes to be filtered.
|
||||
* @param width Width of a scanline in pixels.
|
||||
*/
|
||||
protected void filterUp( byte[] pixels, int startPos, int width )
|
||||
{
|
||||
int i, nBytes;
|
||||
byte current_byte;
|
||||
|
||||
nBytes = width * bytesPerPixel;
|
||||
|
||||
for (i=0; i < nBytes; i++)
|
||||
{
|
||||
current_byte = pixels[startPos + i];
|
||||
pixels[startPos + i] = (byte) ((pixels[startPos + i] - priorRow[i]) % 256);
|
||||
priorRow[i] = current_byte;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the image data into the pngBytes array.
|
||||
* This will write one or more PNG "IDAT" chunks. In order
|
||||
* to conserve memory, this method grabs as many rows as will
|
||||
* fit into 32K bytes, or the whole image; whichever is less.
|
||||
*
|
||||
*
|
||||
* @return true if no errors; false if error grabbing pixels
|
||||
*/
|
||||
protected boolean writeImageData()
|
||||
{
|
||||
int rowsLeft = height; // number of rows remaining to write
|
||||
int startRow = 0; // starting row to process this time through
|
||||
int nRows; // how many rows to grab at a time
|
||||
|
||||
byte[] scanLines; // the scan lines to be compressed
|
||||
int scanPos; // where we are in the scan lines
|
||||
int startPos; // where this line's actual pixels start (used for filtering)
|
||||
|
||||
byte[] compressedLines; // the resultant compressed lines
|
||||
int nCompressed; // how big is the compressed area?
|
||||
|
||||
int depth; // color depth ( handle only 8 or 32 )
|
||||
|
||||
PixelGrabber pg;
|
||||
|
||||
bytesPerPixel = (encodeAlpha) ? 4 : 3;
|
||||
|
||||
Deflater scrunch = new Deflater( compressionLevel );
|
||||
ByteArrayOutputStream outBytes =
|
||||
new ByteArrayOutputStream(1024);
|
||||
|
||||
DeflaterOutputStream compBytes =
|
||||
new DeflaterOutputStream( outBytes, scrunch );
|
||||
try
|
||||
{
|
||||
while (rowsLeft > 0)
|
||||
{
|
||||
nRows = Math.min( 32767 / (width*(bytesPerPixel+1)), rowsLeft );
|
||||
// nRows = rowsLeft;
|
||||
|
||||
int[] pixels = new int[width * nRows];
|
||||
|
||||
pg = new PixelGrabber(image, 0, startRow,
|
||||
width, nRows, pixels, 0, width);
|
||||
try {
|
||||
pg.grabPixels();
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.err.println("interrupted waiting for pixels!");
|
||||
return false;
|
||||
}
|
||||
if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
|
||||
System.err.println("image fetch aborted or errored");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a data chunk. scanLines adds "nRows" for
|
||||
* the filter bytes.
|
||||
*/
|
||||
scanLines = new byte[width * nRows * bytesPerPixel + nRows];
|
||||
|
||||
if (filter == FILTER_SUB)
|
||||
{
|
||||
leftBytes = new byte[16];
|
||||
}
|
||||
if (filter == FILTER_UP)
|
||||
{
|
||||
priorRow = new byte[width*bytesPerPixel];
|
||||
}
|
||||
|
||||
scanPos = 0;
|
||||
startPos = 1;
|
||||
for (int i=0; i<width*nRows; i++)
|
||||
{
|
||||
if (i % width == 0)
|
||||
{
|
||||
scanLines[scanPos++] = (byte) filter;
|
||||
startPos = scanPos;
|
||||
}
|
||||
scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff);
|
||||
scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff);
|
||||
scanLines[scanPos++] = (byte) ((pixels[i] ) & 0xff);
|
||||
if (encodeAlpha)
|
||||
{
|
||||
scanLines[scanPos++] = (byte) ((pixels[i] >> 24) & 0xff );
|
||||
}
|
||||
if ((i % width == width-1) && (filter != FILTER_NONE))
|
||||
{
|
||||
if (filter == FILTER_SUB)
|
||||
{
|
||||
filterSub( scanLines, startPos, width );
|
||||
}
|
||||
if (filter == FILTER_UP)
|
||||
{
|
||||
filterUp( scanLines, startPos, width );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write these lines to the output area
|
||||
*/
|
||||
compBytes.write( scanLines, 0, scanPos );
|
||||
|
||||
|
||||
startRow += nRows;
|
||||
rowsLeft -= nRows;
|
||||
}
|
||||
compBytes.close();
|
||||
|
||||
/*
|
||||
* Write the compressed bytes
|
||||
*/
|
||||
compressedLines = outBytes.toByteArray();
|
||||
nCompressed = compressedLines.length;
|
||||
|
||||
crc.reset();
|
||||
bytePos = writeInt4( nCompressed, bytePos );
|
||||
bytePos = writeString("IDAT", bytePos );
|
||||
crc.update("IDAT".getBytes());
|
||||
bytePos = writeBytes( compressedLines, nCompressed, bytePos );
|
||||
crc.update( compressedLines, 0, nCompressed );
|
||||
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4( (int) crcValue, bytePos );
|
||||
scrunch.finish();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println( e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a PNG "IEND" chunk into the pngBytes array.
|
||||
*/
|
||||
protected void writeEnd()
|
||||
{
|
||||
bytePos = writeInt4( 0, bytePos );
|
||||
bytePos = writeString( "IEND", bytePos );
|
||||
crc.reset();
|
||||
crc.update("IEND".getBytes());
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4( (int) crcValue, bytePos );
|
||||
}
|
||||
}
|
||||
|
||||
415
src/main/java/com/keypoint/PngEncoderB.java
Executable file
415
src/main/java/com/keypoint/PngEncoderB.java
Executable file
@@ -0,0 +1,415 @@
|
||||
package com.keypoint;
|
||||
|
||||
/**
|
||||
* PngEncoderB takes a Java BufferedImage object and creates a byte string which can be saved as a PNG file.
|
||||
* The encoder will accept BufferedImages with eight-bit samples
|
||||
* or 4-byte ARGB samples.
|
||||
*
|
||||
* There is also code to handle 4-byte samples returned as
|
||||
* one int per pixel, but that has not been tested.
|
||||
*
|
||||
* Thanks to Jay Denny at KeyPoint Software
|
||||
* http://www.keypoint.com/
|
||||
* who let me develop this code on company time.
|
||||
*
|
||||
* You may contact me with (probably very-much-needed) improvements,
|
||||
* comments, and bug fixes at:
|
||||
*
|
||||
* david@catcode.com
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* A copy of the GNU LGPL may be found at
|
||||
* http://www.gnu.org/copyleft/lesser.html,
|
||||
*
|
||||
* @author J. David Eisenberg
|
||||
* @version 1.4, 31 March 2000
|
||||
*/
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.IndexColorModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
public class PngEncoderB extends PngEncoder {
|
||||
protected BufferedImage image;
|
||||
protected WritableRaster wRaster;
|
||||
protected int tType;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
*/
|
||||
public PngEncoderB() {
|
||||
this(null, false, FILTER_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying BufferedImage to encode, with no alpha
|
||||
* channel encoding.
|
||||
*
|
||||
* @param image
|
||||
* A Java BufferedImage object
|
||||
*/
|
||||
public PngEncoderB(BufferedImage image) {
|
||||
this(image, false, FILTER_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying BufferedImage to encode, and whether to
|
||||
* encode alpha.
|
||||
*
|
||||
* @param image
|
||||
* A Java BufferedImage object
|
||||
* @param encodeAlpha
|
||||
* Encode the alpha channel? false=no; true=yes
|
||||
*/
|
||||
public PngEncoderB(BufferedImage image, boolean encodeAlpha) {
|
||||
this(image, encodeAlpha, FILTER_NONE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying BufferedImage to encode, whether to encode
|
||||
* alpha, and filter to use.
|
||||
*
|
||||
* @param image
|
||||
* A Java BufferedImage object
|
||||
* @param encodeAlpha
|
||||
* Encode the alpha channel? false=no; true=yes
|
||||
* @param whichFilter
|
||||
* 0=none, 1=sub, 2=up
|
||||
*/
|
||||
public PngEncoderB(BufferedImage image, boolean encodeAlpha, int whichFilter) {
|
||||
this(image, encodeAlpha, whichFilter, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor specifying BufferedImage source to encode, whether to
|
||||
* encode alpha, filter to use, and compression level
|
||||
*
|
||||
* @param image
|
||||
* A Java BufferedImage object
|
||||
* @param encodeAlpha
|
||||
* Encode the alpha channel? false=no; true=yes
|
||||
* @param whichFilter
|
||||
* 0=none, 1=sub, 2=up
|
||||
* @param compLevel
|
||||
* 0..9
|
||||
*/
|
||||
public PngEncoderB(BufferedImage image, boolean encodeAlpha,
|
||||
int whichFilter, int compLevel) {
|
||||
this.image = image;
|
||||
this.encodeAlpha = encodeAlpha;
|
||||
setFilter(whichFilter);
|
||||
if (compLevel >= 0 && compLevel <= 9) {
|
||||
this.compressionLevel = compLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the BufferedImage to be encoded
|
||||
*
|
||||
* @param BufferedImage
|
||||
* A Java BufferedImage object
|
||||
*/
|
||||
public void setImage(BufferedImage image) {
|
||||
this.image = image;
|
||||
pngBytes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of bytes that is the PNG equivalent of the current
|
||||
* image, specifying whether to encode alpha or not.
|
||||
*
|
||||
* @param encodeAlpha
|
||||
* boolean false=no alpha, true=encode alpha
|
||||
* @return an array of bytes, or null if there was a problem
|
||||
*/
|
||||
@Override
|
||||
public byte[] pngEncode(boolean encodeAlpha) {
|
||||
byte[] pngIdBytes = { -119, 80, 78, 71, 13, 10, 26, 10 };
|
||||
int i;
|
||||
|
||||
if (image == null) {
|
||||
return null;
|
||||
}
|
||||
width = image.getWidth(null);
|
||||
height = image.getHeight(null);
|
||||
this.image = image;
|
||||
|
||||
if (!establishStorageInfo()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* start with an array that is big enough to hold all the pixels (plus
|
||||
* filter bytes), and an extra 200 bytes for header info
|
||||
*/
|
||||
pngBytes = new byte[((width + 1) * height * 3) + 200];
|
||||
|
||||
/*
|
||||
* keep track of largest byte written to the array
|
||||
*/
|
||||
maxPos = 0;
|
||||
|
||||
bytePos = writeBytes(pngIdBytes, 0);
|
||||
hdrPos = bytePos;
|
||||
writeHeader();
|
||||
dataPos = bytePos;
|
||||
if (writeImageData()) {
|
||||
writeEnd();
|
||||
pngBytes = resizeByteArray(pngBytes, maxPos);
|
||||
} else {
|
||||
pngBytes = null;
|
||||
}
|
||||
return pngBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of bytes that is the PNG equivalent of the current
|
||||
* image. Alpha encoding is determined by its setting in the constructor.
|
||||
*
|
||||
* @return an array of bytes, or null if there was a problem
|
||||
*/
|
||||
@Override
|
||||
public byte[] pngEncode() {
|
||||
return pngEncode(encodeAlpha);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get and set variables that determine how picture is stored.
|
||||
*
|
||||
* Retrieves the writable raster of the buffered image, as well its transfer
|
||||
* type.
|
||||
*
|
||||
* Sets number of output bytes per pixel, and, if only eight-bit bytes,
|
||||
* turns off alpha encoding.
|
||||
*
|
||||
* @return true if 1-byte or 4-byte data, false otherwise
|
||||
*/
|
||||
protected boolean establishStorageInfo() {
|
||||
int dataBytes;
|
||||
|
||||
wRaster = image.getRaster();
|
||||
dataBytes = wRaster.getNumDataElements();
|
||||
tType = wRaster.getTransferType();
|
||||
|
||||
if (((tType == DataBuffer.TYPE_BYTE) && (dataBytes == 4))
|
||||
|| ((tType == DataBuffer.TYPE_INT) && (dataBytes == 1))) {
|
||||
bytesPerPixel = (encodeAlpha) ? 4 : 3;
|
||||
} else if ((tType == DataBuffer.TYPE_BYTE) && (dataBytes == 1)) {
|
||||
bytesPerPixel = 1;
|
||||
encodeAlpha = false; // one-byte samples
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a PNG "IHDR" chunk into the pngBytes array.
|
||||
*/
|
||||
@Override
|
||||
protected void writeHeader() {
|
||||
int startPos;
|
||||
|
||||
startPos = bytePos = writeInt4(13, bytePos);
|
||||
bytePos = writeString("IHDR", bytePos);
|
||||
width = image.getWidth(null);
|
||||
height = image.getHeight(null);
|
||||
bytePos = writeInt4(width, bytePos);
|
||||
bytePos = writeInt4(height, bytePos);
|
||||
bytePos = writeByte(8, bytePos); // bit depth
|
||||
if (bytesPerPixel != 1) {
|
||||
bytePos = writeByte((encodeAlpha) ? 6 : 2, bytePos); // direct model
|
||||
} else {
|
||||
bytePos = writeByte(3, bytePos); // indexed
|
||||
}
|
||||
bytePos = writeByte(0, bytePos); // compression method
|
||||
bytePos = writeByte(0, bytePos); // filter method
|
||||
bytePos = writeByte(0, bytePos); // no interlace
|
||||
crc.reset();
|
||||
crc.update(pngBytes, startPos, bytePos - startPos);
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4((int) crcValue, bytePos);
|
||||
}
|
||||
|
||||
protected void writePalette(IndexColorModel icm) {
|
||||
byte[] redPal = new byte[256];
|
||||
byte[] greenPal = new byte[256];
|
||||
byte[] bluePal = new byte[256];
|
||||
byte[] allPal = new byte[768];
|
||||
int i;
|
||||
|
||||
icm.getReds(redPal);
|
||||
icm.getGreens(greenPal);
|
||||
icm.getBlues(bluePal);
|
||||
for (i = 0; i < 256; i++) {
|
||||
allPal[i * 3] = redPal[i];
|
||||
allPal[i * 3 + 1] = greenPal[i];
|
||||
allPal[i * 3 + 2] = bluePal[i];
|
||||
}
|
||||
bytePos = writeInt4(768, bytePos);
|
||||
bytePos = writeString("PLTE", bytePos);
|
||||
crc.reset();
|
||||
crc.update("PLTE".getBytes());
|
||||
bytePos = writeBytes(allPal, bytePos);
|
||||
crc.update(allPal);
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4((int) crcValue, bytePos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the image data into the pngBytes array. This will write one or more
|
||||
* PNG "IDAT" chunks. In order to conserve memory, this method grabs as many
|
||||
* rows as will fit into 32K bytes, or the whole image; whichever is less.
|
||||
*
|
||||
*
|
||||
* @return true if no errors; false if error grabbing pixels
|
||||
*/
|
||||
@Override
|
||||
protected boolean writeImageData() {
|
||||
int rowsLeft = height; // number of rows remaining to write
|
||||
int startRow = 0; // starting row to process this time through
|
||||
int nRows; // how many rows to grab at a time
|
||||
|
||||
byte[] scanLines; // the scan lines to be compressed
|
||||
int scanPos; // where we are in the scan lines
|
||||
int startPos; // where this line's actual pixels start (used for
|
||||
// filtering)
|
||||
int readPos; // position from which source pixels are read
|
||||
|
||||
byte[] compressedLines; // the resultant compressed lines
|
||||
int nCompressed; // how big is the compressed area?
|
||||
|
||||
byte[] pixels; // storage area for byte-sized pixels
|
||||
int[] iPixels; // storage area for int-sized pixels
|
||||
|
||||
Deflater scrunch = new Deflater(compressionLevel);
|
||||
ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
|
||||
|
||||
DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes,
|
||||
scrunch);
|
||||
|
||||
if (bytesPerPixel == 1) {
|
||||
writePalette((IndexColorModel) image.getColorModel());
|
||||
}
|
||||
|
||||
try {
|
||||
while (rowsLeft > 0) {
|
||||
nRows = Math.min(32767 / (width * (bytesPerPixel + 1)),
|
||||
rowsLeft);
|
||||
// nRows = rowsLeft;
|
||||
|
||||
/*
|
||||
* Create a data chunk. scanLines adds "nRows" for the filter
|
||||
* bytes.
|
||||
*/
|
||||
scanLines = new byte[width * nRows * bytesPerPixel + nRows];
|
||||
|
||||
if (filter == FILTER_SUB) {
|
||||
leftBytes = new byte[16];
|
||||
}
|
||||
if (filter == FILTER_UP) {
|
||||
priorRow = new byte[width * bytesPerPixel];
|
||||
}
|
||||
|
||||
if (tType == DataBuffer.TYPE_BYTE) {
|
||||
pixels = (byte[]) wRaster.getDataElements(0, startRow,
|
||||
width, nRows, null);
|
||||
iPixels = null;
|
||||
} else {
|
||||
iPixels = (int[]) wRaster.getDataElements(0, startRow,
|
||||
width, nRows, null);
|
||||
pixels = null;
|
||||
}
|
||||
|
||||
scanPos = 0;
|
||||
readPos = 0;
|
||||
startPos = 1;
|
||||
for (int i = 0; i < width * nRows; i++) {
|
||||
if (i % width == 0) {
|
||||
scanLines[scanPos++] = (byte) filter;
|
||||
startPos = scanPos;
|
||||
}
|
||||
|
||||
if (bytesPerPixel == 1) {
|
||||
scanLines[scanPos++] = pixels[readPos++];
|
||||
} else if (tType == DataBuffer.TYPE_BYTE) {
|
||||
scanLines[scanPos++] = pixels[readPos++];
|
||||
scanLines[scanPos++] = pixels[readPos++];
|
||||
scanLines[scanPos++] = pixels[readPos++];
|
||||
if (encodeAlpha) {
|
||||
scanLines[scanPos++] = pixels[readPos++];
|
||||
} else {
|
||||
readPos++;
|
||||
}
|
||||
} else {
|
||||
scanLines[scanPos++] = (byte) ((iPixels[readPos] >> 16) & 0xff);
|
||||
scanLines[scanPos++] = (byte) ((iPixels[readPos] >> 8) & 0xff);
|
||||
scanLines[scanPos++] = (byte) ((iPixels[readPos]) & 0xff);
|
||||
if (encodeAlpha) {
|
||||
scanLines[scanPos++] = (byte) ((iPixels[readPos] >> 24) & 0xff);
|
||||
}
|
||||
readPos++;
|
||||
}
|
||||
if ((i % width == width - 1) && (filter != FILTER_NONE)) {
|
||||
if (filter == FILTER_SUB) {
|
||||
filterSub(scanLines, startPos, width);
|
||||
}
|
||||
if (filter == FILTER_UP) {
|
||||
filterUp(scanLines, startPos, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write these lines to the output area
|
||||
*/
|
||||
compBytes.write(scanLines, 0, scanPos);
|
||||
|
||||
startRow += nRows;
|
||||
rowsLeft -= nRows;
|
||||
}
|
||||
compBytes.close();
|
||||
|
||||
/*
|
||||
* Write the compressed bytes
|
||||
*/
|
||||
compressedLines = outBytes.toByteArray();
|
||||
nCompressed = compressedLines.length;
|
||||
|
||||
crc.reset();
|
||||
bytePos = writeInt4(nCompressed, bytePos);
|
||||
bytePos = writeString("IDAT", bytePos);
|
||||
crc.update("IDAT".getBytes());
|
||||
bytePos = writeBytes(compressedLines, nCompressed, bytePos);
|
||||
crc.update(compressedLines, 0, nCompressed);
|
||||
|
||||
crcValue = crc.getValue();
|
||||
bytePos = writeInt4((int) crcValue, bytePos);
|
||||
scrunch.finish();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.err.println(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
20
src/main/java/org/stfm/texdoclet/ClassFilter.java
Executable file
20
src/main/java/org/stfm/texdoclet/ClassFilter.java
Executable file
@@ -0,0 +1,20 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
|
||||
/**
|
||||
* This interface can be implemented and a class name provided to the Doclet to
|
||||
* filter which classes are and are not included in the output document.
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
* @author Gregg Wonderly - C2 Technologies Inc.
|
||||
*/
|
||||
public interface ClassFilter {
|
||||
|
||||
/**
|
||||
* Filters the ClassDoc passed. If true is returned, the passed class will
|
||||
* be included into the output. If false is returned, this document will not
|
||||
* be included.
|
||||
*/
|
||||
public boolean includeClass(ClassDoc cd);
|
||||
}
|
||||
79
src/main/java/org/stfm/texdoclet/ClassHierachy.java
Executable file
79
src/main/java/org/stfm/texdoclet/ClassHierachy.java
Executable file
@@ -0,0 +1,79 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Manages and prints a class hierarchy. Use <CODE>add</CODE> to add another
|
||||
* class to the hierarchy. Use <CODE>printTree</CODE> to print the corresponding
|
||||
* <TEX txt="\LaTeX{}">LaTeX</TEX>.
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
* @author Soeren Caspersen - XO Software
|
||||
*/
|
||||
public class ClassHierachy extends java.lang.Object {
|
||||
|
||||
public SortedMap root = new TreeMap();
|
||||
|
||||
/**
|
||||
* Creates new ClassHierachy
|
||||
*/
|
||||
public ClassHierachy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another class to the hierachy
|
||||
*/
|
||||
protected SortedMap add(ClassDoc cls) {
|
||||
SortedMap temp;
|
||||
if (cls.superclass() != null) {
|
||||
temp = add(cls.superclass());
|
||||
} else {
|
||||
temp = root;
|
||||
}
|
||||
|
||||
SortedMap result = (SortedMap) temp.get(cls.qualifiedName());
|
||||
if (result == null) {
|
||||
result = new TreeMap();
|
||||
temp.put(cls.qualifiedName(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the <TEX txt="\LaTeX{}">LaTeX</TEX> corresponding to the tree. The
|
||||
* tree is printed using <CODE>TeXDoclet.os</CODE>.
|
||||
*/
|
||||
public void printTree(RootDoc rootDoc, double overviewindent) {
|
||||
printBranch(rootDoc, root, 0, overviewindent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a branch of the tree. The branch is printed using
|
||||
* <CODE>TeXDoclet.os</CODE>.
|
||||
*/
|
||||
protected void printBranch(RootDoc rootDoc, SortedMap map, double indent,
|
||||
double overviewindent) {
|
||||
Set set = map.keySet();
|
||||
Iterator it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
String qualifName = (String) it.next();
|
||||
ClassDoc cls = rootDoc.classNamed(qualifName);
|
||||
TeXDoclet.os.print("\\hspace{" + Double.toString(indent)
|
||||
+ "cm} $\\bullet$ "
|
||||
+ HTMLtoLaTeXBackEnd.fixText(qualifName) + " {\\tiny ");
|
||||
// (S.M. modification) only for resolved classes
|
||||
if (cls != null) {
|
||||
TeXDoclet.printRef(cls.containingPackage(), cls.name(), "");
|
||||
}
|
||||
TeXDoclet.os.println("} \\\\");
|
||||
printBranch(rootDoc, (SortedMap) map.get(qualifName), indent
|
||||
+ overviewindent, overviewindent);
|
||||
}
|
||||
}
|
||||
}
|
||||
610
src/main/java/org/stfm/texdoclet/HTMLtoLaTeXBackEnd.java
Executable file
610
src/main/java/org/stfm/texdoclet/HTMLtoLaTeXBackEnd.java
Executable file
@@ -0,0 +1,610 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.image.MemoryImageSource;
|
||||
import java.awt.image.PixelGrabber;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.text.MutableAttributeSet;
|
||||
import javax.swing.text.html.HTML;
|
||||
import javax.swing.text.html.HTMLEditorKit;
|
||||
import javax.swing.text.html.parser.ParserDelegator;
|
||||
|
||||
import com.keypoint.PngEncoder;
|
||||
|
||||
/**
|
||||
* This class implements a <CODE>ParserCallback</CODE> that translates HTML to
|
||||
* the corresponding <TEX txt="\LaTeX{}">LaTeX</TEX>. Not all tags a processed
|
||||
* but the most common are.
|
||||
*
|
||||
* @see javax.swing.text.html.parser.ParserDelegator
|
||||
* @author Soeren Caspersen
|
||||
*/
|
||||
public class HTMLtoLaTeXBackEnd extends HTMLEditorKit.ParserCallback {
|
||||
|
||||
private static final String IMAGES_DIR = "texdoclet_images";
|
||||
|
||||
/**
|
||||
* Buffer containing the translated HTML.
|
||||
*/
|
||||
StringBuffer ret;
|
||||
|
||||
Stack tblstk = new Stack();
|
||||
TableInfo tblinfo;
|
||||
int verbat = 0;
|
||||
int colIdx = 0;
|
||||
Hashtable colors = new Hashtable(10);
|
||||
String block = "";
|
||||
String refurl = null;
|
||||
// S.M. modification : doNotPrintURL changed to doPrintURL
|
||||
String doPrintURL = null;
|
||||
String refname = null;
|
||||
String refimg = null;
|
||||
boolean notex = false;
|
||||
int imageindex = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param StringBuffer
|
||||
* The <CODE>StringBuffer</CODE> where the translated HTML is
|
||||
* appended.
|
||||
*/
|
||||
public HTMLtoLaTeXBackEnd(StringBuffer ret) {
|
||||
this.ret = ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles simple HTML tags (e.g. <CODE><HR></CODE>-tags).
|
||||
* It is called by the parser whenever such a tag is encountered.
|
||||
*/
|
||||
@Override
|
||||
public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attrSet,
|
||||
int pos) {
|
||||
String str = null;
|
||||
int i = 0;
|
||||
if (tag.toString().equalsIgnoreCase("tex")) {
|
||||
if (attrSet.containsAttribute(HTML.Attribute.ENDTAG, "true")) {
|
||||
notex = false;
|
||||
} else {
|
||||
String tex = (String) attrSet.getAttribute("txt");
|
||||
ret.append(tex);
|
||||
notex = true;
|
||||
}
|
||||
} else if (notex) {
|
||||
return;
|
||||
} else if (tag == HTML.Tag.META) {
|
||||
} else if (tag == HTML.Tag.HR) {
|
||||
String sz = (String) attrSet.getAttribute(HTML.Attribute.SIZE);
|
||||
int size = 1;
|
||||
if (sz != null) {
|
||||
size = Integer.parseInt(sz);
|
||||
}
|
||||
ret.append("\\mbox{}\\newline\\rule[2mm]{\\hsize}{"
|
||||
+ (1 * size * .5) + "mm}\\newline\n");
|
||||
} else if (tag == HTML.Tag.BR) {
|
||||
ret.append("\\mbox{}\\newline ");
|
||||
} else if (tag == HTML.Tag.IMG) {
|
||||
String refimg = (String) attrSet.getAttribute(HTML.Attribute.SRC);
|
||||
|
||||
// (S.M. modification) include images not in java source as link
|
||||
if (refimg.indexOf("://") != -1) {
|
||||
|
||||
// if (refimg.indexOf("http://") == 0) {
|
||||
// make link
|
||||
ret.append("(see image at "
|
||||
+ fixText("<a href=\"" + refimg + "\">" + refimg
|
||||
+ "</a>") + ")");
|
||||
// } else {
|
||||
// skip it
|
||||
// }
|
||||
|
||||
} else {
|
||||
|
||||
new File(IMAGES_DIR).mkdir();
|
||||
|
||||
double scale = 1.0;
|
||||
File imgF = new File(TeXDoclet.packageDir, refimg);
|
||||
if (!imgF.exists()) {
|
||||
ret.append("(image file not found)");
|
||||
return;
|
||||
}
|
||||
|
||||
String imgfile = new File(TeXDoclet.packageDir, refimg)
|
||||
.getAbsolutePath();
|
||||
|
||||
ImageIcon icn = new ImageIcon(imgfile);
|
||||
|
||||
int width = icn.getIconWidth();
|
||||
int height = icn.getIconHeight();
|
||||
|
||||
String sw = (String) attrSet.getAttribute(HTML.Attribute.WIDTH);
|
||||
String sh = (String) attrSet
|
||||
.getAttribute(HTML.Attribute.HEIGHT);
|
||||
|
||||
try {
|
||||
if (sw != null) {
|
||||
scale = NumberFormat.getPercentInstance().parse(sw)
|
||||
.doubleValue();
|
||||
} else if (sh != null) {
|
||||
scale = NumberFormat.getPercentInstance().parse(sh)
|
||||
.doubleValue();
|
||||
}
|
||||
} catch (ParseException er) {
|
||||
er.printStackTrace();
|
||||
}
|
||||
|
||||
Image img = icn.getImage();
|
||||
|
||||
PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height,
|
||||
true);
|
||||
try {
|
||||
pg.grabPixels();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(
|
||||
"interrupted waiting for pixels!");
|
||||
}
|
||||
int[] pixels = (int[]) pg.getPixels();
|
||||
img = Toolkit.getDefaultToolkit().createImage(
|
||||
new MemoryImageSource(width, height, pixels, 0, width));
|
||||
byte[] pngbytes;
|
||||
PngEncoder png = new PngEncoder(img, true);
|
||||
|
||||
String filnavn = IMAGES_DIR + "/pngimage" + imageindex++
|
||||
+ ".png";
|
||||
try {
|
||||
FileOutputStream outfile = new FileOutputStream(filnavn);
|
||||
pngbytes = png.pngEncode();
|
||||
if (pngbytes != null) {
|
||||
outfile.write(pngbytes);
|
||||
}
|
||||
outfile.flush();
|
||||
outfile.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (width * scale <= 800) {
|
||||
width *= scale * 0.5;
|
||||
height *= scale * 0.5;
|
||||
} else {
|
||||
scale = width * scale / 800;
|
||||
width *= 1.0 / scale * 0.5;
|
||||
height *= 1.0 / scale * 0.5;
|
||||
}
|
||||
|
||||
String fs = System.getProperty("file.separator");
|
||||
String filnavnFinal = (TeXDoclet.imagesPath == null ? ""
|
||||
: TeXDoclet.imagesPath
|
||||
+ (TeXDoclet.imagesPath.endsWith(fs) ? "" : fs))
|
||||
+ filnavn;
|
||||
|
||||
ret.append("\\mbox{\\includegraphics[width=" + width
|
||||
+ "pt, height=" + height + "pt]{" + filnavnFinal + "}}");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles HTML tags that mark a beginning (e.g.
|
||||
* <CODE><P></CODE>-tags). It is called by the parser whenever such a
|
||||
* tag is encountered.
|
||||
*/
|
||||
@Override
|
||||
public void handleStartTag(HTML.Tag tag, MutableAttributeSet attrSet,
|
||||
int pos) {
|
||||
String str = null;
|
||||
int i = 0;
|
||||
if (notex) {
|
||||
return;
|
||||
} else if (tag == HTML.Tag.PRE) {
|
||||
ret.append(TeXDoclet.TRUETYPE + "\\small\n\\mbox{}\\newline ");
|
||||
verbat++;
|
||||
} else if (tag == HTML.Tag.H1) {
|
||||
ret.append("\\chapter*{");
|
||||
} else if (tag == HTML.Tag.H2) {
|
||||
ret.append("\\section*{");
|
||||
} else if (tag == HTML.Tag.H3) {
|
||||
ret.append("\\subsection*{");
|
||||
} else if (tag == HTML.Tag.H4) {
|
||||
ret.append("\\subsubsection*{");
|
||||
} else if (tag == HTML.Tag.H5) {
|
||||
ret.append("\\subsubsection*{");
|
||||
} else if (tag == HTML.Tag.H6) {
|
||||
ret.append("\\subsubsection*{");
|
||||
} else if (tag == HTML.Tag.SUB) {
|
||||
ret.append("$_{");
|
||||
} else if (tag == HTML.Tag.SUP) {
|
||||
ret.append("$^{");
|
||||
// } else if (tag == HTML.Tag.HTML) {
|
||||
} else if (tag == HTML.Tag.HEAD) {
|
||||
} else if (tag == HTML.Tag.CENTER) {
|
||||
ret.append("\\makebox[\\hsize]{ ");
|
||||
} else if (tag == HTML.Tag.TITLE) {
|
||||
ret.append("\\chapter{");
|
||||
} else if (tag == HTML.Tag.FORM) {
|
||||
} else if (tag == HTML.Tag.INPUT) {
|
||||
} else if (tag == HTML.Tag.BODY) {
|
||||
} else if (tag == HTML.Tag.CODE) {
|
||||
ret.append(TeXDoclet.TRUETYPE + "\\small ");
|
||||
} else if (tag == HTML.Tag.TT) {
|
||||
ret.append(TeXDoclet.TRUETYPE + " ");
|
||||
} else if (tag == HTML.Tag.P) {
|
||||
ret.append("\n\n");
|
||||
} else if (tag == HTML.Tag.B) {
|
||||
ret.append("{\\bf ");
|
||||
} else if (tag == HTML.Tag.STRONG) {
|
||||
ret.append("{\\bf ");
|
||||
} else if (tag == HTML.Tag.A) {
|
||||
refurl = (String) attrSet.getAttribute(HTML.Attribute.HREF);
|
||||
// (S.M. modification)
|
||||
doPrintURL = (String) attrSet.getAttribute("doprinturl");
|
||||
if (refurl != null) {
|
||||
if (TeXDoclet.hyperref) {
|
||||
// if (refurl.toLowerCase().startsWith("doc-files")) {
|
||||
// File file = new File(TeXDoclet.packageDir, refurl);
|
||||
// if (file.exists()) {
|
||||
// if (TeXDoclet.appendencies.contains(file.getPath())) {
|
||||
// refurl = (String) TeXDoclet.appendencies
|
||||
// .get(file.getPath());
|
||||
// } else {
|
||||
// refurl = "appendix"
|
||||
// + new Integer(
|
||||
// TeXDoclet.appendencies.size() + 1);
|
||||
// TeXDoclet.appendencies.put(file.getPath(),
|
||||
// refurl);
|
||||
// }
|
||||
// ret.append("\\hyperref{}{" + refurl + "}{}{");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
String sharp = "";
|
||||
if (refurl.indexOf("#") >= 0) {
|
||||
sharp = refurl.substring(refurl.indexOf("#") + 1,
|
||||
refurl.length());
|
||||
if (sharp.indexOf("%") >= 0) {
|
||||
sharp = ""; // Don't know what to do with '%'
|
||||
}
|
||||
refurl = refurl.substring(0, refurl.indexOf("#"));
|
||||
}
|
||||
ret.append("\\hyperref{" + refurl + "}{" + sharp + "}{}{");
|
||||
// ret.append("\\href{" + refurl + "}{");
|
||||
} else {
|
||||
ret.append("{\\bf ");
|
||||
}
|
||||
} else {
|
||||
refname = (String) attrSet.getAttribute(HTML.Attribute.NAME);
|
||||
if (refname != null && TeXDoclet.hyperref) {
|
||||
ret.append("\\hyperdef{" + refname + "}{");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (tag == HTML.Tag.OL) {
|
||||
ret.append("\n\\begin{enumerate}");
|
||||
} else if (tag == HTML.Tag.DL) {
|
||||
ret.append("\n\\begin{itemize}");
|
||||
} else if (tag == HTML.Tag.LI) {
|
||||
ret.append("\n\\item{\\vskip -.8ex ");
|
||||
} else if (tag == HTML.Tag.DT) {
|
||||
ret.append("\\item[");
|
||||
} else if (tag == HTML.Tag.DD) {
|
||||
ret.append("{");
|
||||
} else if (tag == HTML.Tag.UL) {
|
||||
ret.append("\\begin{itemize}");
|
||||
} else if (tag == HTML.Tag.I) {
|
||||
ret.append(TeXDoclet.ITALIC + " ");
|
||||
} else if (tag == HTML.Tag.TABLE) {
|
||||
tblstk.push(tblinfo);
|
||||
tblinfo = new TableInfo();
|
||||
ret = tblinfo.startTable(ret, attrSet);
|
||||
} else if (tag == HTML.Tag.TH) {
|
||||
tblinfo.startHeadCol(attrSet);
|
||||
} else if (tag == HTML.Tag.TD) {
|
||||
tblinfo.startCol(attrSet);
|
||||
} else if (tag == HTML.Tag.TR) {
|
||||
tblinfo.startRow(attrSet);
|
||||
} else if (tag == HTML.Tag.FONT) {
|
||||
String sz = (String) attrSet.getAttribute(HTML.Attribute.SIZE);
|
||||
String col = (String) attrSet.getAttribute(HTML.Attribute.COLOR);
|
||||
ret.append("{");
|
||||
if (col != null) {
|
||||
if ("redgreenbluewhiteyellowblackcyanmagenta".indexOf(col) != -1) {
|
||||
ret.append("\\color{" + col + "}");
|
||||
} else {
|
||||
if ("abcdefABCDEF0123456789".indexOf(col.charAt(0)) != -1) {
|
||||
Color cc = new Color((int) Long.parseLong(col, 16));
|
||||
String name = (String) colors
|
||||
.get("color" + cc.getRGB());
|
||||
if (name == null) {
|
||||
ret.append("\\definecolor{color" + colIdx
|
||||
+ "}[rgb]{" + (cc.getRed() / 255.0) + ","
|
||||
+ (cc.getBlue() / 255.0) + ","
|
||||
+ (cc.getGreen() / 255.0) + "}");
|
||||
name = "color" + colIdx;
|
||||
colIdx++;
|
||||
colors.put("color" + cc.getRGB(), name);
|
||||
}
|
||||
ret.append("\\color{" + name + "}");
|
||||
++colIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles HTML tags that mark an ending (e.g.
|
||||
* <CODE></P></CODE>-tags). It is called by the parser whenever such a
|
||||
* tag is encountered.
|
||||
*/
|
||||
@Override
|
||||
public void handleEndTag(HTML.Tag tag, int pos) {
|
||||
int i = 0;
|
||||
|
||||
if (notex) {
|
||||
return;
|
||||
} else if (tag == HTML.Tag.PRE) {
|
||||
verbat--;
|
||||
ret.append("}\n");
|
||||
} else if (tag == HTML.Tag.H1) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.H2) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.H3) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.H4) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.H5) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.H6) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.SUB) {
|
||||
ret.append("}$");
|
||||
} else if (tag == HTML.Tag.SUP) {
|
||||
ret.append("}$");
|
||||
// } else if (tag == HTML.Tag.HTML) {
|
||||
} else if (tag == HTML.Tag.HEAD) {
|
||||
} else if (tag == HTML.Tag.CENTER) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.TITLE) {
|
||||
ret.append("}{");
|
||||
} else if (tag == HTML.Tag.FORM) {
|
||||
} else if (tag == HTML.Tag.INPUT) {
|
||||
} else if (tag == HTML.Tag.BODY) {
|
||||
} else if (tag == HTML.Tag.CODE) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.TT) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.P) {
|
||||
} else if (tag == HTML.Tag.B) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.STRONG) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.A) {
|
||||
if (refurl != null) {
|
||||
ret.append("}");
|
||||
// S.M. modification : doPrintURL must be set instead of
|
||||
// doNotPrintUrl
|
||||
if (doPrintURL != null) {
|
||||
if (!refurl.equals("")) {
|
||||
ret.append("(at ");
|
||||
ret.append(fixText(refurl));
|
||||
ret.append(")");
|
||||
}
|
||||
}
|
||||
} else if (refname != null) {
|
||||
ret.append("}");
|
||||
}
|
||||
|
||||
} else if (tag == HTML.Tag.LI) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.DT) {
|
||||
ret.append("]");
|
||||
} else if (tag == HTML.Tag.DD) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.DL) {// /
|
||||
ret.append("\n\\end{itemize}\n");
|
||||
} else if (tag == HTML.Tag.OL) {
|
||||
ret.append("\n\\end{enumerate}\n");
|
||||
} else if (tag == HTML.Tag.UL) {
|
||||
ret.append("\n\\end{itemize}\n");
|
||||
} else if (tag == HTML.Tag.I) {
|
||||
ret.append("}");
|
||||
} else if (tag == HTML.Tag.TABLE) {
|
||||
ret = tblinfo.endTable();
|
||||
tblinfo = (TableInfo) tblstk.pop();
|
||||
} else if (tag == HTML.Tag.TH) {
|
||||
tblinfo.endCol();
|
||||
} else if (tag == HTML.Tag.TD) {
|
||||
tblinfo.endCol();
|
||||
} else if (tag == HTML.Tag.TR) {
|
||||
tblinfo.endRow();
|
||||
} else if (tag == HTML.Tag.FONT) {
|
||||
ret.append("}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles all other text.
|
||||
*/
|
||||
@Override
|
||||
public void handleText(char[] data, int pos) {
|
||||
String str = new String(data);
|
||||
for (int i = 0; i < str.length(); ++i) {
|
||||
int c = str.charAt(i);
|
||||
if (notex) {
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case 160: //
|
||||
ret.append("\\phantom{ }");
|
||||
break;
|
||||
case ' ':
|
||||
if (verbat > 0) {
|
||||
ret.append("\\phantom{ }");
|
||||
} else {
|
||||
ret.append(' ');
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\lbrack\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\lbrack ");
|
||||
}
|
||||
break;
|
||||
case ']':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\rbrack\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\rbrack ");
|
||||
}
|
||||
break;
|
||||
case '_':
|
||||
case '%':
|
||||
case '$':
|
||||
case '#':
|
||||
case '}':
|
||||
case '{':
|
||||
case '&':
|
||||
ret.append('\\');
|
||||
ret.append((char) c);
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\ ");
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
// case 'æ':
|
||||
case '¾':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\ae\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\ae ");
|
||||
}
|
||||
break;
|
||||
// case 'Æ':
|
||||
case '®':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\AE\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\AE ");
|
||||
}
|
||||
break;
|
||||
// case 'å':
|
||||
case 'Œ':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\aa\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\aa ");
|
||||
}
|
||||
break;
|
||||
// case 'Å':
|
||||
case '<27>':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\AA\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\AA ");
|
||||
}
|
||||
break;
|
||||
// case 'ø':
|
||||
case '¿':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\o\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\o ");
|
||||
}
|
||||
break;
|
||||
// case 'Ø':
|
||||
case '¯':
|
||||
if (i < str.length() - 1 && str.charAt(i + 1) == ' ') {
|
||||
ret.append("\\O\\ ");
|
||||
i++;
|
||||
} else {
|
||||
ret.append("\\O ");
|
||||
}
|
||||
break;
|
||||
case '^':
|
||||
ret.append("$\\wedge$");
|
||||
break;
|
||||
case '<':
|
||||
ret.append("\\textless ");
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
if (tblstk.size() > 0) {
|
||||
// Swallow new lines while tables are in progress,
|
||||
// <tr> controls new line emission.
|
||||
if (verbat > 0) {
|
||||
ret.append("}\\mbox{}\\newline\n" + TeXDoclet.TRUETYPE
|
||||
+ "\\small ");
|
||||
} else {
|
||||
ret.append(" ");
|
||||
}
|
||||
} else {
|
||||
if (verbat > 0) {
|
||||
ret.append("}\\mbox{}\\newline\n" + TeXDoclet.TRUETYPE
|
||||
+ "\\small ");
|
||||
} else if ((i + 1) < str.length()
|
||||
&& str.charAt(i + 1) == 10) {
|
||||
ret.append("\\bl ");
|
||||
++i;
|
||||
} else {
|
||||
ret.append((char) c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
ret.append("/");
|
||||
break;
|
||||
case '>':
|
||||
ret.append("\\textgreater ");
|
||||
break;
|
||||
case '\\':
|
||||
ret.append("\\textbackslash ");
|
||||
break;
|
||||
default:
|
||||
ret.append((char) c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a HTML string into <TEX txt="\LaTeX{}">LaTeX</TEX> using an
|
||||
* instance of <CODE>HTMLtoLaTeXBackEnd</CODE>.
|
||||
*
|
||||
* @returns The converted string.
|
||||
*/
|
||||
public static String fixText(String str) {
|
||||
// System.out.println("fixText: " + str);
|
||||
StringBuffer result = new StringBuffer(str.length());
|
||||
HTMLtoLaTeXBackEnd b = new HTMLtoLaTeXBackEnd(result);
|
||||
Reader reader = new StringReader(str);
|
||||
try {
|
||||
new ParserDelegator().parse(reader, b, false);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
}
|
||||
84
src/main/java/org/stfm/texdoclet/HelpOutput.java
Normal file
84
src/main/java/org/stfm/texdoclet/HelpOutput.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
public class HelpOutput {
|
||||
|
||||
protected static void printHelp() {
|
||||
System.err.println("TeXDoclet Usage:");
|
||||
System.err
|
||||
.println("-title <title> A title to use for the generated output document.");
|
||||
// (S.M. modification)
|
||||
System.err
|
||||
.println("-subtitle <title> A subtitle for the output document.");
|
||||
System.err
|
||||
.println(" No -title will result in no title page.");
|
||||
System.err
|
||||
.println("-output <outfile> Specifies the output file to write to. If none");
|
||||
System.err
|
||||
.println(" specified, the default is docs.tex in the current");
|
||||
System.err.println(" directory.");
|
||||
System.err
|
||||
.println("-docclass <class> LaTeX2e document class, `report' is the default.");
|
||||
System.err
|
||||
.println("-doctype <type> LaTeX2e document style, `headings' is the default.");
|
||||
System.err
|
||||
.println("-classfilter <name> The name of a class implementing the ClassFilter interface.");
|
||||
System.err
|
||||
.println("-date <date string> The value to use for the document date.");
|
||||
System.err
|
||||
.println("-author <author> Specifies string to use for document Author.");
|
||||
System.err
|
||||
.println("-texinit <file> LaTeX2e statements included before \\begin{document}.");
|
||||
System.err
|
||||
.println("-texsetup <file> LaTeX2e statements included after \\begin{document} \\maketitle (if title was specified).");
|
||||
System.err
|
||||
.println("-texintro <file> LaTeX2e statements included after table of contents");
|
||||
System.err
|
||||
.println("-texfinish <file> LaTeX2e statements included before \\end{document}.");
|
||||
System.err
|
||||
.println("-texpackage <file> LaTeX2e statements included before packages' \\chapter.");
|
||||
System.err
|
||||
.println("-setup <file> A setup file included before \\begin{document}.");
|
||||
System.err.println("-twosided Print twosided.");
|
||||
System.err
|
||||
.println("-serial Do print Serializable information.");
|
||||
System.err
|
||||
.println("-nosummaries Do print summaries of fiels, constructors and methods.");
|
||||
// (S.M. modification)
|
||||
System.err
|
||||
.println("-nofieldsummary Do not print field summaries");
|
||||
// (S.M. modification)
|
||||
System.err
|
||||
.println("-noconstructorsummary Do not print constructor summaries");
|
||||
System.err
|
||||
.println("-noinherited Do not include inherited API information in output.");
|
||||
// (S.M. modification)
|
||||
System.err
|
||||
.println("-shortinherited Prints a short inheritance, only the member name (not the whole signature)");
|
||||
System.err.println("-noindex Do not create index.");
|
||||
// (S.M. modification) System.err.println(
|
||||
// "-notree Do not create a class tree." );
|
||||
// no class tree is default
|
||||
System.err.println("-tree Create a class tree.");
|
||||
System.err
|
||||
.println("-treeindent <float> Indent <float>cm i the class tree. Default is 1cm.");
|
||||
System.err
|
||||
.println("-hyperref Use the hyperref package.");
|
||||
System.err
|
||||
.println("-pdfhyperref Use the hyperref package with pdf. Overrides -hypertex ");
|
||||
System.err.println("-version Includes version-tags ");
|
||||
// ----- (S.M. modification)
|
||||
|
||||
System.err
|
||||
.println("-hr Prints horizontal rows in the output (to get a better? view)");
|
||||
System.err
|
||||
.println("-include Creates output without latex initiation (writes it in initdocsinclude.tex), titlepage, contents ");
|
||||
System.err
|
||||
.println("-sectionlevel <level> Specifies the highest level of sections (either \"subsection\", \"section\" or \"chapter\")");
|
||||
System.err
|
||||
.println("-imagespath Path to the texdoclet_images dir (absolute or relative to the output document .tex file).");
|
||||
|
||||
// ----- (S.M. modification end)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
80
src/main/java/org/stfm/texdoclet/InterfaceHierachy.java
Executable file
80
src/main/java/org/stfm/texdoclet/InterfaceHierachy.java
Executable file
@@ -0,0 +1,80 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.RootDoc;
|
||||
|
||||
/**
|
||||
* Manages and prints a interface hierarchy. Use <CODE>add</CODE> to add another
|
||||
* interface to the hierarchy. Use <CODE>printTree</CODE> to print the
|
||||
* corresponding <TEX txt="\LaTeX{}">LaTeX</TEX>.
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
* @author Soeren Caspersen - XO Software
|
||||
*/
|
||||
public class InterfaceHierachy extends java.lang.Object {
|
||||
|
||||
public SortedMap root = new TreeMap();
|
||||
|
||||
/**
|
||||
* Creates new InterfaceHierachy
|
||||
*/
|
||||
public InterfaceHierachy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another interface to the hierachy
|
||||
*/
|
||||
protected SortedMap add(ClassDoc cls) {
|
||||
SortedMap temp;
|
||||
if (cls.interfaces().length > 0) {
|
||||
temp = add(cls.interfaces()[0]);
|
||||
} else {
|
||||
temp = root;
|
||||
}
|
||||
|
||||
SortedMap result = (SortedMap) temp.get(cls.qualifiedName());
|
||||
if (result == null) {
|
||||
result = new TreeMap();
|
||||
temp.put(cls.qualifiedName(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the <TEX txt="\LaTeX{}">LaTeX</TEX> corresponding to the tree. The
|
||||
* tree is printed using <CODE>TeXDoclet.os</CODE>.
|
||||
*/
|
||||
public void printTree(RootDoc rootDoc, double overviewindent) {
|
||||
printBranch(rootDoc, root, 0, overviewindent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a branch of the tree. The branch is printed using
|
||||
* <CODE>TeXDoclet.os</CODE>.
|
||||
*/
|
||||
protected void printBranch(RootDoc rootDoc, SortedMap map, double indent,
|
||||
double overviewindent) {
|
||||
Set set = map.keySet();
|
||||
Iterator it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
String qualifName = (String) it.next();
|
||||
ClassDoc cls = rootDoc.classNamed(qualifName);
|
||||
TeXDoclet.os.print("\\hspace{" + Double.toString(indent)
|
||||
+ "cm} $\\bullet$ "
|
||||
+ HTMLtoLaTeXBackEnd.fixText(qualifName) + " {\\tiny ");
|
||||
// (S.M. modification) only for resolved classes
|
||||
if (cls != null) {
|
||||
TeXDoclet.printRef(cls.containingPackage(), cls.name(), "");
|
||||
}
|
||||
TeXDoclet.os.println("} \\\\");
|
||||
printBranch(rootDoc, (SortedMap) map.get(qualifName), indent
|
||||
+ overviewindent, overviewindent);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
98
src/main/java/org/stfm/texdoclet/Package.java
Executable file
98
src/main/java/org/stfm/texdoclet/Package.java
Executable file
@@ -0,0 +1,98 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Vector;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
import com.sun.javadoc.PackageDoc;
|
||||
|
||||
/**
|
||||
* This class is used to manage the contents of a Java package. It accepts
|
||||
* ClassDoc objects and examines them and groups them according to whether they
|
||||
* are classes, interfaces, exceptions or errors. The accumulated Vectors can
|
||||
* then be processed to get to all of the elements of the package that fall into
|
||||
* each category. If needed the classes, interfaces, exceptions and errors can
|
||||
* be sorted using the <CODE>sort</CODE> method.
|
||||
*
|
||||
* @see #sort
|
||||
* @version $Revision: 1.1 $
|
||||
* @author Gregg Wonderly - C2 Technologies Inc.
|
||||
*/
|
||||
public class Package {
|
||||
|
||||
protected PackageDoc pkgDoc;
|
||||
/** The name of the package this object is for */
|
||||
protected String pkg;
|
||||
/** The classes this package has in it */
|
||||
protected Vector classes;
|
||||
/** The interfaces this package has in it */
|
||||
protected Vector interfaces;
|
||||
/** The exceptions this package has in it */
|
||||
protected Vector exceptions;
|
||||
/** The errors this package has in it */
|
||||
protected Vector errors;
|
||||
|
||||
/**
|
||||
* Construct a new object corresponding to the passed package name.
|
||||
*
|
||||
* @param pkg
|
||||
* the package name to use
|
||||
*/
|
||||
public Package(String pkg, PackageDoc doc) {
|
||||
pkgDoc = doc;
|
||||
this.pkg = pkg;
|
||||
if (pkg.equals("")) {
|
||||
this.pkg = "<none>";
|
||||
}
|
||||
classes = new Vector();
|
||||
interfaces = new Vector();
|
||||
exceptions = new Vector();
|
||||
errors = new Vector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ClassDoc element to this package.
|
||||
*
|
||||
* @param cd
|
||||
* the object to add to this package
|
||||
*/
|
||||
public void addElement(ClassDoc cd) {
|
||||
if (cd.isInterface()) {
|
||||
interfaces.addElement(cd);
|
||||
} else if (cd.isClass()) {
|
||||
if (cd.isException()) {
|
||||
exceptions.addElement(cd);
|
||||
} else if (cd.isError()) {
|
||||
errors.addElement(cd);
|
||||
} else {
|
||||
classes.addElement(cd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the vectors of classes, interfaces exceptions and errors.
|
||||
*/
|
||||
public void sort() {
|
||||
|
||||
Comparator comp = new Comparator() {
|
||||
@Override
|
||||
public int compare(Object o1, Object o2) {
|
||||
ClassDoc cls1 = (ClassDoc) o1;
|
||||
ClassDoc cls2 = (ClassDoc) o2;
|
||||
return cls1.name().compareToIgnoreCase(cls2.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Collections.sort(classes, comp);
|
||||
Collections.sort(interfaces, comp);
|
||||
Collections.sort(exceptions, comp);
|
||||
Collections.sort(errors, comp);
|
||||
}
|
||||
}
|
||||
338
src/main/java/org/stfm/texdoclet/TableInfo.java
Executable file
338
src/main/java/org/stfm/texdoclet/TableInfo.java
Executable file
@@ -0,0 +1,338 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.swing.text.MutableAttributeSet;
|
||||
import javax.swing.text.html.HTML;
|
||||
|
||||
/**
|
||||
* This class provides support for converting HTML tables into <TEX
|
||||
* txt="\LaTeX{}">LaTeX</TEX> tables. Some of the things <b>NOT</b> implemented
|
||||
* include the following:
|
||||
* <ul>
|
||||
* <li>valign attributes are not processed, but align= is.
|
||||
* <li>rowspan attributes are not processed, but colspan= is.
|
||||
* <li>the argument to border= in the table tag is not used to control line size
|
||||
* </ul>
|
||||
* <br>
|
||||
* Here is an example table.
|
||||
* <p>
|
||||
* <table border bgcolor="#AAAAAA">
|
||||
* <tr>
|
||||
* <th>Column 1 Heading
|
||||
* <th>Column two heading
|
||||
* <th>Column three heading
|
||||
* <tr>
|
||||
* <td>data
|
||||
* <td colspan=2>Span two columns
|
||||
* <tr>
|
||||
* <td><i>more data</i>
|
||||
* <td align=right>right
|
||||
* <td align=left>left
|
||||
* <tr>
|
||||
* <td colspan=3>
|
||||
* <table border=5 bgcolor="#CCCCCC">
|
||||
* <tr>
|
||||
* <th colspan=3>A nested table example
|
||||
* <tr>
|
||||
* <th>Column 1 Heading</th>
|
||||
* <th>Coludliadfuapfd a fia fopia foipapio dupoau foapoifd pdpfiu apsd
|
||||
* oipoioaofiduaopiufopiiiiiiiiiimn two heading</th>
|
||||
* <th>Column three heading</th>
|
||||
* <tr>
|
||||
* <td>data</td>
|
||||
* <td colspan=2>Span two columns</td>
|
||||
* <tr>
|
||||
* <td><i>more data</i></td>
|
||||
* <td align=right>right</td>
|
||||
* <td align=left>left</td>
|
||||
* <tr>
|
||||
* <td>
|
||||
*
|
||||
* <pre>
|
||||
* 1
|
||||
* 2
|
||||
* 3
|
||||
* 4
|
||||
* </pre>
|
||||
*
|
||||
* </td>
|
||||
* <td>
|
||||
*
|
||||
* <pre>
|
||||
* first line
|
||||
* second line
|
||||
* third line
|
||||
* fourth line
|
||||
* </pre>
|
||||
*
|
||||
* </td>
|
||||
* </table>
|
||||
* </table>
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
* @author Gregg Wonderly - C2 Technologies Inc.
|
||||
*/
|
||||
public class TableInfo {
|
||||
|
||||
private StringBuffer originalBuffer;
|
||||
private StringBuffer ret;
|
||||
|
||||
private int colcnt = 0;
|
||||
private int rowcnt = 0;
|
||||
private int totalcolcnt = 0;
|
||||
private boolean border = false;
|
||||
private Properties props;
|
||||
private int bordwid;
|
||||
private boolean parboxed;
|
||||
private double red = -1.0;
|
||||
private double blue = -1.0;
|
||||
private double green = -1.0;
|
||||
static int tblcnt;
|
||||
int tblno;
|
||||
String tc;
|
||||
|
||||
HTML.Tag lastTag;
|
||||
|
||||
int hasNumAttr(HTML.Attribute attr, MutableAttributeSet attrSet) {
|
||||
String val = (String) attrSet.getAttribute(attr);
|
||||
if (val == null) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(val);
|
||||
} catch (Exception ex) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new table object and starts processing of the table by
|
||||
* scanning the <code><table></code> passed to count columns.
|
||||
*
|
||||
* @param p
|
||||
* properties found on the <code><table></code> tag
|
||||
* @param ret
|
||||
* the result buffer that will contain the output
|
||||
* @param table
|
||||
* the input string that has the entire table definition in it.
|
||||
* @param off
|
||||
* the offset into <code><table></code> where scanning
|
||||
* should start
|
||||
*/
|
||||
public StringBuffer startTable(StringBuffer org, MutableAttributeSet attrSet) {
|
||||
originalBuffer = org;
|
||||
ret = new StringBuffer();
|
||||
|
||||
tblno = tblcnt++;
|
||||
tc = "" + (char) ('a' + (tblno / (26 * 26)))
|
||||
+ (char) ((tblno / 26) + 'a') + (char) ((tblno % 26) + 'a');
|
||||
|
||||
String val = (String) attrSet.getAttribute(HTML.Attribute.BORDER);
|
||||
border = false;
|
||||
if (val != null) {
|
||||
border = true;
|
||||
bordwid = 2;
|
||||
if (val.equals("") == false) {
|
||||
try {
|
||||
bordwid = Integer.parseInt(val);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
if (bordwid == 0) {
|
||||
border = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
String bgcolor = (String) attrSet.getAttribute(HTML.Attribute.BGCOLOR);
|
||||
if (bgcolor != null) {
|
||||
try {
|
||||
if (bgcolor.length() != 7 && bgcolor.charAt(0) == '#') {
|
||||
throw new NumberFormatException();
|
||||
}
|
||||
red = Integer.decode("#" + bgcolor.substring(1, 3))
|
||||
.doubleValue();
|
||||
blue = Integer.decode("#" + bgcolor.substring(3, 5))
|
||||
.doubleValue();
|
||||
green = Integer.decode("#" + bgcolor.substring(5, 7))
|
||||
.doubleValue();
|
||||
red /= 255.0;
|
||||
blue /= 255.0;
|
||||
green /= 255.0;
|
||||
} catch (NumberFormatException e) {
|
||||
red = 1.0;
|
||||
blue = 1.0;
|
||||
green = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the table, closing the last row as needed
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX>
|
||||
* into.
|
||||
*/
|
||||
public StringBuffer endTable() {
|
||||
originalBuffer.append("\n% Table #" + tblno + "\n");
|
||||
int col = totalcolcnt;
|
||||
if (col == 0) {
|
||||
col = 1;
|
||||
}
|
||||
for (int i = 0; i < col; ++i) {
|
||||
String cc = "" + (char) ('a' + (i / (26 * 26)))
|
||||
+ (char) ((i / 26) + 'a') + (char) ((i % 26) + 'a');
|
||||
originalBuffer.append("\\newlength{\\tbl" + tc + "c" + cc + "w}\n");
|
||||
// originalBuffer.append("\\setlength{\\tbl"+tc+"c"+cc+"w}{"+(1.0/col)+"\\hsize}\n");
|
||||
originalBuffer.append("\\setlength{\\tbl" + tc + "c" + cc + "w}{"
|
||||
+ (1.0 / col) + "\\linewidth}\n");
|
||||
}
|
||||
if (red != -1.0 && green != -1.0 && blue != -1.0) {
|
||||
originalBuffer.append("\\colorbox[rgb]{" + Double.toString(red)
|
||||
+ "," + Double.toString(blue) + ","
|
||||
+ Double.toString(green) + "}{");
|
||||
}
|
||||
originalBuffer.append("\\begin{tabular}{");
|
||||
if (border) {
|
||||
originalBuffer.append("|");
|
||||
}
|
||||
for (int i = 0; i < col; ++i) {
|
||||
String cc = "" + (char) ('a' + (i / (26 * 26)))
|
||||
+ (char) ((i / 26) + 'a') + (char) ((i % 26) + 'a');
|
||||
originalBuffer.append("p{\\tbl" + tc + "c" + cc + "w}");
|
||||
if (border) {
|
||||
originalBuffer.append("|");
|
||||
}
|
||||
}
|
||||
originalBuffer.append("}\n");
|
||||
|
||||
// Append the cached table
|
||||
originalBuffer.append(ret);
|
||||
|
||||
originalBuffer.append("\\end{tabular}\n");
|
||||
if (red != -1.0 && green != -1.0 && blue != -1.0) {
|
||||
originalBuffer.append("}\n");
|
||||
}
|
||||
|
||||
return originalBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new column, possibly closing the current column if needed
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX>
|
||||
* into.
|
||||
* @param p
|
||||
* the properties from the <code><td></code> tag
|
||||
*/
|
||||
public void startCol(MutableAttributeSet attrSet) {
|
||||
int span = hasNumAttr(HTML.Attribute.COLSPAN, attrSet);
|
||||
if (colcnt > 0) {
|
||||
ret.append(" & ");
|
||||
}
|
||||
String align = (String) attrSet.getAttribute(HTML.Attribute.ALIGN);
|
||||
if (align != null && span < 0) {
|
||||
span = 1;
|
||||
}
|
||||
if (span > 0) {
|
||||
ret.append("\\multicolumn{" + span + "}{");
|
||||
if (border && colcnt == 0) {
|
||||
ret.append("|");
|
||||
}
|
||||
String cc = "" + (char) ('a' + (colcnt / (26 * 26)))
|
||||
+ (char) ((colcnt / 26) + 'a')
|
||||
+ (char) ((colcnt % 26) + 'a');
|
||||
if (align != null) {
|
||||
String h = align.substring(0, 1);
|
||||
if ("rR".indexOf(h) >= 0) {
|
||||
ret.append("r");
|
||||
} else if ("lL".indexOf(h) >= 0) {
|
||||
ret.append("p{\\tbl" + tc + "c" + cc + "w}");
|
||||
} else if ("cC".indexOf(h) >= 0) {
|
||||
ret.append("p{\\tbl" + tc + "c" + cc + "w}");
|
||||
}
|
||||
} else {
|
||||
ret.append("p{\\tbl" + tc + "c" + cc + "w}");
|
||||
}
|
||||
if (border) {
|
||||
ret.append("|");
|
||||
}
|
||||
ret.append("}");
|
||||
}
|
||||
String wid = (String) attrSet.getAttribute("texwidth");
|
||||
ret.append("{");
|
||||
if (wid != null) {
|
||||
ret.append("\\parbox{" + wid + "}{\\vskip 1ex ");
|
||||
parboxed = true;
|
||||
}
|
||||
colcnt++;
|
||||
totalcolcnt = totalcolcnt > colcnt ? totalcolcnt : colcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new Heading column, possibly closing the current column if
|
||||
* needed. A Heading column has a Bold Face font directive around it.
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX>
|
||||
* into.
|
||||
* @param p
|
||||
* The properties from the <code><th></code> tag
|
||||
*/
|
||||
public void startHeadCol(MutableAttributeSet attrSet) {
|
||||
startCol(attrSet);
|
||||
ret.append("\\bf ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the current column.
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX>
|
||||
* into.
|
||||
*/
|
||||
public void endCol() {
|
||||
if (parboxed) {
|
||||
ret.append("\\vskip 1ex}");
|
||||
}
|
||||
parboxed = false;
|
||||
ret.append("}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new row, possibly closing the current row if needed
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeX{}">LaTeX</TEX> into.
|
||||
* @param p
|
||||
* The properties from the <code><tr></code> tag
|
||||
*/
|
||||
public void startRow(MutableAttributeSet attrSet) {
|
||||
if (rowcnt == 0) {
|
||||
if (border) {
|
||||
ret.append(" \\hline ");
|
||||
}
|
||||
}
|
||||
colcnt = 0;
|
||||
++rowcnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the current row.
|
||||
*
|
||||
* @param ret
|
||||
* The output buffer to put <TEX txt="\LaTeXe{}">LaTeX2e</TEX>
|
||||
* into.
|
||||
*/
|
||||
public void endRow() {
|
||||
ret.append(" \\\\");
|
||||
if (border) {
|
||||
ret.append(" \\hline");
|
||||
}
|
||||
ret.append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
2321
src/main/java/org/stfm/texdoclet/TeXDoclet.java
Executable file
2321
src/main/java/org/stfm/texdoclet/TeXDoclet.java
Executable file
File diff suppressed because it is too large
Load Diff
20
src/main/java/org/stfm/texdoclet/TestFilter.java
Executable file
20
src/main/java/org/stfm/texdoclet/TestFilter.java
Executable file
@@ -0,0 +1,20 @@
|
||||
package org.stfm.texdoclet;
|
||||
|
||||
import com.sun.javadoc.ClassDoc;
|
||||
|
||||
/**
|
||||
* This class filters out classes beginning with "Test" when applied to the
|
||||
* Doclet.
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
public class TestFilter implements ClassFilter {
|
||||
|
||||
/**
|
||||
* Returns false if class name starts with "Test".
|
||||
*/
|
||||
@Override
|
||||
public boolean includeClass(ClassDoc cd) {
|
||||
return !cd.name().startsWith("Test");
|
||||
}
|
||||
}
|
||||
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.gif
Normal file
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.jpg
Executable file
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.jpg
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.png
Normal file
BIN
src/main/java/org/stfm/texdoclet/doc-files/texdoclet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
6
src/main/java/org/stfm/texdoclet/package.html
Executable file
6
src/main/java/org/stfm/texdoclet/package.html
Executable file
@@ -0,0 +1,6 @@
|
||||
<BODY>
|
||||
This doclet is based on the doclet originally created by Greg Wonderly of
|
||||
<A href=http://www.c2-tech.com>C2 technologies Inc.</A> and its revision by
|
||||
<A HREF=http://www.xosoftware.dk>XO Software</A>. The project of Greg Wonderly is available here :
|
||||
<A href=http://java.net/projects/texdoclet>http://java.net/projects/texdoclet</A>.
|
||||
</BODY>
|
||||
Reference in New Issue
Block a user