Как исправить пунктуацию CJK в начале строки в iText7 / iText7.pdfhtml - PullRequest
0 голосов
/ 08 января 2019

Я столкнулся с этой проблемой при использовании iText7 / iText7.pdfhtml для преобразования строки HTML в файл PDF. Я нашел несколько похожих вопросов, таких как:

Но решение этих вопросов предназначено для iText5, я пробовал эти решения в своем приложении, но, наконец, потерпел неудачу. Мой код выглядит так:

IList<IElement> elements = HtmlConverter.ConvertToElements(pdfHtmlString, properties);
Document document = new Document(pdfDoc);
CJKSplitCharacters splitCharacters = new CJKSplitCharacters();
document.SetFontProvider(fp);
document.SetSplitCharacters(splitCharacters);
document.SetProperty(Property.SPLIT_CHARACTERS, splitCharacters);
foreach (IElement e in elements)
{
     try
     {
          document.Add((AreaBreak)e);
     }
     catch
     {
          document.Add((IBlockElement)e);
     }
}

Код для CJKSplitCharacters:

public class CJKSplitCharacters : ISplitCharacters
{
    // line of text cannot start or end with this character
    static char u2060 = '\u2060';   //       - ZERO WIDTH NO BREAK SPACE

    // a line of text cannot start with any following characters in NOT_BEGIN_CHARACTERS[]
    static char[] NOT_BEGIN_CHARACTERS = new char[]{u30fb, u2022, uff65, u300d, uff09, u0021, u0025, u0029, u002c,
      u002e, u003f, u005d, u007d, uff61, uff63, uff64, uff67, uff68, uff69, uff6a, uff6b, uff6c, uff6d, uff6e,
      uff6f, uff70, uff9e, uff9f, u3001, u3002, uff0c, uff0e, uff1a, uff1b, uff1f, uff01, u309b, u309c, u30fd,
      u30fe, u309d, u309e, u3005, u30fc, u2019, u201d, u3015, uff3d, uff5d, u3009, u300b, u300f, u3011, u00b0,
      u2032, u2033, u2103, u00a2, uff05, u2030, u3041, u3043, u3045, u3047, u3049, u3063, u3083, u3085, u3087,
      u308e, u30a1, u30a3, u30a5, u30a7, u30a9, u30c3, u30e3, u30e5, u30e7, u30ee, u30f5, u30f6, u2060};

    // a line of text cannot end with any following characters in NOT_ENDING_CHARACTERS[]
    static char[] NOT_ENDING_CHARACTERS = new char[]{u0024, u0028, u005b, u007b, u00a3, u00a5, u201c, u2018, u3008,
      u300a, u300c, u300e, u3010, u3014, uff62, uff08, uff3b, uff5b, uffe5, uff04, u2060};

    /// <summary>
    /// 
    /// </summary>
    /// <param name="text"></param>
    /// <param name="glyphPos"></param>
    /// <returns></returns>
    public bool IsSplitCharacter(GlyphLine text, int glyphPos)
    {
        if (!text.Get(glyphPos).HasValidUnicode())
        {
            return false;
        }
        int charCode = text.Get(glyphPos).GetUnicode();

        if (NOT_BEGIN_CHARACTERS.Contains((char)charCode))
        {
            return false;
        }
        return new DefaultSplitCharacters().IsSplitCharacter(text, glyphPos);
    }

Мой исходный код находится здесь: Исходный код

Моя проблема в следующем:

CJK punctuation problem in iText7/iText7.pdfhtml

Большое спасибо за вашу помощь заранее!

1 Ответ

0 голосов
/ 08 января 2019

Полагаю, проблема в IsSplitCharacter реализации метода. Вы не используете NOT_ENDING_CHARACTERS и используете только NOT_BEGIN_CHARACTERS.

Хотя я не могу воспроизвести ваш образец из-за отсутствия исходных строковых данных (что означает, что я не проверял свой подход), я думаю, вам следует реализовать следующий метод:

public bool IsSplitCharacter(GlyphLine text, int glyphPos)
{
    if (!text.Get(glyphPos).HasValidUnicode())
    {
        return false;
    }
    int charCode = text.Get(glyphPos).GetUnicode();

    if (NOT_ENDING_CHARACTERS.Contains((char)charCode))
    {
        return false;
    }

    // Look ahead for the next non-whitespace character and check it not to be in NOT_BEGIN_CHARACTERS list
    for (int i = 1; glyphPos + i < text.end; i++)
    {
        if (!text.Get(glyphPos + i).HasValidUnicode())
        {
            break;
        }
        if (!TextUtil.isSpaceOrWhitespace(text.Get(glyphPos + i)))
        {
            if (NOT_BEGIN_CHARACTERS.Contains(text.Get(glyphPos + i).GetUnicode()))
            {
                return false;
            }
            break;
        }
    }

    return new DefaultSplitCharacters().IsSplitCharacter(text, glyphPos);
}

Обратите также внимание, что ваша реализация не очень эффективна, и вы должны заменить массивы символов на HashSets, чтобы ускорить поиск Contains, который теперь является линейным относительно размеров ваших массивов. Кроме того, вместо создания экземпляра DefaultSplitCharacters каждый раз в IsSplitCharacter, вы должны создать его один раз как поле в вашем классе CJKSplitCharacters и использовать его повторно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...