TMW->TM, TM->TMW, and TMW->Unicode conversions are all (at least 2)
orders of magnitude faster.
This commit is contained in:
parent
afe73c2228
commit
1f4343bed0
2 changed files with 311 additions and 90 deletions
|
@ -124,7 +124,7 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
rtf.write(out, this, 0, getLength());
|
rtf.write(out, this, 0, getLength());
|
||||||
}
|
}
|
||||||
catch (BadLocationException ble) {
|
catch (BadLocationException ble) {
|
||||||
ThdlDebug.noteIffyCode();
|
throw new Error("Cannot write RTF output; [0, " + getLength() + ") constitutes a bad position.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,30 +167,49 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
fontSize. */
|
fontSize. */
|
||||||
private void replaceDuff(int fontSize, int pos,
|
private void replaceDuff(int fontSize, int pos,
|
||||||
DuffData glyph, boolean asTMW) {
|
DuffData glyph, boolean asTMW) {
|
||||||
|
replaceDuffs(fontSize, pos, pos + 1, glyph.text,
|
||||||
|
glyph.font, asTMW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Replacing can be more efficient than inserting and then
|
||||||
|
removing. This replaces the glyphs at position [startOffset,
|
||||||
|
endOffset) with data, which is interpreted as TMW glyphs if
|
||||||
|
asTMW is true and as TM glyphs otherwise. The font size for
|
||||||
|
the new glyph is fontSize; the particular TM or TMW font is
|
||||||
|
specified by newFontIndex, which is one-based, not
|
||||||
|
zero-based. */
|
||||||
|
private void replaceDuffs(int fontSize, int startOffset,
|
||||||
|
int endOffset, String data,
|
||||||
|
int newFontIndex, boolean asTMW) {
|
||||||
MutableAttributeSet mas
|
MutableAttributeSet mas
|
||||||
= ((asTMW)
|
= ((asTMW)
|
||||||
? TibetanMachineWeb.getAttributeSet(glyph.font)
|
? TibetanMachineWeb.getAttributeSet(newFontIndex)
|
||||||
: TibetanMachineWeb.getAttributeSetTM(glyph.font));
|
: TibetanMachineWeb.getAttributeSetTM(newFontIndex));
|
||||||
StyleConstants.setFontSize(mas, fontSize);
|
StyleConstants.setFontSize(mas, fontSize);
|
||||||
try {
|
try {
|
||||||
replace(pos, 1, glyph.text, mas);
|
replace(startOffset, endOffset - startOffset, data, mas);
|
||||||
} catch (BadLocationException ble) {
|
} catch (BadLocationException ble) {
|
||||||
ThdlDebug.noteIffyCode();
|
ThdlDebug.noteIffyCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Replacing can be more efficient than inserting and then
|
/** Replacing can be more efficient than inserting and then
|
||||||
removing. This replaces the glyph at position pos with
|
removing. This replaces the glyphs at position [startOffset,
|
||||||
unicode. The font size for the new unicode is fontSize. */
|
endOffset) with unicode. The font size for the new unicode is
|
||||||
private void replaceDuffWithUnicode(int fontSize, int pos,
|
fontSize. Which particular Unicode font is used depends on
|
||||||
String unicode) {
|
TibetanMachineWeb.getUnicodeAttributeSet().
|
||||||
|
|
||||||
|
@see TibetanMachineWeb#getUnicodeAttributeSet()
|
||||||
|
*/
|
||||||
|
private void replaceDuffsWithUnicode(int fontSize, int startOffset,
|
||||||
|
int endOffset, String unicode) {
|
||||||
MutableAttributeSet mas
|
MutableAttributeSet mas
|
||||||
= TibetanMachineWeb.getUnicodeAttributeSet();
|
= TibetanMachineWeb.getUnicodeAttributeSet();
|
||||||
StyleConstants.setFontSize(mas, fontSize);
|
StyleConstants.setFontSize(mas, fontSize);
|
||||||
try {
|
try {
|
||||||
replace(pos, 1, unicode, mas);
|
replace(startOffset, endOffset - startOffset, unicode, mas);
|
||||||
} catch (BadLocationException ble) {
|
} catch (BadLocationException ble) {
|
||||||
ThdlDebug.noteIffyCode();
|
throw new Error("TMW->Unicode failed because the following constitute a bad position: startOffset " + startOffset + ", endOffset " + endOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +558,7 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (font = 0; font < 5; font++) {
|
for (font = 0; font < 5; font++) {
|
||||||
for (ord = 32; ord < 255; ord++) {
|
for (ord = 32; ord < 255; ord++) {
|
||||||
if (TibetanMachineWeb.mapTMtoTMW(font, ord) != null) {
|
if (TibetanMachineWeb.mapTMtoTMW(font, ord, 0) != null) {
|
||||||
equivalent[0].setData((char)ord, font + 1);
|
equivalent[0].setData((char)ord, font + 1);
|
||||||
try {
|
try {
|
||||||
insertDuff(tibetanFontSize, count++, equivalent, false);
|
insertDuff(tibetanFontSize, count++, equivalent, false);
|
||||||
|
@ -672,22 +691,91 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
@see convertToTM(int,int) */
|
@see convertToTM(int,int) */
|
||||||
private boolean convertHelper(int begin, int end, boolean toTM,
|
private boolean convertHelper(int begin, int end, boolean toTM,
|
||||||
boolean toUnicode, StringBuffer errors) {
|
boolean toUnicode, StringBuffer errors) {
|
||||||
|
// To preserve formatting, we go paragraph by paragraph.
|
||||||
|
|
||||||
|
// Use positions, not offsets, because our work on paragraph K
|
||||||
|
// will affect the offsets of paragraph K+1.
|
||||||
|
|
||||||
|
Position finalEndPos;
|
||||||
|
if (end < 0) {
|
||||||
|
end = getLength();
|
||||||
|
}
|
||||||
|
Element[] paragraphs = getParagraphs(begin, end);
|
||||||
|
try {
|
||||||
|
finalEndPos = createPosition(end);
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
throw new Error("BAD LOCATION DURING CONVERSION");
|
||||||
|
}
|
||||||
|
|
||||||
|
ConversionErrorHelper ceh = new ConversionErrorHelper();
|
||||||
|
int pl = paragraphs.length;
|
||||||
|
for (int i = 0; i < pl; i++) {
|
||||||
|
int p_end = paragraphs[i].getEndOffset();
|
||||||
|
if (i + 1 == paragraphs.length)
|
||||||
|
ceh.doErrorWrapup = true;
|
||||||
|
convertHelperHelper(paragraphs[i].getStartOffset(),
|
||||||
|
((finalEndPos.getOffset() < p_end)
|
||||||
|
? finalEndPos.getOffset()
|
||||||
|
: p_end),
|
||||||
|
toTM, toUnicode, errors, ceh);
|
||||||
|
|
||||||
|
// Now that we've changed paragraph i, recalculate
|
||||||
|
// paragraphs. (PERFORMANCE FIXME: this is O(N*N), and we
|
||||||
|
// could make it O(N) by calculating just one paragraph at
|
||||||
|
// a time.)
|
||||||
|
paragraphs = getParagraphs(begin, finalEndPos.getOffset());
|
||||||
|
if (paragraphs.length != pl)
|
||||||
|
throw new Error("Conversion failed: the number of paragraphs changed, indicating that formatting was lost.");
|
||||||
|
}
|
||||||
|
return ceh.errorReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** See the sole caller, convertHelper. */
|
||||||
|
private void convertHelperHelper(int begin, int end, boolean toTM,
|
||||||
|
boolean toUnicode, StringBuffer errors,
|
||||||
|
ConversionErrorHelper ceh) {
|
||||||
|
final boolean debug = false;
|
||||||
|
if (debug)
|
||||||
|
System.err.println("cHH: [" + begin + ", " + end + ")");
|
||||||
|
// DLC FIXME: here's an idea, a compressor -- use the '-' (ord
|
||||||
|
// 45) or ' ' (ord 32) glyph from the same font as the
|
||||||
|
// preceding glyph, never others. This reduces the size of a
|
||||||
|
// TMW RTF file by a factor of 3 sometimes. To do it, use
|
||||||
|
// this routine, but give it the ability to go from TMW->TMW
|
||||||
|
// and TM->TM.
|
||||||
|
|
||||||
// toTM is ignored when toUnicode is true:
|
// toTM is ignored when toUnicode is true:
|
||||||
ThdlDebug.verify(!toUnicode || !toTM);
|
ThdlDebug.verify(!toUnicode || !toTM);
|
||||||
|
|
||||||
boolean toStdout = ThdlOptions.getBooleanOption("thdl.debug");
|
boolean toStdout = ThdlOptions.getBooleanOption("thdl.debug");
|
||||||
boolean errorReturn = false;
|
|
||||||
if (end < 0)
|
if (end < 0)
|
||||||
end = getLength();
|
end = getLength();
|
||||||
if (begin >= end)
|
if (begin >= end)
|
||||||
return errorReturn; // nothing to do, so no errors in the doing.
|
return; // nothing to do
|
||||||
int i = begin;
|
|
||||||
HashMap problemGlyphsTable = new HashMap();
|
// For speed, do as few replaces as possible. To preserve
|
||||||
|
// formatting, we'll try to replace one paragraph at a time.
|
||||||
|
// But we *must* replace when we hit a different font (TMW3 as
|
||||||
|
// opposed to TMW2, e.g.), so we'll likely replace many times
|
||||||
|
// per paragraph. One very important optimization is that we
|
||||||
|
// don't have to treat TMW3.45 or TMW3.32 as a different font
|
||||||
|
// than TMW.33 -- that's because each of the ten TMW fonts has
|
||||||
|
// the same glyph at position 32 (space) and the same glyph at
|
||||||
|
// position 45 (tsheg). Note that we're building up a big
|
||||||
|
// ArrayList; we're trading space for time.
|
||||||
try {
|
try {
|
||||||
|
int replacementStartIndex = begin;
|
||||||
|
StringBuffer replacementQueue = new StringBuffer();
|
||||||
|
int replacementFontIndex = 0;
|
||||||
|
int replacementFontSize = -1;
|
||||||
|
|
||||||
|
int i = begin;
|
||||||
|
HashMap problemGlyphsTable = new HashMap();
|
||||||
Position endPos = createPosition(end);
|
Position endPos = createPosition(end);
|
||||||
DuffData[] equivalent = new DuffData[1];
|
DuffData[] equivalent = new DuffData[1];
|
||||||
equivalent[0] = new DuffData();
|
equivalent[0] = new DuffData();
|
||||||
int errorGlyphLocation = 0;
|
boolean mustReplace = false;
|
||||||
|
int mustReplaceUntil = -1;
|
||||||
while (i < endPos.getOffset()) {
|
while (i < endPos.getOffset()) {
|
||||||
AttributeSet attr = getCharacterElement(i).getAttributes();
|
AttributeSet attr = getCharacterElement(i).getAttributes();
|
||||||
String fontName = StyleConstants.getFontFamily(attr);
|
String fontName = StyleConstants.getFontFamily(attr);
|
||||||
|
@ -697,6 +785,13 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
: TibetanMachineWeb.getTMFontNumber(fontName));
|
: TibetanMachineWeb.getTMFontNumber(fontName));
|
||||||
|
|
||||||
if (0 != fontNum) {
|
if (0 != fontNum) {
|
||||||
|
|
||||||
|
// SPEED_FIXME: determining font size might be slow, allow an override.
|
||||||
|
int fontSize = tibetanFontSize;
|
||||||
|
try {
|
||||||
|
fontSize = ((Integer)getCharacterElement(i).getAttributes().getAttribute(StyleConstants.FontSize)).intValue();
|
||||||
|
} catch (Exception e) { /* leave it as tibetanFontSize */ }
|
||||||
|
|
||||||
DuffCode dc = null;
|
DuffCode dc = null;
|
||||||
String unicode = null;
|
String unicode = null;
|
||||||
if (toUnicode) {
|
if (toUnicode) {
|
||||||
|
@ -705,63 +800,75 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
} else {
|
} else {
|
||||||
if (toTM) {
|
if (toTM) {
|
||||||
dc = TibetanMachineWeb.mapTMWtoTM(fontNum - 1,
|
dc = TibetanMachineWeb.mapTMWtoTM(fontNum - 1,
|
||||||
getText(i,1).charAt(0));
|
getText(i,1).charAt(0),
|
||||||
|
replacementFontIndex);
|
||||||
} else {
|
} else {
|
||||||
dc = TibetanMachineWeb.mapTMtoTMW(fontNum - 1,
|
dc = TibetanMachineWeb.mapTMtoTMW(fontNum - 1,
|
||||||
getText(i,1).charAt(0));
|
getText(i,1).charAt(0),
|
||||||
|
replacementFontIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (null != dc || null != unicode) {
|
if (replacementQueue.length() > 0
|
||||||
// SPEED_FIXME: determining font size might be slow
|
&& (mustReplace
|
||||||
int fontSize = tibetanFontSize;
|
|| ((!toUnicode
|
||||||
try {
|
&& null != dc
|
||||||
fontSize = ((Integer)getCharacterElement(i).getAttributes().getAttribute(StyleConstants.FontSize)).intValue();
|
&& dc.getFontNum() != replacementFontIndex)
|
||||||
} catch (Exception e) {
|
|| fontSize != replacementFontSize))) {
|
||||||
// leave it as tibetanFontSize
|
// We must replace now, because the attribute
|
||||||
}
|
// set has changed.
|
||||||
|
|
||||||
if (!toUnicode) {
|
// We have two choices: replace or
|
||||||
equivalent[0].setData(dc.getCharacter(),
|
// insert-and-remove. We replace, because
|
||||||
dc.getFontNum());
|
// that preserves formatting.
|
||||||
}
|
|
||||||
|
|
||||||
// We have two choices: remove-then-insert
|
// this if-else statement is duplicated below; beware!
|
||||||
// second vs. insert-then-remove and also
|
int endIndex = mustReplace ? mustReplaceUntil : i;
|
||||||
// insert-before vs. insert-after. It turns
|
if (toUnicode) {
|
||||||
// out that insert-after preserves formatting
|
replaceDuffsWithUnicode(replacementFontSize,
|
||||||
// whereas insert-before doesn't. And we do
|
replacementStartIndex,
|
||||||
// insert-then-remove because we're guessing
|
endIndex,
|
||||||
// that helps with formatting too.
|
replacementQueue.toString());
|
||||||
if (replaceInsteadOfInserting()) {
|
|
||||||
if (toUnicode) {
|
|
||||||
replaceDuffWithUnicode(fontSize, i, unicode);
|
|
||||||
i += unicode.length() - 1; // we do i++ below
|
|
||||||
} else {
|
|
||||||
replaceDuff(fontSize, i, equivalent[0], !toTM);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (toUnicode)
|
replaceDuffs(replacementFontSize,
|
||||||
throw new Error("Please execute 'Clear Preferences' and retry -- you've caused us to go into insert-and-remove mode, as opposed to replace mode, and replacing, the default preference, is the only way you can get TMW->Unicode conversion at present.");
|
replacementStartIndex,
|
||||||
if (insertBefore()) {
|
endIndex,
|
||||||
insertDuff(fontSize, i, equivalent, !toTM);
|
replacementQueue.toString(),
|
||||||
remove(i+1, 1);
|
replacementFontIndex,
|
||||||
} else {
|
!toTM);
|
||||||
insertDuff(fontSize, i+1, equivalent, !toTM);
|
}
|
||||||
remove(i, 1);
|
|
||||||
|
// i += numnewchars - numoldchars;
|
||||||
|
if (debug)
|
||||||
|
System.err.println("Incrementing i by " + (replacementQueue.length()
|
||||||
|
- (endIndex - replacementStartIndex)) + "; replaced a patch with font size " + replacementFontSize + ", fontindex " + replacementFontIndex);
|
||||||
|
i += (replacementQueue.length()
|
||||||
|
- (endIndex - replacementStartIndex));
|
||||||
|
|
||||||
|
replacementQueue.delete(0, replacementQueue.length());
|
||||||
|
mustReplace = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != dc || null != unicode) {
|
||||||
|
if (0 == replacementQueue.length()) {
|
||||||
|
replacementFontSize = fontSize;
|
||||||
|
replacementStartIndex = i;
|
||||||
|
if (!toUnicode) {
|
||||||
|
replacementFontIndex = dc.getFontNum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (toUnicode) {
|
||||||
|
replacementQueue.append(unicode);
|
||||||
|
} else {
|
||||||
|
replacementQueue.append(dc.getCharacter());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// DLC FIXME: insert into document a string
|
// For now, on error, we insert the alphabet
|
||||||
// saying "<<[[there's no TM equivalent for
|
// in a big font in TMW to try and get some
|
||||||
// this, details are ...]]>>" (For now, I'm
|
// attention. We also put the oddballs at the
|
||||||
// inserting the alphabet in a big font in TMW
|
// start of the document. But then we delete
|
||||||
// to try and get some attention. And I've
|
// the alphabet usually.
|
||||||
// *documented* this on the website. I'm also
|
|
||||||
// putting the oddballs at the start of the
|
|
||||||
// document, but I haven't documented that
|
|
||||||
// (FIXME).)
|
|
||||||
|
|
||||||
errorReturn = true;
|
ceh.errorReturn = true;
|
||||||
CharacterInAGivenFont cgf
|
CharacterInAGivenFont cgf
|
||||||
= new CharacterInAGivenFont(getText(i,1), fontName);
|
= new CharacterInAGivenFont(getText(i,1), fontName);
|
||||||
if (!problemGlyphsTable.containsKey(cgf)) {
|
if (!problemGlyphsTable.containsKey(cgf)) {
|
||||||
|
@ -784,7 +891,7 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
// Now also put this problem glyph at
|
// Now also put this problem glyph at
|
||||||
// the beginning of the document:
|
// the beginning of the document:
|
||||||
equivalent[0].setData(getText(i,1), fontNum);
|
equivalent[0].setData(getText(i,1), fontNum);
|
||||||
insertDuff(72, errorGlyphLocation++,
|
insertDuff(72, ceh.errorGlyphLocation++,
|
||||||
equivalent, toUnicode || toTM);
|
equivalent, toUnicode || toTM);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -798,20 +905,83 @@ public class TibetanDocument extends DefaultStyledDocument {
|
||||||
i += trickyTMW.length();
|
i += trickyTMW.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (debug) System.err.println("non-tm/tmw found at offset " + i + "; font=" + fontName + " ord " + (int)getText(i,1).charAt(0));
|
||||||
|
if (replacementQueue.length() > 0) {
|
||||||
|
if (!mustReplace) {
|
||||||
|
mustReplaceUntil = i;
|
||||||
|
mustReplace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
if (replacementQueue.length() > 0) {
|
||||||
|
// this if-else statement is duplicated above; beware!
|
||||||
|
int endIndex = mustReplace ? mustReplaceUntil : i;
|
||||||
|
if (toUnicode) {
|
||||||
|
replaceDuffsWithUnicode(replacementFontSize,
|
||||||
|
replacementStartIndex,
|
||||||
|
endIndex,
|
||||||
|
replacementQueue.toString());
|
||||||
|
} else {
|
||||||
|
replaceDuffs(replacementFontSize,
|
||||||
|
replacementStartIndex,
|
||||||
|
endIndex,
|
||||||
|
replacementQueue.toString(),
|
||||||
|
replacementFontIndex,
|
||||||
|
!toTM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ThdlOptions.getBooleanOption("thdl.leave.bad.tm.tmw.conversions.in.place")) {
|
if (!ThdlOptions.getBooleanOption("thdl.leave.bad.tm.tmw.conversions.in.place")) {
|
||||||
// Remove all characters other than the oddballs:
|
// Remove all characters other than the oddballs:
|
||||||
if (errorGlyphLocation > 0) {
|
if (ceh.doErrorWrapup && ceh.errorGlyphLocation > 0) {
|
||||||
remove(errorGlyphLocation, getLength()-errorGlyphLocation-1);
|
remove(ceh.errorGlyphLocation, getLength()-ceh.errorGlyphLocation-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (BadLocationException ble) {
|
} catch (BadLocationException ble) {
|
||||||
ble.printStackTrace();
|
ble.printStackTrace();
|
||||||
ThdlDebug.noteIffyCode();
|
ThdlDebug.noteIffyCode();
|
||||||
}
|
}
|
||||||
return errorReturn;
|
}
|
||||||
|
|
||||||
|
/** Returns all the paragraph elements in this document that
|
||||||
|
* contain glyphs with offsets in the range [start, end) where
|
||||||
|
* end < 0 is treated as the document's length. Note that roman,
|
||||||
|
* TM, Arial Unicode MS, and TMW text can all be intermingled
|
||||||
|
* within a paragraph. It's the correct level of abstraction to
|
||||||
|
* use, however, because the next finer grain is roughly one
|
||||||
|
* Element per glyph. */
|
||||||
|
private Element[] getParagraphs(int start, int end) {
|
||||||
|
if (end < 0)
|
||||||
|
end = getLength();
|
||||||
|
Element arrayType[] = new Element[0];
|
||||||
|
ArrayList v = new ArrayList();
|
||||||
|
int pos = start;
|
||||||
|
while (pos <= end) {
|
||||||
|
Element pe = getParagraphElement(pos);
|
||||||
|
v.add(pe);
|
||||||
|
if (pe.getEndOffset() == pos)
|
||||||
|
pos = pe.getEndOffset() + 1;
|
||||||
|
else
|
||||||
|
pos = pe.getEndOffset();
|
||||||
|
}
|
||||||
|
return (Element[])v.toArray(arrayType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A helper class used by TibetanDocument.convertHelper(..). */
|
||||||
|
class ConversionErrorHelper {
|
||||||
|
boolean errorReturn;
|
||||||
|
/** one more than the location of the last error glyph, or zero if no
|
||||||
|
* error glyphs yet exist */
|
||||||
|
int errorGlyphLocation;
|
||||||
|
boolean doErrorWrapup;
|
||||||
|
ConversionErrorHelper() {
|
||||||
|
errorReturn = false;
|
||||||
|
errorGlyphLocation = 0;
|
||||||
|
doErrorWrapup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,18 @@ public class TibetanMachineWeb implements THDLWylieConstants {
|
||||||
readInFontFile("/Fonts/TibetanMachineWeb/timwn9.ttf");
|
readInFontFile("/Fonts/TibetanMachineWeb/timwn9.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Assumes that the TM font files are resources associated with
|
||||||
|
* this class and loads those font files.
|
||||||
|
* @throws Error if that assumption does not hold */
|
||||||
|
private static void readInTMFontFiles() {
|
||||||
|
/* Note the leading slashes on these paths: */
|
||||||
|
readInFontFile("/Fonts/TibetanMachine/Timn.ttf");
|
||||||
|
readInFontFile("/Fonts/TibetanMachine/Tims1.ttf");
|
||||||
|
readInFontFile("/Fonts/TibetanMachine/Tims2.ttf");
|
||||||
|
readInFontFile("/Fonts/TibetanMachine/Tims3.ttf");
|
||||||
|
readInFontFile("/Fonts/TibetanMachine/Tims4.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
/** Assumes that the TMW font file at the given path is a resource
|
/** Assumes that the TMW font file at the given path is a resource
|
||||||
* associated with this class and loads that font file.
|
* associated with this class and loads that font file.
|
||||||
* @param path a path within the JAR containing this class file
|
* @param path a path within the JAR containing this class file
|
||||||
|
@ -263,6 +275,14 @@ public class TibetanMachineWeb implements THDLWylieConstants {
|
||||||
readInFontFiles();
|
readInFontFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DLC FIXME: include TM fonts with Jskad but not with other
|
||||||
|
// packages. Right now you can get them manually by editing
|
||||||
|
// build.xml and your options.txt or my_thdl_preferences.txt
|
||||||
|
// file.
|
||||||
|
if (ThdlOptions.getBooleanOption("thdl.do.not.rely.on.system.tm.fonts")) {
|
||||||
|
readInTMFontFiles();
|
||||||
|
}
|
||||||
|
|
||||||
unicodeFontAttributeSet = new SimpleAttributeSet();
|
unicodeFontAttributeSet = new SimpleAttributeSet();
|
||||||
StyleConstants.setFontFamily(unicodeFontAttributeSet,
|
StyleConstants.setFontFamily(unicodeFontAttributeSet,
|
||||||
ThdlOptions.getStringOption("thdl.tmw.to.unicode.font",
|
ThdlOptions.getStringOption("thdl.tmw.to.unicode.font",
|
||||||
|
@ -972,27 +992,43 @@ private static final DuffCode TMW_tab = new DuffCode(1, '\t');
|
||||||
valid.
|
valid.
|
||||||
|
|
||||||
Only a few control characters are supported: '\r' (carriage
|
Only a few control characters are supported: '\r' (carriage
|
||||||
return), '\n' (line feed), and '\t' (tab). */
|
return), '\n' (line feed), and '\t' (tab).
|
||||||
public static DuffCode mapTMtoTMW(int font, int ordinal) {
|
|
||||||
|
If suggestedFont is not zero, then any ordinals that are the same
|
||||||
|
in all fonts ('\n', '-', ' ', '\r', and '\t') will be converted to
|
||||||
|
the font named tmwFontNames[suggestedFont].
|
||||||
|
*/
|
||||||
|
public static DuffCode mapTMtoTMW(int font, int ordinal, int suggestedFont) {
|
||||||
if (font < 0 || font > 4)
|
if (font < 0 || font > 4)
|
||||||
return null;
|
return null;
|
||||||
if (ordinal > 255)
|
if (ordinal > 255)
|
||||||
return getUnusualTMtoTMW(font, ordinal);
|
return getUnusualTMtoTMW(font, ordinal);
|
||||||
if (ordinal < 32) {
|
if (ordinal < 32) {
|
||||||
if (ordinal == (int)'\r')
|
if (ordinal == (int)'\r') {
|
||||||
return TMW_cr;
|
if (0 == suggestedFont)
|
||||||
else if (ordinal == (int)'\n')
|
return TMW_cr;
|
||||||
return TMW_lf;
|
else
|
||||||
else if (ordinal == (int)'\t')
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
return TMW_tab;
|
} else if (ordinal == (int)'\n') {
|
||||||
else {
|
if (0 == suggestedFont)
|
||||||
|
return TMW_lf;
|
||||||
|
else
|
||||||
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
} else if (ordinal == (int)'\t') {
|
||||||
|
if (0 == suggestedFont)
|
||||||
|
return TMW_tab;
|
||||||
|
else
|
||||||
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
} else {
|
||||||
// for robustness, just return font 1, char ordinal.
|
// for robustness, just return font 1, char ordinal.
|
||||||
ThdlDebug.noteIffyCode();
|
ThdlDebug.noteIffyCode();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DuffCode ans = TMtoTMW[font][ordinal-32];
|
if (0 != suggestedFont && 32 == ordinal || 45 == ordinal) {
|
||||||
return ans;
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
}
|
||||||
|
return TMtoTMW[font][ordinal-32];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final DuffCode TM_cr = new DuffCode(1, '\r');
|
private static final DuffCode TM_cr = new DuffCode(1, '\r');
|
||||||
|
@ -1011,25 +1047,40 @@ private static final DuffCode TM_tab = new DuffCode(1, '\t');
|
||||||
Only a few control characters are supported: '\r' (carriage
|
Only a few control characters are supported: '\r' (carriage
|
||||||
return), '\n' (line feed), and '\t' (tab).
|
return), '\n' (line feed), and '\t' (tab).
|
||||||
|
|
||||||
*/
|
If suggestedFont is not zero, then any ordinals that are the same
|
||||||
public static DuffCode mapTMWtoTM(int font, int ordinal) {
|
in all fonts ('\n', '-', ' ', '\r', and '\t') will be converted to
|
||||||
|
the font named tmwFontNames[suggestedFont].
|
||||||
|
*/
|
||||||
|
public static DuffCode mapTMWtoTM(int font, int ordinal, int suggestedFont) {
|
||||||
if (font < 0 || font > 9)
|
if (font < 0 || font > 9)
|
||||||
return null;
|
return null;
|
||||||
if (ordinal > 127)
|
if (ordinal > 127)
|
||||||
return null;
|
return null;
|
||||||
if (ordinal < 32) {
|
if (ordinal < 32) {
|
||||||
if (ordinal == (int)'\r')
|
if (ordinal == (int)'\r') {
|
||||||
return TM_cr;
|
if (0 == suggestedFont)
|
||||||
else if (ordinal == (int)'\n')
|
return TM_cr;
|
||||||
return TM_lf;
|
else
|
||||||
else if (ordinal == (int)'\t')
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
return TM_tab;
|
} else if (ordinal == (int)'\n') {
|
||||||
else {
|
if (0 == suggestedFont)
|
||||||
|
return TM_lf;
|
||||||
|
else
|
||||||
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
} else if (ordinal == (int)'\t') {
|
||||||
|
if (0 == suggestedFont)
|
||||||
|
return TM_tab;
|
||||||
|
else
|
||||||
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
} else {
|
||||||
// for robustness, just return font 1, char ordinal.
|
// for robustness, just return font 1, char ordinal.
|
||||||
ThdlDebug.noteIffyCode();
|
ThdlDebug.noteIffyCode();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (0 != suggestedFont && 32 == ordinal || 45 == ordinal) {
|
||||||
|
return new DuffCode(suggestedFont, (char)ordinal);
|
||||||
|
}
|
||||||
DuffCode ans = TMWtoTM[font][ordinal-32];
|
DuffCode ans = TMWtoTM[font][ordinal-32];
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1092,7 @@ public static void main(String[] args) {
|
||||||
count = 0;
|
count = 0;
|
||||||
for (font = 0; font < 5; font++) {
|
for (font = 0; font < 5; font++) {
|
||||||
for (ord = 32; ord < 255; ord++) {
|
for (ord = 32; ord < 255; ord++) {
|
||||||
if (mapTMtoTMW(font, ord) != null) {
|
if (mapTMtoTMW(font, ord, 0) != null) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1102,7 @@ public static void main(String[] args) {
|
||||||
count = 0;
|
count = 0;
|
||||||
for (font = 0; font < 10; font++) {
|
for (font = 0; font < 10; font++) {
|
||||||
for (ord = 32; ord < 127; ord++) {
|
for (ord = 32; ord < 127; ord++) {
|
||||||
if (mapTMWtoTM(font, ord) != null) {
|
if (mapTMWtoTM(font, ord, 0) != null) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1062,7 +1113,7 @@ public static void main(String[] args) {
|
||||||
for (font = 0; font < 10; font++) {
|
for (font = 0; font < 10; font++) {
|
||||||
for (ord = 32; ord < 127; ord++) {
|
for (ord = 32; ord < 127; ord++) {
|
||||||
DuffCode dc;
|
DuffCode dc;
|
||||||
if ((dc = mapTMWtoTM(font, ord)) != null) {
|
if ((dc = mapTMWtoTM(font, ord, 0)) != null) {
|
||||||
System.out.println(dc.getCharNum() + " "
|
System.out.println(dc.getCharNum() + " "
|
||||||
+ (dc.getFontNum()-1) + " "
|
+ (dc.getFontNum()-1) + " "
|
||||||
+ font + " "
|
+ font + " "
|
||||||
|
@ -1075,7 +1126,7 @@ public static void main(String[] args) {
|
||||||
for (font = 0; font < 5; font++) {
|
for (font = 0; font < 5; font++) {
|
||||||
for (ord = 32; ord < 255; ord++) {
|
for (ord = 32; ord < 255; ord++) {
|
||||||
DuffCode dc;
|
DuffCode dc;
|
||||||
if ((dc = mapTMtoTMW(font, ord)) != null) {
|
if ((dc = mapTMtoTMW(font, ord, 0)) != null) {
|
||||||
System.out.println(ord + " " + font + " "
|
System.out.println(ord + " " + font + " "
|
||||||
+ (dc.getFontNum()-1) + " "
|
+ (dc.getFontNum()-1) + " "
|
||||||
+ dc.getCharNum());
|
+ dc.getCharNum());
|
||||||
|
|
Loading…
Reference in a new issue