📄 bidiline.java
字号:
indexChunk = 0;
}
storedRunDirection = runDirection;
storedTotalTextLength = totalTextLength;
storedIndexChunk = indexChunk;
storedIndexChunkChar = indexChunkChar;
storedCurrentChar = currentChar;
shortStore = (currentChar < totalTextLength);
if (!shortStore) {
// long save
if (storedText.length < totalTextLength) {
storedText = new char[totalTextLength];
storedDetailChunks = new PdfChunk[totalTextLength];
}
System.arraycopy(text, 0, storedText, 0, totalTextLength);
System.arraycopy(detailChunks, 0, storedDetailChunks, 0, totalTextLength);
}
if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
if (storedOrderLevels.length < totalTextLength) {
storedOrderLevels = new byte[totalTextLength];
storedIndexChars = new int[totalTextLength];
}
System.arraycopy(orderLevels, currentChar, storedOrderLevels, currentChar, totalTextLength - currentChar);
System.arraycopy(indexChars, currentChar, storedIndexChars, currentChar, totalTextLength - currentChar);
}
}
public void restore() {
runDirection = storedRunDirection;
totalTextLength = storedTotalTextLength;
indexChunk = storedIndexChunk;
indexChunkChar = storedIndexChunkChar;
currentChar = storedCurrentChar;
if (!shortStore) {
// long restore
System.arraycopy(storedText, 0, text, 0, totalTextLength);
System.arraycopy(storedDetailChunks, 0, detailChunks, 0, totalTextLength);
}
if (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL) {
System.arraycopy(storedOrderLevels, currentChar, orderLevels, currentChar, totalTextLength - currentChar);
System.arraycopy(storedIndexChars, currentChar, indexChars, currentChar, totalTextLength - currentChar);
}
}
public void mirrorGlyphs() {
for (int k = 0; k < totalTextLength; ++k) {
if ((orderLevels[k] & 1) == 1) {
int mirror = mirrorChars.get(text[k]);
if (mirror != 0)
text[k] = (char)mirror;
}
}
}
public void doArabicShapping() {
int src = 0;
int dest = 0;
for (;;) {
while (src < totalTextLength) {
char c = text[src];
if (c >= 0x0600 && c <= 0x06ff)
break;
if (src != dest) {
text[dest] = text[src];
detailChunks[dest] = detailChunks[src];
orderLevels[dest] = orderLevels[src];
}
++src;
++dest;
}
if (src >= totalTextLength) {
totalTextLength = dest;
return;
}
int startArabicIdx = src;
++src;
while (src < totalTextLength) {
char c = text[src];
if (c < 0x0600 || c > 0x06ff)
break;
++src;
}
int arabicWordSize = src - startArabicIdx;
int size = ArabicLigaturizer.arabic_shape(text, startArabicIdx, arabicWordSize, text, dest, arabicWordSize, arabicOptions /*PangoArabicShapping.ar_novowel PangoArabicShapping.ar_lig | PangoArabicShapping.ar_composedtashkeel*/);
if (startArabicIdx != dest) {
for (int k = 0; k < size; ++k) {
detailChunks[dest] = detailChunks[startArabicIdx];
orderLevels[dest++] = orderLevels[startArabicIdx++];
}
}
else
dest += size;
}
}
public PdfLine processLine(float width, int alignment, int runDirection, int arabicOptions) {
this.arabicOptions = arabicOptions;
save();
boolean isRTL = (runDirection == PdfWriter.RUN_DIRECTION_RTL);
if (currentChar >= totalTextLength) {
boolean hasText = getParagraph(runDirection);
if (!hasText)
return null;
if (totalTextLength == 0) {
ArrayList ar = new ArrayList();
PdfChunk ck = new PdfChunk("", detailChunks[0]);
ar.add(ck);
return new PdfLine(0, 0, alignment, true, ar, isRTL);
}
}
float originalWidth = width;
int lastSplit = -1;
if (currentChar != 0)
currentChar = trimLeftEx(currentChar, totalTextLength - 1);
int oldCurrentChar = currentChar;
char c = 0;
char uniC = 0;
PdfChunk ck = null;
float charWidth = 0;
PdfChunk lastValidChunk = null;
for (; currentChar < totalTextLength; ++currentChar) {
c = text[currentChar];
ck = detailChunks[currentChar];
uniC = ck.getUnicodeEquivalent(c);
if (PdfChunk.noPrint(uniC))
continue;
charWidth = ck.getCharWidth(c);
if (ck.isExtSplitCharacter(oldCurrentChar, currentChar, totalTextLength, text, detailChunks))
lastSplit = currentChar;
if (width - charWidth < 0)
break;
width -= charWidth;
lastValidChunk = ck;
}
if (lastValidChunk == null) {
// not even a single char fit; must output the first char
++currentChar;
return new PdfLine(0, 0, alignment, false, createArrayOfPdfChunks(currentChar - 1, currentChar - 1), isRTL);
}
if (currentChar >= totalTextLength) {
// there was more line than text
return new PdfLine(0, width, alignment, true, createArrayOfPdfChunks(oldCurrentChar, totalTextLength - 1), isRTL);
}
int newCurrentChar = trimRightEx(oldCurrentChar, currentChar - 1);
if (newCurrentChar < oldCurrentChar) {
// only WS
return new PdfLine(0, width, alignment, false, createArrayOfPdfChunks(oldCurrentChar, currentChar - 1), isRTL);
}
if (newCurrentChar == currentChar - 1) { // middle of word
HyphenationEvent he = (HyphenationEvent)lastValidChunk.getAttribute(Chunk.HYPHENATION);
if (he != null) {
int word[] = getWord(oldCurrentChar, newCurrentChar);
if (word != null) {
float testWidth = width + getWidth(word[0], currentChar - 1);
String pre = he.getHyphenatedWordPre(new String(text, word[0], word[1] - word[0]), lastValidChunk.font().getFont(), lastValidChunk.font().size(), testWidth);
String post = he.getHyphenatedWordPost();
if (pre.length() > 0) {
PdfChunk extra = new PdfChunk(pre, lastValidChunk);
currentChar = word[1] - post.length();
return new PdfLine(0, testWidth - lastValidChunk.font().width(pre), alignment, false, createArrayOfPdfChunks(oldCurrentChar, word[0] - 1, extra), isRTL);
}
}
}
}
if (lastSplit == -1 || lastSplit >= newCurrentChar) {
// no split point or split point ahead of end
return new PdfLine(0, width + getWidth(newCurrentChar + 1, currentChar - 1), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
}
// standard split
currentChar = lastSplit + 1;
newCurrentChar = trimRightEx(oldCurrentChar, lastSplit);
if (newCurrentChar < oldCurrentChar) {
// only WS again
newCurrentChar = currentChar - 1;
}
return new PdfLine(0, originalWidth - getWidth(oldCurrentChar, newCurrentChar), alignment, false, createArrayOfPdfChunks(oldCurrentChar, newCurrentChar), isRTL);
}
/** Gets the width of a range of characters.
* @param startIdx the first index to calculate
* @param lastIdx the last inclusive index to calculate
* @return the sum of all widths
*/
public float getWidth(int startIdx, int lastIdx) {
char c = 0;
char uniC;
PdfChunk ck = null;
float width = 0;
for (; startIdx <= lastIdx; ++startIdx) {
c = text[startIdx];
ck = detailChunks[startIdx];
uniC = ck.getUnicodeEquivalent(c);
if (PdfChunk.noPrint(uniC))
continue;
width += detailChunks[startIdx].getCharWidth(c);
}
return width;
}
public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx) {
return createArrayOfPdfChunks(startIdx, endIdx, null);
}
public ArrayList createArrayOfPdfChunks(int startIdx, int endIdx, PdfChunk extraPdfChunk) {
boolean bidi = (runDirection == PdfWriter.RUN_DIRECTION_LTR || runDirection == PdfWriter.RUN_DIRECTION_RTL);
if (bidi)
reorder(startIdx, endIdx);
ArrayList ar = new ArrayList();
PdfChunk refCk = detailChunks[startIdx];
PdfChunk ck = null;
StringBuffer buf = new StringBuffer();
char c;
int idx = 0;
for (; startIdx <= endIdx; ++startIdx) {
idx = bidi ? indexChars[startIdx] : startIdx;
c = text[idx];
ck = detailChunks[idx];
if (PdfChunk.noPrint(ck.getUnicodeEquivalent(c)))
continue;
if (ck.isImage()) {
if (buf.length() > 0) {
ar.add(new PdfChunk(buf.toString(), refCk));
buf = new StringBuffer();
}
ar.add(ck);
}
else if (ck == refCk) {
buf.append(c);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -