/// <summary> /// 指定の字間で行分割できるか /// </summary> public bool IsProhibited(UChar proceeding, UChar following) { return DoViolateLineStartProhibitionRule(following) || DoViolateLineEndProhibitionRule(proceeding) || DoViolateUnbreakableCharactersRule(proceeding, following); }
void IExchangableTextVisitor.Letter(UChar letter) { if (_inRuby) { _rubyBaseText.Append(letter); } else { _builder.Text(letter); } }
static ParentType ClassifyParentType(UChar ch) { foreach (var type in _someParentTypes) { if (type.IsInitiating(ch)) { return type; } } return _none; }
private static Lang JudgeLang(UChar letter) { if (CC.IsLatin(letter) || letter.IsAscii) //TODO: 半角空白はここでやるべきか? { return Lang.Latin; } else if (CC.IsCJKIdeograph(letter) || CC.IsHiragana(letter) || CC.IsKatakana(letter)) { return Lang.Japanese; } else { return Lang.Undef; } }
public GlueProperty InterletterGlueJP(UChar letterBefore, float zwSizeBefore, UChar letterAfter, float zwSizeAfter) { //最優先は分離禁止。 if (CC.Cl08(letterBefore, letterAfter)) { return new GlueProperty(0, 0, 0); } else { //それ以外の場合について検査 float zwSpaceSize; float baseSize; InterletterSpaceJP(letterBefore, zwSizeBefore, letterAfter, zwSizeAfter, out zwSpaceSize, out baseSize); return new GlueProperty(zwSpaceSize, _standardStretchJPByZw, zwSpaceSize + _standardShrinkJPByZw) * baseSize; } }
public GlueProperty LineTailGlueJP(UChar letter, float zwSize) { if (CC.Cl07(letter) || CC.Cl06(letter) || CC.Cl02(letter)) { var toCancel = LengthJPByZw(letter, zwSize); return new GlueProperty(-toCancel, toCancel + 0.5F * zwSize, 0F); //TODO: 行末は指定のアキかベタ組かどちらか。またほかのアキより優先的に詰める。データ型と UnjustfiedLine のデータ構造変更。 //TODO: 前項目の修正はぶら下げも実現できるように } else if (CC.Cl05(letter)) { var length = 0.25F * zwSize; return new GlueProperty(length, 0, length); } else { return new GlueProperty(); } }
public void Send(UChar letter) { var oldLang = _lang; var newLang = JudgeLang(letter); if (oldLang != newLang && oldLang != Lang.Undef && newLang != Lang.Undef) { if (BeforeLangChange != null) { BeforeLangChange(this, new LangChangeEventArgs(newLang, oldLang)); } } _lang = newLang; if (newLang == Lang.Latin) { _latinBufer.Append(letter); } else { DoFlush(); } }
public void PrintJapaneseLetter(UChar letter, float length) { var deltaY = new GlyphMetric(letter, length).VerticalOffset; DrawString(letter.ToString(), _x, _y - deltaY, _graphics, _fontCache); _y += length; }
protected override void HandleTransliterate(IReplaceable text, TransliterationPosition pos, bool incremental) { lock (this) { boundaryCount = 0; int boundary = 0; GetBreakIterator(); // Lazy-create it if necessary bi.SetText(new ReplaceableCharacterIterator(text, pos.Start, pos.Limit, pos.Start)); // TODO: fix clumsy workaround used below. /* * char[] tempBuffer = new char[text.length()]; * text.getChars(0, text.length(), tempBuffer, 0); * bi.setText(new StringCharacterIterator(new String(tempBuffer), pos.start, pos.limit, pos.start)); */ // end debugging // To make things much easier, we will stack the boundaries, and then insert at the end. // generally, we won't need too many, since we will be filtered. for (boundary = bi.First(); boundary != BreakIterator.Done && boundary < pos.Limit; boundary = bi.Next()) { if (boundary == 0) { continue; } // HACK: Check to see that preceeding item was a letter int cp = UTF16.CharAt(text, boundary - 1); int type = UChar.GetUnicodeCategory(cp).ToInt32(); //System.out.println(Integer.toString(cp,16) + " (before): " + type); if (((1 << type) & LETTER_OR_MARK_MASK) == 0) { continue; } cp = UTF16.CharAt(text, boundary); type = UChar.GetUnicodeCategory(cp).ToInt32(); //System.out.println(Integer.toString(cp,16) + " (after): " + type); if (((1 << type) & LETTER_OR_MARK_MASK) == 0) { continue; } if (boundaryCount >= boundaries.Length) { // realloc if necessary int[] temp = new int[boundaries.Length * 2]; System.Array.Copy(boundaries, 0, temp, 0, boundaries.Length); boundaries = temp; } boundaries[boundaryCount++] = boundary; //System.out.println(boundary); } int delta = 0; int lastBoundary = 0; if (boundaryCount != 0) { // if we found something, adjust delta = boundaryCount * insertion.Length; lastBoundary = boundaries[boundaryCount - 1]; // we do this from the end backwards, so that we don't have to keep updating. while (boundaryCount > 0) { boundary = boundaries[--boundaryCount]; text.Replace(boundary, boundary - boundary, insertion); // ICU4N: Corrected 2nd parameter } } // Now fix up the return values pos.ContextLimit += delta; pos.Limit += delta; pos.Start = incremental ? lastBoundary + delta : pos.Limit; } }
private static bool IsEmDash(UChar letter) { return(letter.CodePoint == 0x2014); }
public float FollowingLineIndent(UChar letter, float zwSize) { return _indentStyle.ParagraphIndent * zwSize; }
/// <summary> /// 行頭禁則 /// </summary> private static bool DoViolateLineStartProhibitionRule(UChar following) { return CC.Cl02(following) || CC.Cl04(following) || CC.Cl06(following) || CC.Cl07(following) || CC.Cl09(following); }
public bool Send(PdfContentByte cb, float fontSize, float xtlm, float ytlm, UChar letter, float length) { if (IsEmDash(letter)) { Open(cb, fontSize, xtlm, ytlm); return true; } else { Close(cb, fontSize, xtlm, ytlm); return false; } }
private static LazyList<UChar> Seq(UChar[] proceeding) { if (proceeding.Length == 0) return LazyList<UChar>.New(); else { var cdr = new UChar[proceeding.Length - 1]; Array.Copy(proceeding, 1, cdr, 0, cdr.Length); return LazyList<UChar>.New(proceeding[0], () => Seq(cdr)); } }
void IExchangableTextVisitor.Letter(UChar letter) { _buffer.Append(letter); }
private void AppendLetterJP(UChar letter) { _buffer.Add(new JapaneseLetter(letter, _advancing.LengthJPByZw(letter, _currentZwSize))); _lastLetter = letter; _lastLetterZwSize = _currentZwSize; }
public void Text(UChar letter) { _buffer.Append(letter); }
private void AppendHeadIndentGlue(UChar letter) { var indent = _advancing.FirstLineIndent(letter, _currentZwSize); _buffer.Add(new ParagraphHeadIndent(indent)); }
public abstract bool IsInitiating(UChar ch);
public abstract bool IsContinuous(UChar ch);
private static float IndentOnSpaceType(UChar firstLetter) { switch (Formatting.SpaceTypeExtension.GetSpaceType(firstLetter)) { case Formatting.SpaceType.Opening: return 0.5F; case Formatting.SpaceType.MiddleDots: return 0.25F; case Formatting.SpaceType.Closing: case Formatting.SpaceType.DividingPunctuation: case Formatting.SpaceType.Normal: default: return 0F; } }
public JapaneseLetter(UChar letter, float length) { Letter = letter; Length = length; }
public void TestExtended() { TestParams tp = new TestParams(); // // Open and read the test data file. // StringBuilder testFileBuf = new StringBuilder(); Stream @is = null; try { #if FEATURE_TYPEEXTENSIONS_GETTYPEINFO Assembly assembly = typeof(RBBITestExtended).GetTypeInfo().Assembly; #else Assembly assembly = typeof(RBBITestExtended).Assembly; #endif @is = assembly.GetManifestResourceStream("ICU4N.Dev.Test.Rbbi.rbbitst.txt"); if (@is == null) { Errln("Could not open test data file rbbitst.txt"); return; } StreamReader isr = new StreamReader(@is, Encoding.UTF8); try { int c; int count = 0; for (; ;) { c = isr.Read(); if (c < 0) { break; } count++; if (c == 0xFEFF && count == 1) { // BOM in the test data file. Discard it. continue; } testFileBuf.AppendCodePoint(c); } } finally { isr.Dispose(); } } catch (IOException e) { Errln(e.ToString()); try { @is.Dispose(); } catch (IOException ignored) { } return; } String testString = testFileBuf.ToString(); const int PARSE_COMMENT = 1; const int PARSE_TAG = 2; const int PARSE_DATA = 3; const int PARSE_NUM = 4; const int PARSE_RULES = 5; int parseState = PARSE_TAG; int savedState = PARSE_TAG; int lineNum = 1; int colStart = 0; int column = 0; int charIdx = 0; int i; int tagValue = 0; // The numeric value of a <nnn> tag. StringBuilder rules = new StringBuilder(); // Holds rules from a <rules> ... </rules> block int rulesFirstLine = 0; // Line number of the start of current <rules> block int len = testString.Length; for (charIdx = 0; charIdx < len;) { int c = testString.CodePointAt(charIdx); charIdx++; if (c == '\r' && charIdx < len && testString[charIdx] == '\n') { // treat CRLF as a unit c = '\n'; charIdx++; } if (c == '\n' || c == '\r') { lineNum++; colStart = charIdx; } column = charIdx - colStart + 1; switch (parseState) { case PARSE_COMMENT: if (c == 0x0a || c == 0x0d) { parseState = savedState; } break; case PARSE_TAG: { if (c == '#') { parseState = PARSE_COMMENT; savedState = PARSE_TAG; break; } if (UChar.IsWhiteSpace(c)) { break; } if (testString.StartsWith("<word>", charIdx - 1, StringComparison.Ordinal)) { tp.bi = BreakIterator.GetWordInstance(tp.currentLocale); charIdx += 5; break; } if (testString.StartsWith("<char>", charIdx - 1, StringComparison.Ordinal)) { tp.bi = BreakIterator.GetCharacterInstance(tp.currentLocale); charIdx += 5; break; } if (testString.StartsWith("<line>", charIdx - 1, StringComparison.Ordinal)) { tp.bi = BreakIterator.GetLineInstance(tp.currentLocale); charIdx += 5; break; } if (testString.StartsWith("<sent>", charIdx - 1, StringComparison.Ordinal)) { tp.bi = BreakIterator.GetSentenceInstance(tp.currentLocale); charIdx += 5; break; } if (testString.StartsWith("<title>", charIdx - 1, StringComparison.Ordinal)) { tp.bi = BreakIterator.GetTitleInstance(tp.currentLocale); charIdx += 6; break; } if (testString.StartsWith("<rules>", charIdx - 1, StringComparison.Ordinal) || testString.StartsWith("<badrules>", charIdx - 1, StringComparison.Ordinal)) { charIdx = testString.IndexOf('>', charIdx) + 1; parseState = PARSE_RULES; rules.Length = (0); rulesFirstLine = lineNum; break; } if (testString.StartsWith("<locale ", charIdx - 1, StringComparison.Ordinal)) { int closeIndex = testString.IndexOf('>', charIdx); if (closeIndex < 0) { Errln("line" + lineNum + ": missing close on <locale tag."); break; } String localeName = testString.Substring(charIdx + 6, closeIndex - (charIdx + 6)); // ICU4N: Corrected 2nd parameter localeName = localeName.Trim(); tp.currentLocale = new ULocale(localeName); charIdx = closeIndex + 1; break; } if (testString.StartsWith("<data>", charIdx - 1, StringComparison.Ordinal)) { parseState = PARSE_DATA; charIdx += 5; tp.dataToBreak.Length = (0); tp.expectedBreaks.Fill(0); tp.srcCol.Fill(0); tp.srcLine.Fill(0); break; } Errln("line" + lineNum + ": Tag expected in test file."); return; //parseState = PARSE_COMMENT; //savedState = PARSE_DATA; } case PARSE_RULES: if (testString.StartsWith("</rules>", charIdx - 1, StringComparison.Ordinal)) { charIdx += 7; parseState = PARSE_TAG; try { tp.bi = new RuleBasedBreakIterator(rules.ToString()); } catch (ArgumentException e) { Errln(String.Format("rbbitst.txt:{0} Error creating break iterator from rules. {1}", lineNum, e)); } } else if (testString.StartsWith("</badrules>", charIdx - 1, StringComparison.Ordinal)) { charIdx += 10; parseState = PARSE_TAG; bool goodRules = true; try { new RuleBasedBreakIterator(rules.ToString()); } catch (ArgumentException e) { goodRules = false; } if (goodRules) { Errln(String.Format( "rbbitst.txt:{0} Expected, but did not get, a failure creating break iterator from rules.", lineNum)); } } else { rules.AppendCodePoint(c); } break; case PARSE_DATA: if (c == '•') { int breakIdx = tp.dataToBreak.Length; tp.expectedBreaks[breakIdx] = -1; tp.srcLine[breakIdx] = lineNum; tp.srcCol[breakIdx] = column; break; } if (testString.StartsWith("</data>", charIdx - 1, StringComparison.Ordinal)) { // Add final entry to mappings from break location to source file position. // Need one extra because last break position returned is after the // last char in the data, not at the last char. int idx = tp.dataToBreak.Length; tp.srcLine[idx] = lineNum; tp.srcCol[idx] = column; parseState = PARSE_TAG; charIdx += 6; // RUN THE TEST! executeTest(tp); break; } if (testString.StartsWith("\\N{", charIdx - 1, StringComparison.Ordinal)) { int nameEndIdx = testString.IndexOf('}', charIdx); if (nameEndIdx == -1) { Errln("Error in named character in test file at line " + lineNum + ", col " + column); } // Named character, e.g. \N{COMBINING GRAVE ACCENT} // Get the code point from the name and insert it into the test data. String charName = testString.Substring(charIdx + 2, nameEndIdx - (charIdx + 2)); // ICU4N: Corrected 2nd parameter c = UChar.GetCharFromName(charName); if (c == -1) { Errln("Error in named character in test file at line " + lineNum + ", col " + column); } else { // Named code point was recognized. Insert it // into the test data. tp.dataToBreak.AppendCodePoint(c); for (i = tp.dataToBreak.Length - 1; i >= 0 && tp.srcLine[i] == 0; i--) { tp.srcLine[i] = lineNum; tp.srcCol[i] = column; } } if (nameEndIdx > charIdx) { charIdx = nameEndIdx + 1; } break; } if (testString.StartsWith("<>", charIdx - 1, StringComparison.Ordinal)) { charIdx++; int breakIdx = tp.dataToBreak.Length; tp.expectedBreaks[breakIdx] = -1; tp.srcLine[breakIdx] = lineNum; tp.srcCol[breakIdx] = column; break; } if (c == '<') { tagValue = 0; parseState = PARSE_NUM; break; } if (c == '#' && column == 3) { // TODO: why is column off so far? parseState = PARSE_COMMENT; savedState = PARSE_DATA; break; } if (c == '\\') { // Check for \ at end of line, a line continuation. // Advance over (discard) the newline int cp = testString.CodePointAt(charIdx); if (cp == '\r' && charIdx < len && testString.CodePointAt(charIdx + 1) == '\n') { // We have a CR LF // Need an extra increment of the input ptr to move over both of them charIdx++; } if (cp == '\n' || cp == '\r') { lineNum++; column = 0; charIdx++; colStart = charIdx; break; } // Let unescape handle the back slash. int[] charIdxAr = new int[1]; charIdxAr[0] = charIdx; cp = Utility.UnescapeAt(testString, charIdxAr); if (cp != -1) { // Escape sequence was recognized. Insert the char // into the test data. charIdx = charIdxAr[0]; tp.dataToBreak.AppendCodePoint(cp); for (i = tp.dataToBreak.Length - 1; i >= 0 && tp.srcLine[i] == 0; i--) { tp.srcLine[i] = lineNum; tp.srcCol[i] = column; } break; } // Not a recognized backslash escape sequence. // Take the next char as a literal. // TODO: Should this be an error? c = testString.CodePointAt(charIdx); charIdx = testString.OffsetByCodePoints(charIdx, 1); } // Normal, non-escaped data char. tp.dataToBreak.AppendCodePoint(c); // Save the mapping from offset in the data to line/column numbers in // the original input file. Will be used for better error messages only. // If there's an expected break before this char, the slot in the mapping // vector will already be set for this char; don't overwrite it. for (i = tp.dataToBreak.Length - 1; i >= 0 && tp.srcLine[i] == 0; i--) { tp.srcLine[i] = lineNum; tp.srcCol[i] = column; } break; case PARSE_NUM: // We are parsing an expected numeric tag value, like <1234>, // within a chunk of data. if (UChar.IsWhiteSpace(c)) { break; } if (c == '>') { // Finished the number. Add the info to the expected break data, // and switch parse state back to doing plain data. parseState = PARSE_DATA; if (tagValue == 0) { tagValue = -1; } int breakIdx = tp.dataToBreak.Length; tp.expectedBreaks[breakIdx] = tagValue; tp.srcLine[breakIdx] = lineNum; tp.srcCol[breakIdx] = column; break; } if (UChar.IsDigit(c)) { tagValue = tagValue * 10 + UChar.Digit(c); break; } Errln(String.Format("Syntax Error in rbbitst.txt at line {0}, col {1}", lineNum, column)); return; } } // Reached end of test file. Raise an error if parseState indicates that we are // within a block that should have been terminated. if (parseState == PARSE_RULES) { Errln(String.Format("rbbitst.txt:{0} <rules> block beginning at line {1} is not closed.", lineNum, rulesFirstLine)); } if (parseState == PARSE_DATA) { Errln(String.Format("rbbitst.txt:{0} <data> block not closed.", lineNum)); } }
public GlyphMetric(UChar letter, float zwSize) { _letter = letter; _zwSize = zwSize; }
public void PrintJapaneseLetter(UChar letter, float length) { var cb = _writer.DirectContent; //実際にフォントを適用 ApplyFont(); //印字。ただし一部の文字についてはフォント変更。 BaseFont specialFont = null; if (Array.IndexOf(symbols, letter) != -1) { specialFont = _symbolFont; } if (specialFont != null) cb.SetFontAndSize(specialFont, _fontSize); var voffset = +new GlyphMetric(letter, length).VerticalOffset; if (!_emdashRenderer.Send(cb, _fontSize, _xtlm, MyYTLM + voffset, letter, length)) { string letterAsString = letter.ToString(); SetAppropriateTextMatrix(letter, voffset, cb); cb.ShowText(letterAsString); } if (specialFont != null) cb.SetFontAndSize(_font, _fontSize); _deltaY += length; }
public void TestCodePointAtBefore() { String s = "" + UChar.MinHighSurrogate + // isolated high UChar.MinHighSurrogate + // pair UChar.MinLowSurrogate + UChar.MinLowSurrogate; // isolated // low char[] c = s.ToCharArray(); int[] avalues = { UChar.MinHighSurrogate, UChar.ToCodePoint(UChar.MinHighSurrogate, UChar.MinLowSurrogate), UChar.MinLowSurrogate, UChar.MinLowSurrogate }; int[] bvalues = { UChar.MinHighSurrogate, UChar.MinHighSurrogate, UChar.ToCodePoint(UChar.MinHighSurrogate, UChar.MinLowSurrogate), UChar.MinLowSurrogate, }; StringBuffer b = new StringBuffer(s); for (int i = 0; i < avalues.Length; ++i) { if (UChar.CodePointAt(s, i) != avalues[i]) { Errln("string at: " + i); } if (UChar.CodePointAt(c, i) != avalues[i]) { Errln("chars at: " + i); } if (UChar.CodePointAt(b, i) != avalues[i]) { Errln("stringbuffer at: " + i); } if (UChar.CodePointBefore(s, i + 1) != bvalues[i]) { Errln("string before: " + i); } if (UChar.CodePointBefore(c, i + 1) != bvalues[i]) { Errln("chars before: " + i); } if (UChar.CodePointBefore(b, i + 1) != bvalues[i]) { Errln("stringbuffer before: " + i); } } //cover codePointAtBefore with limit Logln("Testing codePointAtBefore with limit ..."); for (int i = 0; i < avalues.Length; ++i) { if (UChar.CodePointAt(c, i, 4) != avalues[i]) { Errln("chars at: " + i); } if (UChar.CodePointBefore(c, i + 1, 0) != bvalues[i]) { Errln("chars before: " + i); } } }
/// <summary> /// 行末禁則 /// </summary> private static bool DoViolateLineEndProhibitionRule(UChar proceeding) { return(CC.Cl01(proceeding)); }
/// <summary> /// Implements <see cref="Transliterator.HandleTransliterate(IReplaceable, TransliterationPosition, bool)"/>. /// </summary> protected override void HandleTransliterate(IReplaceable text, TransliterationPosition pos, bool isIncremental) { int start = pos.Start; int limit = pos.Limit; int i, ipat; //loop: while (start < limit) { // Loop over the forms in spec[]. Exit this loop when we // match one of the specs. Exit the outer loop if a // partial match is detected and isIncremental is true. for (ipat = 0; spec[ipat] != END;) { // Read the header int prefixLen = spec[ipat++]; int suffixLen = spec[ipat++]; int radix = spec[ipat++]; int minDigits = spec[ipat++]; int maxDigits = spec[ipat++]; // s is a copy of start that is advanced over the // characters as we parse them. int s = start; bool match = true; for (i = 0; i < prefixLen; ++i) { if (s >= limit) { if (i > 0) { // We've already matched a character. This is // a partial match, so we return if in // incremental mode. In non-incremental mode, // go to the next spec. if (isIncremental) { goto loop_break; } match = false; break; } } char c = text[s++]; if (c != spec[ipat + i]) { match = false; break; } } if (match) { int u = 0; int digitCount = 0; for (; ;) { if (s >= limit) { // Check for partial match in incremental mode. if (s > start && isIncremental) { goto loop_break; } break; } int ch = text.Char32At(s); int digit = UChar.Digit(ch, radix); if (digit < 0) { break; } s += UTF16.GetCharCount(ch); u = (u * radix) + digit; if (++digitCount == maxDigits) { break; } } match = (digitCount >= minDigits); if (match) { for (i = 0; i < suffixLen; ++i) { if (s >= limit) { // Check for partial match in incremental mode. if (s > start && isIncremental) { goto loop_break; } match = false; break; } char c = text[s++]; if (c != spec[ipat + prefixLen + i]) { match = false; break; } } if (match) { // At this point, we have a match string str = UTF16.ValueOf(u); text.Replace(start, s, str); limit -= s - start - str.Length; // The following break statement leaves the // loop that is traversing the forms in // spec[]. We then parse the next input // character. break; } } } ipat += prefixLen + suffixLen; } if (start < limit) { start += UTF16.GetCharCount(text.Char32At(start)); } } loop_break : { } pos.ContextLimit += limit - pos.Limit; pos.Limit = limit; pos.Start = start; }
internal InlineLetterJp(float length, float offset, UChar letter) { _length = length; _offset = offset; _letter = letter; }
/// <summary> /// 行頭禁則 /// </summary> private static bool DoViolateLineStartProhibitionRule(UChar following) { return(CC.Cl02(following) || CC.Cl04(following) || CC.Cl06(following) || CC.Cl07(following) || CC.Cl09(following)); }
private static string FoldCase(string foldee) { return(UChar.FoldCase(foldee, true)); }
[Test] // ICU4N Specific public void TestPropertyNamesUsingTry() { int v, rev; UProperty p; NameChoice choice; for (p = 0; ; ++p) { bool sawProp = false; for (choice = 0; ; ++choice) { string name = null; if (UChar.TryGetPropertyName(p, choice, out name)) { if (!sawProp) { Log("prop " + p + ":"); } string n = (name != null) ? ("\"" + name + '"') : "null"; Log(" " + choice + "=" + n); sawProp = true; } else { if (choice > 0) { break; } } if (name != null) { /* test reverse mapping */ rev = UChar.GetPropertyEnum(name); if (rev != (int)p) { Errln("Property round-trip failure: " + p + " -> " + name + " -> " + rev); } } } if (sawProp) { /* looks like a valid property; check the values */ string pname; UChar.TryGetPropertyName(p, NameChoice.Long, out pname); int max = 0; if (p == UProperty.Canonical_Combining_Class) { max = 255; } else if (p == UProperty.General_Category_Mask) { /* it's far too slow to iterate all the way up to * the real max, U_GC_P_MASK */ max = 0x1000; // U_GC_NL_MASK; } else if (p == UProperty.Block) { /* UBlockCodes, unlike other values, start at 1 */ max = 1; } Logln(""); for (v = -1; ; ++v) { bool sawValue = false; for (choice = 0; ; ++choice) { string vname = null; if (UChar.TryGetPropertyValueName(p, v, choice, out vname)) { string n = (vname != null) ? ("\"" + vname + '"') : "null"; if (!sawValue) { Log(" " + pname + ", value " + v + ":"); } Log(" " + choice + "=" + n); sawValue = true; } else { if (choice > 0) { break; } } if (vname != null) { /* test reverse mapping */ UChar.TryGetPropertyValueEnum(p, vname, out rev); if (rev != v) { Errln("Value round-trip failure (" + pname + "): " + v + " -> " + vname + " -> " + rev); } } } if (sawValue) { Logln(""); } if (!sawValue && v >= max) { break; } } } if (!sawProp) { if (p >= UProperty.String_Limit) { break; } else if (p >= UProperty.Double_Limit) { p = UProperty.String_Start - 1; } else if (p >= UProperty.Mask_Limit) { p = UProperty.Double_Start - 1; } else if (p >= UProperty.Int_Limit) { p = UProperty.Mask_Start - 1; } else if (p >= UProperty.Binary_Limit) { p = UProperty.Int_Start - 1; } } } int i = UChar.GetIntPropertyMinValue( UProperty.Canonical_Combining_Class); for (; i <= UChar.GetIntPropertyMaxValue( UProperty.Canonical_Combining_Class); i++) { string valueName; if (!UChar.TryGetPropertyValueName( UProperty.Canonical_Combining_Class, i, NameChoice.Long, out valueName)) { Errln("0x" + i.ToHexString() + " should have a null property value name"); break; } } }
public override bool IsContinuous(UChar ch) { return(false); }
float IParagraphIndentStyle.TextIndent(UChar firstLetter) { return _textIndent + IndentOnSpaceType(firstLetter); }
public override bool IsInitiating(UChar ch) { return(false); }
//----------------------------------------------------------------------------- // // calcChainedFollowPos. Modify the previously calculated followPos sets // to implement rule chaining. NOT described by Aho // //----------------------------------------------------------------------------- internal virtual void CalcChainedFollowPos(RBBINode tree) { List <RBBINode> endMarkerNodes = new List <RBBINode>(); List <RBBINode> leafNodes = new List <RBBINode>(); // get a list of all endmarker nodes. tree.FindNodes(endMarkerNodes, RBBINode.endMark); // get a list all leaf nodes tree.FindNodes(leafNodes, RBBINode.leafChar); // Collect all leaf nodes that can start matches for rules // with inbound chaining enabled, which is the union of the // firstPosition sets from each of the rule root nodes. List <RBBINode> ruleRootNodes = new List <RBBINode>(); AddRuleRootNodes(ruleRootNodes, tree); ISet <RBBINode> matchStartNodes = new HashSet <RBBINode>(); foreach (RBBINode node in ruleRootNodes) { if (node.fChainIn) { matchStartNodes.UnionWith(node.fFirstPosSet); } } // Iterate over all leaf nodes, // foreach (RBBINode tNode in leafNodes) { RBBINode endNode = null; // Identify leaf nodes that correspond to overall rule match positions. // These include an endMarkerNode in their followPos sets. foreach (RBBINode endMarkerNode in endMarkerNodes) { if (tNode.fFollowPos.Contains(endMarkerNode)) { endNode = tNode; break; } } if (endNode == null) { // node wasn't an end node. Try again with the next. continue; } // We've got a node that can end a match. // Line Break Specific hack: If this node's val correspond to the $CM char class, // don't chain from it. // TODO: Add rule syntax for this behavior, get specifics out of here and // into the rule file. if (fRB.fLBCMNoChain) { int c = this.fRB.fSetBuilder.GetFirstChar(endNode.fVal); if (c != -1) { // c == -1 occurs with sets containing only the {eof} marker string. int cLBProp = UChar.GetIntPropertyValue(c, UProperty.Line_Break); if (cLBProp == UChar.LineBreak.CombiningMark) { continue; } } } // Now iterate over the nodes that can start a match, looking for ones // with the same char class as our ending node. foreach (RBBINode startNode in matchStartNodes) { if (startNode.fType != RBBINode.leafChar) { continue; } if (endNode.fVal == startNode.fVal) { // The end val (character class) of one possible match is the // same as the start of another. // Add all nodes from the followPos of the start node to the // followPos set of the end node, which will have the effect of // letting matches transition from a match state at endNode // to the second char of a match starting with startNode. endNode.fFollowPos.UnionWith(startNode.fFollowPos); } } } }
public override bool IsContinuous(UChar ch) { return(IsExCJKIdeograph(ch) || (new UString("々〆仝\u303b").Contains(ch))); }
private static LazyList<UChar> Seq(UChar[] proceeding, System.Func<LazyList<UChar>> following) { if (proceeding.Length == 0) return following(); else { var slice = new UChar[proceeding.Length - 1]; Array.Copy(proceeding, 1, slice, 0, slice.Length); return LazyList<UChar>.New(proceeding[0], () => Seq(slice, following)); } }
public override bool IsInitiating(UChar ch) { return(IsExCJKIdeograph(ch)); }
private static bool IsExCJKIdeograph(UChar ch) { return(CharacterClasses.IsCJKIdeograph(ch) || ch == SpecialCharacters.ExternalCharacterPlaceholder); }
private void SetAppropriateTextMatrix(UChar letter, float voffset, PdfContentByte cb) { var ytlm = MyYTLM; if (_isPsuedoVertical) { if (CC.Cl06(letter) || CC.Cl07(letter)) { //句読点を平行移動。 cb.SetTextMatrix(_xtlm + _fontSize * (1F / 2 + 1F / 8), ytlm + _fontSize * (1F / 2 + 1F / 8) + voffset); } else if (CC.Cl11(letter)) { //小書きの仮名を平行移動。 cb.SetTextMatrix(_xtlm + _fontSize / 8, ytlm + _fontSize / 8 + voffset); } else if (CC.Cl01(letter)) { //始め括弧を回転、平行移動 cb.SetTextMatrix(0F, -1F, 1F, 0F, _xtlm + _fontSize / 2, ytlm); } else if (letter.CodePoint == char.ConvertToUtf32("ー", 0)) { //音引きを回転、かつ左右反転 cb.SetTextMatrix(0F, -1F, -1F, 0F, _xtlm - _fontSize / 2, ytlm - _fontSize / 2); } else if (letter.CodePoint == char.ConvertToUtf32("—", 0)) //part of Cl08) { //エムダッシュを回転 cb.SetTextMatrix(0F, -1F, 1F, 0F, _xtlm + _fontSize * (1F / 2F + 1 / 8F), ytlm - _fontSize / 2); } //TODO: 毎回 UString 作らない UChar[] で持つ。 else if ( CC.Cl02(letter) || (new UString("―…‥").Contains(letter)) || //part of Cl08 CC.Cl10(letter) || (new UString("~+±=-÷≠:;‘’“”<>≦≧_|→↓←↑⇒⇔").Contains(letter))) //その他転置すべき記号。よく使いそうなものだけ { //それ以外の記号を回転 cb.SetTextMatrix(0F, -1F, 1F, 0F, _xtlm + _fontSize / 2, ytlm - _fontSize / 2); } else { cb.SetTextMatrix(_xtlm, ytlm + voffset); } } else { cb.SetTextMatrix(_xtlm, ytlm + voffset); } }
public override bool IsContinuous(UChar ch) { return(CharacterClasses.IsKatakana(ch) || (new UString("ヽヾ").Contains(ch))); }
private static bool IsEmDash(UChar letter) { return letter.CodePoint == 0x2014; }
//行頭アキはゼロと仮定 public float LengthJPByZw(UChar letter, float zwSize) { return new GlyphMetric(letter, zwSize).VerticalSize; }
/// <summary> /// 行末禁則 /// </summary> private static bool DoViolateLineEndProhibitionRule(UChar proceeding) { return CC.Cl01(proceeding); }
private void InterletterSpaceJP(UChar letterBefore, float zwSizeBefore, UChar letterAfter, float zwSizeAfter, out float zwSpaceSize, out float baseSize) { var beforeSpaceType = letterBefore.GetSpaceType(); var afterSpaceType = letterAfter.GetSpaceType(); switch (beforeSpaceType) { case SpaceType.Closing: switch (afterSpaceType) { case SpaceType.Closing: case SpaceType.DividingPunctuation: case SpaceType.MiddleDots: zwSpaceSize = 0F; baseSize = zwSizeBefore; break; case SpaceType.Opening: case SpaceType.Normal: default: zwSpaceSize = 0.5F; baseSize = zwSizeBefore; break; } break; case SpaceType.DividingPunctuation: switch (afterSpaceType) { case SpaceType.Closing: case SpaceType.DividingPunctuation: zwSpaceSize = 0F; baseSize = zwSizeBefore; break; case SpaceType.MiddleDots: zwSpaceSize = 0.25F; baseSize = zwSizeAfter; break; case SpaceType.Opening: zwSpaceSize = 0.5F; baseSize = zwSizeAfter; break; case SpaceType.Normal: default: zwSpaceSize = 1.0F; baseSize = zwSizeBefore; break; } break; case SpaceType.MiddleDots: switch (afterSpaceType) { case SpaceType.Opening: zwSpaceSize = 0.5F; baseSize = zwSizeAfter; break; case SpaceType.Closing: case SpaceType.DividingPunctuation: case SpaceType.MiddleDots: zwSpaceSize = 0F; baseSize = zwSizeBefore; break; case SpaceType.Normal: default: zwSpaceSize = 0.25F; baseSize = zwSizeBefore; break; } break; case SpaceType.Opening: switch (afterSpaceType) { case SpaceType.Opening: case SpaceType.Closing: case SpaceType.DividingPunctuation: case SpaceType.MiddleDots: case SpaceType.Normal: default: zwSpaceSize = 0F; baseSize = zwSizeBefore; break; } break; case SpaceType.Normal: default: switch (afterSpaceType) { case SpaceType.Opening: zwSpaceSize = 0.5F; baseSize = zwSizeAfter; break; case SpaceType.MiddleDots: zwSpaceSize = 0.25F; baseSize = zwSizeAfter; break; case SpaceType.Closing: case SpaceType.DividingPunctuation: case SpaceType.Normal: default: zwSpaceSize = 0F; baseSize = zwSizeBefore; break; } break; } }
/// <summary> /// 分割禁止 /// </summary> private static bool DoViolateUnbreakableCharactersRule(UChar proceeding, UChar following) { return CC.Cl08(proceeding, following); }
/// <summary> /// 分割禁止 /// </summary> private static bool DoViolateUnbreakableCharactersRule(UChar proceeding, UChar following) { return(CC.Cl08(proceeding, following)); }
/// <summary> /// 段落頭字下げ /// </summary> public float FirstLineIndent(UChar letter, float zwSize) { return (_indentStyle.ParagraphIndent + _indentStyle.TextIndent(letter)) * zwSize; }
/// <summary> /// Implements <see cref="Transliterator.HandleTransliterate(IReplaceable, TransliterationPosition, bool)"/>. /// </summary> protected override void HandleTransliterate(IReplaceable text, TransliterationPosition offsets, bool isIncremental) { int maxLen = UCharacterName.Instance.MaxCharNameLength + 1; // allow for temporary trailing space StringBuffer name = new StringBuffer(maxLen); // Get the legal character set UnicodeSet legal = new UnicodeSet(); UCharacterName.Instance.GetCharNameCharacters(legal); int cursor = offsets.Start; int limit = offsets.Limit; // Modes: // 0 - looking for open delimiter // 1 - after open delimiter int mode = 0; int openPos = -1; // open delim candidate pos int c; while (cursor < limit) { c = text.Char32At(cursor); switch (mode) { case 0: // looking for open delimiter if (c == OPEN_DELIM) { // quick check first openPos = cursor; int i = Utility.ParsePattern(OPEN_PAT, text, cursor, limit); if (i >= 0 && i < limit) { mode = 1; name.Length = 0; cursor = i; continue; // *** reprocess char32At(cursor) } } break; case 1: // after open delimiter // Look for legal chars. If \s+ is found, convert it // to a single space. If closeDelimiter is found, exit // the loop. If any other character is found, exit the // loop. If the limit is reached, exit the loop. // Convert \s+ => SPACE. This assumes there are no // runs of >1 space characters in names. if (PatternProps.IsWhiteSpace(c)) { // Ignore leading whitespace if (name.Length > 0 && name[name.Length - 1] != SPACE) { name.Append(SPACE); // If we are too long then abort. maxLen includes // temporary trailing space, so use '>'. if (name.Length > maxLen) { mode = 0; } } break; } if (c == CLOSE_DELIM) { int len = name.Length; // Delete trailing space, if any if (len > 0 && name[len - 1] == SPACE) { name.Length = --len; } c = UChar.GetCharFromExtendedName(name.ToString()); if (c != -1) { // Lookup succeeded // assert(UTF16.getCharCount(CLOSE_DELIM) == 1); cursor++; // advance over CLOSE_DELIM string str = UTF16.ValueOf(c); text.Replace(openPos, cursor, str); // Adjust indices for the change in the length of // the string. Do not assume that str.length() == // 1, in case of surrogates. int delta = cursor - openPos - str.Length; cursor -= delta; limit -= delta; // assert(cursor == openPos + str.length()); } // If the lookup failed, we leave things as-is and // still switch to mode 0 and continue. mode = 0; openPos = -1; // close off candidate continue; // *** reprocess char32At(cursor) } if (legal.Contains(c)) { UTF16.Append(name, c); // If we go past the longest possible name then abort. // maxLen includes temporary trailing space, so use '>='. if (name.Length >= maxLen) { mode = 0; } } // Invalid character else { --cursor; // Backup and reprocess this character mode = 0; } break; } cursor += UTF16.GetCharCount(c); } offsets.ContextLimit += limit - offsets.Limit; offsets.Limit = limit; // In incremental mode, only advance the cursor up to the last // open delimiter candidate. offsets.Start = (isIncremental && openPos >= 0) ? openPos : cursor; }
public override bool IsContinuous(UChar ch) { return(IsInitiating(ch) || (new UChar('-') == ch)); }
public override bool IsInitiating(UChar ch) { return false; }
public override bool IsInitiating(UChar ch) { return(CharacterClasses.IsLatin(ch)); }
public void TestMaxExpansion(/* char* par */) { int unassigned = 0xEFFFD; String rule = "&a < ab < c/aba < d < z < ch"; RuleBasedCollator coll = null; try { coll = new RuleBasedCollator(rule); } catch (Exception e) { Warnln("Fail to create RuleBasedCollator"); return; } char ch = (char)0; String str = ch + ""; CollationElementIterator iter = coll.GetCollationElementIterator(str); while (ch < 0xFFFF) { int count = 1; ch++; str = ch + ""; iter.SetText(str); int order = iter.Previous(); // thai management if (order == 0) { order = iter.Previous(); } while (iter.Previous() != CollationElementIterator.NullOrder) { count++; } if (iter.GetMaxExpansion(order) < count) { Errln("Failure at codepoint " + ch + ", maximum expansion count < " + count); } } // testing for exact max expansion ch = (char)0; while (ch < 0x61) { str = ch + ""; iter.SetText(str); int order = iter.Previous(); if (iter.GetMaxExpansion(order) != 1) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count == 1"); } ch++; } ch = (char)0x63; str = ch + ""; iter.SetText(str); int temporder = iter.Previous(); if (iter.GetMaxExpansion(temporder) != 3) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count == 3"); } ch = (char)0x64; str = ch + ""; iter.SetText(str); temporder = iter.Previous(); if (iter.GetMaxExpansion(temporder) != 1) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count == 1"); } str = UChar.ConvertFromUtf32(unassigned); iter.SetText(str); temporder = iter.Previous(); if (iter.GetMaxExpansion(temporder) != 2) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count == 2"); } // testing jamo ch = (char)0x1165; str = ch + ""; iter.SetText(str); temporder = iter.Previous(); if (iter.GetMaxExpansion(temporder) > 3) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count < 3"); } // testing special jamo &a<\u1165 rule = "\u0026\u0071\u003c\u1165\u002f\u0071\u0071\u0071\u0071"; try { coll = new RuleBasedCollator(rule); } catch (Exception e) { Errln("Fail to create RuleBasedCollator"); return; } iter = coll.GetCollationElementIterator(str); temporder = iter.Previous(); if (iter.GetMaxExpansion(temporder) != 6) { Errln("Failure at codepoint 0x" + (ch).ToHexString() + " maximum expansion count == 6"); } }
private static int U_GET_GC_MASK(int c) { return(1 << UChar.GetUnicodeCategory(c).ToInt32()); }