提交 31ed2e1e authored 作者: Thomas Mueller's avatar Thomas Mueller

HTML railroad diagrams

上级 c4ae4586
......@@ -24,9 +24,14 @@ Data Types
<c:forEach var="item" items="dataTypes">
<h3 id="${item.link}" class="notranslate">${item.topic}</h3>
<!-- railroad-start -->
${item.railroad}
<!-- railroad-end -->
<!-- syntax-start
<pre>
${item.syntax}
</pre>
syntax-end -->
<p>${item.text}</p>
<b>Example:</b>
<p class="notranslate">${item.example}</p>
......
......@@ -54,9 +54,14 @@ Functions
<c:forEach var="item" items="functionsAll">
<h3 id="${item.link}" class="notranslate">${item.topic}</h3>
<!-- railroad-start -->
${item.railroad}
<!-- railroad-end -->
<!-- syntax-start
<pre>
${item.syntax}
</pre>
syntax-end -->
<p>${item.text}</p>
<b>Example:</b>
<p class="notranslate">${item.example}</p>
......
......@@ -52,9 +52,14 @@ SQL Grammar
<c:forEach var="item" items="commands">
<h3 id="${item.link}" class="notranslate">${item.topic}</h3>
<!-- railroad-start -->
${item.railroad}
<!-- railroad-end -->
<!-- syntax-start
<pre>
${item.syntax}
</pre>
syntax-end -->
<p>${item.text}</p>
<b>Example:</b>
<p class="notranslate">${item.example}</p>
......@@ -62,9 +67,14 @@ ${item.syntax}
<c:forEach var="item" items="otherGrammar">
<h3 id="${item.link}" class="notranslate">${item.topic}</h3>
<!-- railroad-start -->
${item.railroad}
<!-- railroad-end -->
<!-- syntax-start
<pre>
${item.syntax}
</pre>
syntax-end -->
<p>${item.text}</p>
<b>Example:</b>
<p class="notranslate">${item.example}</p>
......
......@@ -210,3 +210,90 @@ td.content {
.compareN {
color: #800;
}
.railroad {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
}
.c {
padding: 1px 3px;
margin: 0px 0px;
border: 2px solid;
-moz-border-radius: 0.4em;
border-radius: 0.4em;
background-color: #fff;
}
.ts {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ts.png);
width: 16px;
}
.ls {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ls.png);
width: 16px;
}
.ks {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ks.png);
width: 16px;
}
.te {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-te.png);
width: 16px;
}
.le {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-le.png);
width: 16px;
}
.ke {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ke.png);
width: 16px;
}
.d {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-d.png);
background-repeat: repeat-x;
min-width: 16px;
}
......@@ -127,3 +127,90 @@ em.u {
.compareN {
color: #800;
}
.railroad {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
}
.c {
padding: 1px 3px;
margin: 0px 0px;
border: 2px solid;
-moz-border-radius: 0.4em;
border-radius: 0.4em;
background-color: #fff;
}
.ts {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ts.png);
width: 16px;
}
.ls {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ls.png);
width: 16px;
}
.ks {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ks.png);
width: 16px;
}
.te {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-te.png);
width: 16px;
}
.le {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-le.png);
width: 16px;
}
.ke {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-ke.png);
width: 16px;
}
.d {
border: 0px;
padding: 0px;
margin: 0px;
border-collapse: collapse;
vertical-align: top;
height: 24px;
background-image: url(images/div-d.png);
background-repeat: repeat-x;
min-width: 16px;
}
......@@ -8120,7 +8120,7 @@ Bugfixes
Page store: new storage mechanism
@roadmap_1009_li
[Requires page store] Support large updates (use the transaction log for rollback).
[Requires page store] Support large updates (use the transaction log for rollback instead of persistent UndoLog.file).
@roadmap_1010_li
[Requires page store] Shutdown compact
......
......@@ -8120,7 +8120,7 @@ H2 コンソール アプリケーション
#Page store: new storage mechanism
@roadmap_1009_li
#[Requires page store] Support large updates (use the transaction log for rollback).
#[Requires page store] Support large updates (use the transaction log for rollback instead of persistent UndoLog.file).
@roadmap_1010_li
#[Requires page store] Shutdown compact
......
......@@ -2705,7 +2705,7 @@ roadmap_1005_li=Enable the system property h2.pageStore by default.
roadmap_1006_h2=Priority 1
roadmap_1007_li=Bugfixes
roadmap_1008_li=Page store\: new storage mechanism
roadmap_1009_li=[Requires page store] Support large updates (use the transaction log for rollback).
roadmap_1009_li=[Requires page store] Support large updates (use the transaction log for rollback instead of persistent UndoLog.file).
roadmap_1010_li=[Requires page store] Shutdown compact
roadmap_1011_li=More tests with MULTI_THREADED\=1
roadmap_1012_li=RECOVER\=1 should automatically recover, \=2 should run the recovery tool if required
......
......@@ -31,6 +31,11 @@ import org.h2.util.StringUtils;
public class Bnf {
private final Random random = new Random();
/**
* The rule map. The key is lowercase, and all spaces
* are replaces with underscore.
*/
private final HashMap<String, RuleHead> ruleMap = New.hashMap();
private String syntax;
private String currentToken;
......@@ -68,10 +73,11 @@ public class Bnf {
private RuleHead addRule(String topic, String section, Rule rule) {
RuleHead head = new RuleHead(section, topic, rule);
if (ruleMap.get(StringUtils.toLowerEnglish(topic)) != null) {
String key = StringUtils.toLowerEnglish(topic.trim().replace(' ', '_'));
if (ruleMap.get(key) != null) {
throw new AssertionError("already exists: " + topic);
}
ruleMap.put(StringUtils.toLowerEnglish(topic), head);
ruleMap.put(key, head);
return head;
}
......@@ -88,9 +94,7 @@ public class Bnf {
if (section.startsWith("System")) {
continue;
}
String topic = StringUtils.toLowerEnglish(rs.getString("TOPIC").trim());
topic = StringUtils.replaceAll(topic, " ", "_");
// topic = StringUtils.replaceAll(topic, "_", "");
String topic = rs.getString("TOPIC");
syntax = rs.getString("SYNTAX").trim();
currentTopic = section;
if (section.startsWith("Function")) {
......@@ -131,6 +135,32 @@ public class Bnf {
addFixedRule("@digit@", RuleFixed.DIGIT);
}
/**
* Get the HTML railroad for a given syntax.
*
* @param syntax the syntax
* @return the HTML formatted railroad
*/
public String getRailroadHtml(String syntax) {
syntax = StringUtils.replaceAll(syntax, "\n ", " ");
String[] syntaxList = StringUtils.arraySplit(syntax, '\n', true);
StringBuilder buff = new StringBuilder();
for (String s : syntaxList) {
this.syntax = s;
tokens = tokenize();
index = 0;
Rule rule = parseRule();
rule.setLinks(ruleMap);
String html = rule.getHtmlRailroad(this, false);
html = StringUtils.replaceAll(html, "</code></td><td class=\"d\"><code class=\"c\">", " ");
if (buff.length() > 0) {
buff.append("<br />");
}
buff.append(html);
}
return buff.toString();
}
/**
* Get the HTML documentation for a given syntax.
*
......@@ -138,40 +168,77 @@ public class Bnf {
* @return the HTML formatted text
*/
public String getSyntaxHtml(String bnf) {
bnf = StringUtils.replaceAll(bnf, "\n ", "\n");
StringTokenizer tokenizer = getTokenizer(bnf);
StringBuilder buff = new StringBuilder();
while (tokenizer.hasMoreTokens()) {
String s = tokenizer.nextToken();
if (s.length() == 1 || StringUtils.toUpperEnglish(s).equals(s)) {
buff.append(s);
buff.append(StringUtils.xmlText(s));
continue;
}
RuleHead found = null;
for (int i = 0; i < s.length(); i++) {
String test = StringUtils.toLowerEnglish(s.substring(i));
RuleHead r = ruleMap.get(test);
if (r != null) {
found = r;
break;
}
}
if (found == null || found.getRule() instanceof RuleFixed) {
buff.append(s);
continue;
}
String page = "grammar.html";
if (found.getSection().startsWith("Data Types")) {
page = "datatypes.html";
} else if (found.getSection().startsWith("Functions")) {
page = "functions.html";
buff.append(getLink(s));
}
String s = buff.toString();
// ensure it works within XHTML comments
s = StringUtils.replaceAll(s, "--", "&#45;-");
return s;
}
/**
* Convert convert ruleLink to rule_link.
*
* @param token the token
* @return the rule map key
*/
static String getRuleMapKey(String token) {
StringBuilder buff = new StringBuilder();
for (char ch : token.toCharArray()) {
if (Character.isUpperCase(ch)) {
buff.append('_').append(Character.toLowerCase(ch));
} else {
buff.append(ch);
}
String link = StringUtils.urlEncode(found.getTopic().toLowerCase());
buff.append("<a href=\"").append(page).append("#").
append(link).append("\">").append(s).append("</a>");
}
return buff.toString();
}
/**
* Get the HTML link for the given token, or the token itself if no link
* exists.
*
* @param token the token
* @return the HTML link
*/
String getLink(String token) {
RuleHead found = null;
String key = getRuleMapKey(token);
for (int i = 0; i < token.length(); i++) {
String test = StringUtils.toLowerEnglish(key.substring(i));
RuleHead r = ruleMap.get(test);
if (r != null) {
found = r;
break;
}
}
if (found == null) {
return token;
}
String page = "grammar.html";
if (found.getSection().startsWith("Data Types")) {
page = "datatypes.html";
} else if (found.getSection().startsWith("Functions")) {
page = "functions.html";
} else if (token.equals("@func@")) {
return "<a href=\"functions.html\">Function</a>";
} else if (found.getRule() instanceof RuleFixed) {
return found.getRule().getHtmlRailroad(this, false);
}
String link = found.getTopic().toLowerCase().replace(' ', '_');
link = page + "#" + StringUtils.urlEncode(link);
return "<a href=\"" + link + "\">" + token + "</a>";
}
private Rule parseRule() {
read();
return parseOr();
......@@ -216,9 +283,9 @@ public class Bnf {
}
} else if ("@commaDots@".equals(currentToken)) {
r = new RuleList(new RuleElement(",", currentTopic), lastRepeat, false);
r = new RuleRepeat(r);
r = new RuleRepeat(r, true);
} else if ("@dots@".equals(currentToken)) {
r = new RuleRepeat(lastRepeat);
r = new RuleRepeat(lastRepeat, false);
} else {
r = new RuleElement(currentToken, currentTopic);
}
......
......@@ -62,4 +62,13 @@ public interface Rule {
*/
boolean matchRemove(Sentence sentence);
/**
* Get the HTML railroad.
*
* @param config the configuration
* @param topLevel true if line break are permitted
* @return the railroad
*/
String getHtmlRailroad(Bnf config, boolean topLevel);
}
......@@ -33,6 +33,16 @@ public class RuleElement implements Rule {
return name;
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
String x;
if (keyword) {
x = StringUtils.xmlText(name.trim());
} else {
x = config.getLink(name.trim());
}
return "<code class=\"c\">" + x + "</code>";
}
public String random(Bnf config, int level) {
if (keyword) {
return name.length() > 1 ? " " + name + " " : name;
......@@ -58,17 +68,8 @@ public class RuleElement implements Rule {
if (keyword) {
return;
}
StringBuilder buff = new StringBuilder();
for (char c : name.toCharArray()) {
if (Character.isUpperCase(c)) {
buff.append('_');
buff.append(Character.toLowerCase(c));
} else {
buff.append(c);
}
}
String test = buff.toString();
for (int i = 0; i < name.length(); i++) {
String test = Bnf.getRuleMapKey(name);
for (int i = 0; i < test.length(); i++) {
String t = test.substring(i);
RuleHead r = ruleMap.get(t);
if (r != null) {
......
......@@ -59,6 +59,41 @@ public class RuleFixed implements Rule {
}
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
return getHtmlText();
}
public String getHtmlText() {
switch(type) {
case YMD:
return "2000-01-01";
case HMS:
return "12:00";
case NANOS:
return "0";
case ANY_UNTIL_EOL:
case ANY_EXCEPT_SINGLE_QUOTE:
case ANY_EXCEPT_DOUBLE_QUOTE:
case ANY_WORD:
case ANY_EXCEPT_2_DOLLAR:
case ANY_UNTIL_END: {
return "anything";
}
case HEX_START:
return "0x";
case CONCAT:
return "||";
case AZ_UNDERSCORE:
return "A-Z | _";
case AF:
return "A-F";
case DIGIT:
return "0-9";
default:
throw new AssertionError("type="+type);
}
}
public String random(Bnf config, int level) {
Random r = config.getRandom();
switch(type) {
......
......@@ -53,6 +53,40 @@ public class RuleList implements Rule {
return buff.toString();
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
StringBuilder buff = new StringBuilder();
if (or) {
buff.append("<table class=\"railroad\">");
int i = 0;
for (Rule r : list) {
String a = i == 0 ? "t" : i == list.size() - 1 ? "l" : "k";
i++;
buff.append("<tr class=\"railroad\"><td class=\"" + a + "s\"></td><td class=\"d\">");
buff.append(r.getHtmlRailroad(config, false));
buff.append("</td><td class=\"" + a + "e\"></td></tr>");
}
buff.append("</table>");
} else {
if (!topLevel) {
buff.append("<table class=\"railroad\">");
buff.append("<tr class=\"railroad\">");
}
for (Rule r : list) {
if (!topLevel) {
buff.append("<td class=\"d\">");
}
buff.append(r.getHtmlRailroad(config, false));
if (!topLevel) {
buff.append("</td>");
}
}
if (!topLevel) {
buff.append("</tr></table>");
}
}
return buff.toString();
}
public String random(Bnf config, int level) {
if (or) {
if (level > 10) {
......
......@@ -23,6 +23,16 @@ public class RuleOptional implements Rule {
return "[" + rule.toString() + "]";
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
StringBuilder buff = new StringBuilder();
buff.append("<table class=\"railroad\">");
buff.append("<tr class=\"railroad\"><td class=\"ts\"></td><td class=\"d\">&nbsp;</td><td class=\"te\"></td></tr>");
buff.append("<tr class=\"railroad\"><td class=\"ls\"></td><td class=\"d\">");
buff.append(rule.getHtmlRailroad(config, false));
buff.append("</td><td class=\"le\"></td></tr></table>");
return buff.toString();
}
public String name() {
return null;
}
......
......@@ -13,16 +13,41 @@ import java.util.HashMap;
*/
public class RuleRepeat implements Rule {
private Rule rule;
private static final boolean RAILROAD_DOTS = true;
RuleRepeat(Rule rule) {
private final Rule rule;
private final boolean comma;
RuleRepeat(Rule rule, boolean comma) {
this.rule = rule;
this.comma = comma;
}
public String toString() {
return "...";
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
StringBuilder buff = new StringBuilder();
if (RAILROAD_DOTS) {
buff.append("<code class=\"c\">");
if (comma) {
buff.append(", ");
}
buff.append("...</code>");
} else {
buff.append("<table class=\"railroad\">");
buff.append("<tr class=\"railroad\"><td class=\"te\"></td>");
buff.append("<td class=\"d\">");
buff.append(rule.getHtmlRailroad(config, false));
buff.append("</td><td class=\"ts\"></td></tr>");
buff.append("<tr class=\"railroad\"><td class=\"ls\"></td>");
buff.append("<td class=\"d\">&nbsp;</td>");
buff.append("<td class=\"le\"></td></tr></table>");
}
return buff.toString();
}
public String name() {
return rule.name();
}
......
......@@ -476,4 +476,9 @@ public class DbContextRule implements Rule {
}
return best;
}
public String getHtmlRailroad(Bnf config, boolean topLevel) {
return null;
}
}
......@@ -133,7 +133,7 @@ public class PageParser {
break;
}
case '$':
if (p.charAt(i + 1) == '{') {
if (p.length() > i + 1 && p.charAt(i + 1) == '{') {
i += 2;
int j = p.indexOf('}', i);
if (j < 0) {
......
......@@ -297,9 +297,12 @@ java org.h2.test.TestAll timer
/*
serialized patches
check if sources.jar is not in installer and zip, but in h2web
documentation: rolling review at history.html
html sql railroads
math utils compareTo?
toArray?
mvcc merge problem
......
......@@ -59,28 +59,30 @@ public class GenerateDoc {
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:mem:");
new File(outDir).mkdirs();
new RailroadImages().run(outDir + "/images");
bnf = Bnf.getInstance(null);
bnf.linkStatements();
session.put("version", Constants.getVersion());
session.put("versionDate", Constants.BUILD_DATE);
session.put("stableVersion", Constants.getVersionStable());
session.put("stableVersionDate", Constants.BUILD_DATE_STABLE);
// String help = "SELECT * FROM INFORMATION_SCHEMA.HELP WHERE SECTION";
String help = "SELECT ROWNUM ID, * FROM CSVREAD('" + inHelp + "') WHERE SECTION ";
map("commands", help + "LIKE 'Commands%' ORDER BY ID");
map("commandsDML", help + "= 'Commands (DML)' ORDER BY ID");
map("commandsDDL", help + "= 'Commands (DDL)' ORDER BY ID");
map("commandsOther", help + "= 'Commands (Other)' ORDER BY ID");
map("otherGrammar", help + "= 'Other Grammar' ORDER BY ID");
map("functionsAggregate", help + "= 'Functions (Aggregate)' ORDER BY ID");
map("functionsNumeric", help + "= 'Functions (Numeric)' ORDER BY ID");
map("functionsString", help + "= 'Functions (String)' ORDER BY ID");
map("functionsTimeDate", help + "= 'Functions (Time and Date)' ORDER BY ID");
map("functionsSystem", help + "= 'Functions (System)' ORDER BY ID");
map("functionsAll", help + "LIKE 'Functions%' ORDER BY SECTION, ID");
map("dataTypes", help + "LIKE 'Data Types%' ORDER BY SECTION, ID");
map("commands", help + "LIKE 'Commands%' ORDER BY ID", true);
map("commandsDML", help + "= 'Commands (DML)' ORDER BY ID", true);
map("commandsDDL", help + "= 'Commands (DDL)' ORDER BY ID", true);
map("commandsOther", help + "= 'Commands (Other)' ORDER BY ID", true);
map("otherGrammar", help + "= 'Other Grammar' ORDER BY ID", true);
map("functionsAggregate", help + "= 'Functions (Aggregate)' ORDER BY ID", true);
map("functionsNumeric", help + "= 'Functions (Numeric)' ORDER BY ID", true);
map("functionsString", help + "= 'Functions (String)' ORDER BY ID", true);
map("functionsTimeDate", help + "= 'Functions (Time and Date)' ORDER BY ID", true);
map("functionsSystem", help + "= 'Functions (System)' ORDER BY ID", true);
map("functionsAll", help + "LIKE 'Functions%' ORDER BY SECTION, ID", true);
map("dataTypes", help + "LIKE 'Data Types%' ORDER BY SECTION, ID", true);
map("informationSchema", "SELECT TABLE_NAME TOPIC, GROUP_CONCAT(COLUMN_NAME "
+ "ORDER BY ORDINAL_POSITION SEPARATOR ', ') SYNTAX FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE TABLE_SCHEMA='INFORMATION_SCHEMA' GROUP BY TABLE_NAME ORDER BY TABLE_NAME");
+ "WHERE TABLE_SCHEMA='INFORMATION_SCHEMA' GROUP BY TABLE_NAME ORDER BY TABLE_NAME", false);
processAll("");
conn.close();
}
......@@ -115,7 +117,7 @@ public class GenerateDoc {
out.close();
}
private void map(String key, String sql) throws Exception {
private void map(String key, String sql, boolean railroads) throws Exception {
ResultSet rs = null;
Statement stat = null;
try {
......@@ -133,9 +135,10 @@ public class GenerateDoc {
}
String topic = rs.getString("TOPIC");
String syntax = rs.getString("SYNTAX").trim();
syntax = PageParser.escapeHtml(syntax);
// if enabled, HTML docs get very wide
// syntax = StringUtils.replaceAll(syntax, "<br />", " ");
if (railroads) {
String railroad = bnf.getRailroadHtml(syntax);
map.put("railroad", railroad);
}
syntax = bnf.getSyntaxHtml(syntax);
map.put("syntax", syntax);
......
......@@ -43,6 +43,7 @@ public class MergeDocs {
for (String page : pages) {
text = StringUtils.replaceAll(text, page + "#", "#");
}
text = disableRailroads(text);
text = removeHeaderFooter(fileName, text);
buff.append(text);
}
......@@ -59,6 +60,14 @@ public class MergeDocs {
writer.close();
}
private String disableRailroads(String text) {
text = StringUtils.replaceAll(text, "<!-- railroad-start -->", "<!-- railroad-start ");
text = StringUtils.replaceAll(text, "<!-- railroad-end -->", " railroad-end -->");
text = StringUtils.replaceAll(text, "<!-- syntax-start", "<!-- syntax-start -->");
text = StringUtils.replaceAll(text, "syntax-end -->", "<!-- syntax-end -->");
return text;
}
private String removeHeaderFooter(String fileName, String text) {
// String start = "<body";
// String end = "</body>";
......
/*
* Copyright 2004-2009 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.build.doc;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
* Create the images used in the railroad diagrams.
*/
public class RailroadImages {
private static final int SIZE = 64;
private static final int LINE_REPEAT = 32;
private static final int DIV = 4;
private static final int STROKE = 4;
private String outDir;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String[] args) {
new RailroadImages().run("docs/html/images");
}
/**
* Create the images.
*
* @param outDir the target directory
*/
void run(String outDir) {
this.outDir = outDir;
new File(outDir).mkdirs();
BufferedImage img;
Graphics2D g;
img = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
g = img.createGraphics();
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(STROKE));
g.drawLine(0, SIZE / 2, SIZE, SIZE / 2);
g.dispose();
savePng(img, "div-d.png");
img = new BufferedImage(SIZE, SIZE * LINE_REPEAT, BufferedImage.TYPE_INT_ARGB);
g = img.createGraphics();
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(STROKE));
g.drawLine(0, SIZE / 2, SIZE, SIZE / 2);
g.drawLine(SIZE / 2, SIZE, SIZE / 2, SIZE * LINE_REPEAT);
// g.drawLine(0, SIZE / 2, SIZE / 2, SIZE);
g.drawArc(-SIZE / 2, SIZE / 2, SIZE, SIZE, 0, 90);
g.dispose();
savePng(img, "div-ts.png");
savePng(flipHorizontal(img), "div-te.png");
img = new BufferedImage(SIZE, SIZE * LINE_REPEAT, BufferedImage.TYPE_INT_ARGB);
g = img.createGraphics();
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(STROKE));
g.drawArc(SIZE / 2, -SIZE / 2, SIZE, SIZE, 180, 270);
// g.drawLine(SIZE / 2, 0, SIZE, SIZE / 2);
savePng(img, "div-ls.png");
savePng(flipHorizontal(img), "div-le.png");
g.drawLine(SIZE / 2, 0, SIZE / 2, SIZE * LINE_REPEAT);
g.dispose();
savePng(img, "div-ks.png");
savePng(flipHorizontal(img), "div-ke.png");
}
private void savePng(BufferedImage img, String fileName) {
int w = img.getWidth();
int h = img.getHeight();
BufferedImage smaller = new BufferedImage(w / DIV, h / DIV, img.getType());
Graphics2D g = smaller.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, w / DIV, h / DIV, 0, 0, w, h, null);
g.dispose();
try {
ImageIO.write(smaller, "png", new File(outDir + "/" + fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private BufferedImage flipHorizontal(BufferedImage img) {
int w = img.getWidth(), h = img.getHeight();
BufferedImage copy = new BufferedImage(w, h, img.getType());
Graphics2D g = copy.createGraphics();
g.drawImage(img, 0, 0, w, h, w, 0, 0, h, null);
g.dispose();
return copy;
}
}
......@@ -124,7 +124,7 @@ public class XMLParser {
}
private void error(String expected) {
throw new RuntimeException("Expected: " + expected + " got: " + xml.substring(index));
throw new RuntimeException("Expected: " + expected + " got: " + xml.substring(index, Math.min(index + 1000, xml.length())));
}
private void read(String chars) {
......
......@@ -615,4 +615,6 @@ linkage superfluous disallow scoop moebius inputs copilot dmoebius leod jenkov
jakob poker docware peter unstable measurable scramble reissued recreation
scrambling distinguish official unofficial distinguishable overwrites lastval
notranslate vince bonfanti alphabetically sysdummy sysibm activation
deactivation concatenating reproducing black
\ No newline at end of file
deactivation concatenating reproducing black railroads railroad radius moz
imageio argb bilinear rendering stroke interpolation flip diagrams draw
delim
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论