📄 renderer.java
字号:
assert begin<end;
assert begin>=renderedIndex;
if (isStartOfBlock()) appendBlockVerticalMargin();
final String text=CharacterReference.decode(source.string.subSequence(begin,end),convertNonBreakingSpaces);
for (int i=0; i<text.length(); i++) {
final char ch=text.charAt(i);
if (ch=='\n') {
newLine();
} else if (ch=='\r') {
newLine();
final int nextI=i+1;
if (nextI==text.length()) break;
if (text.charAt(nextI)=='\n') i++;
} else {
append(ch);
}
}
}
private void appendNonPreformattedSegment(final int begin, final int end) throws IOException {
assert begin<end;
assert begin>=renderedIndex;
final String text=CharacterReference.decodeCollapseWhiteSpace(source.string.subSequence(begin,end),convertNonBreakingSpaces);
if (text.length()==0) {
if (!ignoreInitialWhitespace) lastCharWhiteSpace=true;
return;
}
if (isStartOfBlock()) {
appendBlockVerticalMargin();
} else if (lastCharWhiteSpace || (Segment.isWhiteSpace(source.charAt(begin)) && !ignoreInitialWhitespace)) {
append(' ');
}
int textIndex=0;
int i=0;
lastCharWhiteSpace=ignoreInitialWhitespace=false;
while (true) {
for (; i<text.length(); i++) {
if (text.charAt(i)!=' ') continue; // search for end of word
// At end of word. To comply with RFC264 Format=Flowed protocol, need to make sure we don't wrap immediately before ">" or "From ".
if (i+1<text.length() && text.charAt(i+1)=='>') continue;
if (i+6<text.length() && text.startsWith("From ",i+1)) continue;
break; // OK to wrap here if necessary
}
if (col+i-textIndex+1>=maxLineLength) {
if (lastCharWhiteSpace && (blockIndentLevel|listIndentLevel)==0) append(' ');
startNewLine(0);
} else if (lastCharWhiteSpace) {
append(' ');
}
append(text,textIndex,i);
if (i==text.length()) break;
lastCharWhiteSpace=true;
textIndex=++i;
}
lastCharWhiteSpace=Segment.isWhiteSpace(source.charAt(end-1));
}
private boolean isStartOfBlock() {
return blockVerticalMargin!=NO_MARGIN;
}
private void appendBlockVerticalMargin() throws IOException {
assert blockVerticalMargin!=NO_MARGIN;
startNewLine(blockVerticalMargin);
blockVerticalMargin=NO_MARGIN;
}
private void blockBoundary(final int verticalMargin) throws IOException {
// Set a block boundary with the given vertical margin. The vertical margin is the minimum number of blank lines to output between the blocks.
// This method can be called multiple times at a block boundary, and the next textual output will output the number of blank lines determined by the
// maximum vertical margin of all the method calls.
if (blockVerticalMargin<verticalMargin) blockVerticalMargin=verticalMargin;
}
private void startNewLine(int verticalMargin) throws IOException {
// ensures we end up at the start of a line with the specified vertical margin between the previous textual output and the next textual output.
final int requiredNewLines=verticalMargin+(atStartOfLine?0:1);
for (int i=0; i<requiredNewLines; i++) appendable.append(newLine);
atStartOfLine=true;
lastCharWhiteSpace=ignoreInitialWhitespace=false;
}
private void newLine() throws IOException {
appendable.append(newLine);
atStartOfLine=true;
lastCharWhiteSpace=ignoreInitialWhitespace=false;
}
private void appendIndent() throws IOException {
for (int i=blockIndentLevel*blockIndentSize; i>0; i--) appendable.append(' ');
if (bullet) {
for (int i=(listIndentLevel-1)*listIndentSize; i>0; i--) appendable.append(' ');
if (listBulletNumber==UNORDERED_LIST) {
for (int i=listIndentSize-2; i>0; i--) appendable.append(' ');
appendable.append(listBullets[(listIndentLevel-1)%listBullets.length]).append(' ');
} else {
String bulletNumberString=Integer.toString(listBulletNumber);
for (int i=listIndentSize-bulletNumberString.length()-2; i>0; i--) appendable.append(' ');
appendable.append(bulletNumberString).append(". ");
}
bullet=false;
} else {
for (int i=listIndentLevel*listIndentSize; i>0; i--) appendable.append(' ');
}
col=blockIndentLevel*blockIndentSize+listIndentLevel*listIndentSize;
atStartOfLine=false;
}
private Processor append(final char ch) throws IOException {
if (atStartOfLine) appendIndent();
appendable.append(ch);
col++;
return this;
}
private Processor append(final String text) throws IOException {
if (atStartOfLine) appendIndent();
appendable.append(text);
col+=text.length();
return this;
}
private void append(final CharSequence text, final int begin, final int end) throws IOException {
if (atStartOfLine) appendIndent();
for (int i=begin; i<end; i++) appendable.append(text.charAt(i));
col+=end-begin;
}
private interface ElementHandler {
void process(Processor x, Element element) throws IOException;
}
private static class RemoveElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new RemoveElementHandler();
public void process(Processor x, Element element) {}
}
private static class StandardInlineElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new StandardInlineElementHandler();
public void process(Processor x, Element element) throws IOException {
x.appendElementContent(element);
}
}
private static class FontStyleElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE_B=new FontStyleElementHandler('*');
public static final ElementHandler INSTANCE_I=new FontStyleElementHandler('/');
public static final ElementHandler INSTANCE_U=new FontStyleElementHandler('_');
public static final ElementHandler INSTANCE_CODE=new FontStyleElementHandler('|');
private final char decorationChar;
public FontStyleElementHandler(char decorationChar) {
this.decorationChar=decorationChar;
}
public void process(Processor x, Element element) throws IOException {
if (x.decorateFontStyles) {
if (x.lastCharWhiteSpace) {
x.append(' ');
x.lastCharWhiteSpace=false;
}
x.append(decorationChar);
x.appendElementContent(element);
if (x.decorateFontStyles) x.append(decorationChar);
} else {
x.appendElementContent(element);
}
}
}
private static class StandardBlockElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE_0_0=new StandardBlockElementHandler(0,0,false);
public static final ElementHandler INSTANCE_1_1=new StandardBlockElementHandler(1,1,false);
public static final ElementHandler INSTANCE_2_1=new StandardBlockElementHandler(2,1,false);
public static final ElementHandler INSTANCE_0_0_INDENT=new StandardBlockElementHandler(0,0,true);
public static final ElementHandler INSTANCE_1_1_INDENT=new StandardBlockElementHandler(1,1,true);
private final int topMargin;
private final int bottomMargin;
private final boolean indent;
public StandardBlockElementHandler(int topMargin, int bottomMargin, boolean indent) {
this.topMargin=topMargin;
this.bottomMargin=bottomMargin;
this.indent=indent;
}
public void process(Processor x, Element element) throws IOException {
x.blockBoundary(topMargin);
if (indent) x.blockIndentLevel++;
x.appendElementContent(element);
if (indent) x.blockIndentLevel--;
x.blockBoundary(bottomMargin);
}
}
private static class A_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new A_ElementHandler();
public void process(Processor x, Element element) throws IOException {
x.appendElementContent(element);
if (!x.includeHyperlinkURLs) return;
String renderedHyperlinkURL=x.renderer.renderHyperlinkURL(element.getStartTag());
if (renderedHyperlinkURL==null) return;
int linkLength=renderedHyperlinkURL.length()+1;
if (x.col+linkLength>=x.maxLineLength) {
x.startNewLine(0);
} else {
x.append(' ');
}
x.append(renderedHyperlinkURL);
x.lastCharWhiteSpace=true;
}
}
private static class BR_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new BR_ElementHandler();
public void process(Processor x, Element element) throws IOException {
x.newLine();
x.blockBoundary(0);
}
}
private static class HR_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new HR_ElementHandler();
public void process(Processor x, Element element) throws IOException {
x.blockBoundary(0);
x.appendBlockVerticalMargin();
for (int i=0; i<72; i++) x.append('-');
x.blockBoundary(0);
}
}
private static class ListElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE_OL=new ListElementHandler(0);
public static final ElementHandler INSTANCE_UL=new ListElementHandler(UNORDERED_LIST);
private final int initialListBulletNumber;
public ListElementHandler(int initialListBulletNumber) {
this.initialListBulletNumber=initialListBulletNumber;
}
public void process(Processor x, Element element) throws IOException {
x.blockBoundary(0);
int oldListBulletNumber=x.listBulletNumber;
x.listBulletNumber=initialListBulletNumber;
x.listIndentLevel++;
x.appendElementContent(element);
x.listIndentLevel--;
x.listBulletNumber=oldListBulletNumber;
x.blockBoundary(0);
}
}
private static class LI_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new LI_ElementHandler();
public void process(Processor x, Element element) throws IOException {
if (x.listBulletNumber!=UNORDERED_LIST) x.listBulletNumber++;
x.bullet=true;
x.blockBoundary(0);
x.appendBlockVerticalMargin();
x.appendIndent();
x.ignoreInitialWhitespace=true;
x.appendElementContent(element);
x.bullet=false;
x.blockBoundary(0);
}
}
private static class PRE_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new PRE_ElementHandler();
public void process(Processor x, Element element) throws IOException {
x.blockBoundary(1);
boolean oldPreformatted=x.preformatted; // should always be false
x.preformatted=true;
x.appendElementContent(element);
x.preformatted=oldPreformatted;
x.blockBoundary(1);
}
}
private static class TD_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new TD_ElementHandler();
public void process(Processor x, Element element) throws IOException {
if (!x.isStartOfBlock()) x.append(x.tableCellSeparator);
x.lastCharWhiteSpace=false;
x.appendElementContent(element);
}
}
private static class TR_ElementHandler implements ElementHandler {
public static final ElementHandler INSTANCE=new TR_ElementHandler();
public void process(Processor x, Element element) throws IOException {
x.blockBoundary(0);
x.appendElementContent(element);
x.blockBoundary(0);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -