fix-CJK-Latin-spacing-at-the-end-of-line.patch (6,137 bytes)
commit e1bcddf70f55f06e89e2c47903e9ad2ee6d328a9
Author: Fuminobu TAKEYAMA <ftake@geeko.jp>
Date: Wed May 6 18:08:33 2020 +0900
#16102: Automatic spaces between CJK and Latin is inserted at the end of line
To add spaces between a CJK and Latin letter according to the position
in a line, this commit moves part of code adjusting those spaces to
pageitem_textframe.cpp. Now the apace is inserted before a ltter, in
a similar way to tracking.
It also introduces ScLayout_CJKLatinSpace, representing places
where that spaces are insterted.
diff --git a/scribus/pageitem_textframe.cpp b/scribus/pageitem_textframe.cpp
index 077688b12..6d4eecd1e 100644
--- a/scribus/pageitem_textframe.cpp
+++ b/scribus/pageitem_textframe.cpp
@@ -1643,6 +1643,14 @@ void PageItem_TextFrame::layout()
// glyphs->yadvance = 0;
+ // adjust space between CJK and Latin letter
+ if (!current.glyphs[currentIndex].hasFlag(ScLayout_StartOfLine) && current.glyphs[currentIndex].hasFlag(ScLayout_CJKLatinSpace))
+ {
+ double quaterEM = charStyle.fontSize() / 10 / 4;
+ current.glyphs[currentIndex].extraWidth += quaterEM;
+ current.glyphs[currentIndex].xoffset += quaterEM;
+ }
+
if (i == current.lineData.firstCluster && current.glyphs[currentIndex].hasFlag(ScLayout_CJKFence))
{
current.glyphs[currentIndex].extraWidth -= (charStyle.fontSize() / 10 / 2);
diff --git a/scribus/sctextstruct.h b/scribus/sctextstruct.h
index a3fae20ec..20cc1c258 100644
--- a/scribus/sctextstruct.h
+++ b/scribus/sctextstruct.h
@@ -56,7 +56,8 @@ enum LayoutFlags {
ScLayout_CJKFence = 1 << 19, // marks CJK fence glyph that needs spacing adjustment at start of line
ScLayout_NoBreakAfter = 1 << 20, // marks glyphs after which a line break cannot occur
ScLayout_NoBreakBefore = 1 << 21, // marks glyphs before which a line break cannot occur
- ScLayout_JustificationTracking = 1 << 22 // marks place of tracking in justification (e.g. for Thai)
+ ScLayout_JustificationTracking = 1 << 22, // marks place of tracking in justification (e.g. for Thai)
+ ScLayout_CJKLatinSpace = 1 << 23 // marks place of space between CJK and latin letter
};
diff --git a/scribus/text/textshaper.cpp b/scribus/text/textshaper.cpp
index 3129e1644..81c561fd1 100644
--- a/scribus/text/textshaper.cpp
+++ b/scribus/text/textshaper.cpp
@@ -456,6 +456,7 @@ ShapedText TextShaper::shape(int fromPos, int toPos)
int firstStat = SpecialChars::getCJKAttr(m_story.text(firstChar));
int currStat = (firstChar != lastChar) ? SpecialChars::getCJKAttr(m_story.text(lastChar)) : firstStat;
+ int prevStat = SpecialChars::getCJKAttr(m_story.text(firstChar - 1));
if (firstStat & SpecialChars::CJK_NOBREAK_BEFORE)
run.setFlag(ScLayout_NoBreakBefore);
@@ -465,7 +466,6 @@ ShapedText TextShaper::shape(int fromPos, int toPos)
if ((firstChar > 0) && (firstStat != 0) && ((firstStat & SpecialChars::CJK_NOBREAK_BEFORE) == 0))
{
- int prevStat = SpecialChars::getCJKAttr(m_story.text(firstChar - 1));
if (prevStat != 0 && ((prevStat & SpecialChars::CJK_NOBREAK_AFTER) == 0))
run.setFlag(ScLayout_LineBoundary);
}
@@ -560,49 +560,49 @@ ShapedText TextShaper::shape(int fromPos, int toPos)
}
// Apply CJK spacing according to JIS X4051
- if (lastChar + 1 < m_story.length())
- {
- double halfEM = run.style().fontSize() / 10 / 2;
- double quarterEM = run.style().fontSize() / 10 / 4;
-
- int nextStat = SpecialChars::getCJKAttr(m_story.text(lastChar + 1));
+ // https://www.w3.org/TR/jlreq/
- // 1. add 1/4 aki (space) between a CJK letter and
- // - a latin letter
- // - an ASCII Digits
- if (currStat != 0)
+ // 1. add 1/4 aki (space) between a CJK letter and
+ // - a latin letter
+ // - an ASCII digit
+ if (firstChar > 0) {
+ if (prevStat == 0)
{
- // current char is CJK
- if (SpecialChars::isLetterRequiringSpaceAroundCJK(m_story.text(lastChar + 1).unicode()))
- {
+ // <Latin> <<CJK>>
+ if (SpecialChars::isLetterRequiringSpaceAroundCJK(m_story.text(firstChar - 1).unicode())) {
switch (currStat & SpecialChars::CJK_CHAR_MASK)
{
case SpecialChars::CJK_KANJI:
case SpecialChars::CJK_KANA:
case SpecialChars::CJK_NOTOP:
- run.extraWidth += quarterEM;
+ run.setFlag(ScLayout_CJKLatinSpace);
}
}
}
else
{
- // current char is not CJK
- if (SpecialChars::isLetterRequiringSpaceAroundCJK(m_story.text(lastChar).unicode()))
- {
- switch (nextStat & SpecialChars::CJK_CHAR_MASK)
+ // <CJK> <<Latin>>
+ if (SpecialChars::isLetterRequiringSpaceAroundCJK(m_story.text(firstChar).unicode())) {
+ switch (prevStat & SpecialChars::CJK_CHAR_MASK)
{
case SpecialChars::CJK_KANJI:
case SpecialChars::CJK_KANA:
case SpecialChars::CJK_NOTOP:
- // use the size of the current char instead of the next one
- run.extraWidth += quarterEM;
+ // use the size of the current Latin char
+ // instead of the previous CJK char
+ run.setFlag(ScLayout_CJKLatinSpace);
+ }
}
}
}
- // 2. remove spaces from glyphs with the following CJK attributes
+ // 2. remove spaces from glyphs with the following CJK attributes
+ if (lastChar + 1 < m_story.length())
+ {
if (currStat != 0)
{ // current char is CJK
+ double halfEM = run.style().fontSize() / 10 / 2;
+ int nextStat = SpecialChars::getCJKAttr(m_story.text(lastChar + 1));
switch (currStat & SpecialChars::CJK_CHAR_MASK)
{
case SpecialChars::CJK_FENCE_END:
@@ -636,7 +636,6 @@ ShapedText TextShaper::shape(int fromPos, int toPos)
break;
case SpecialChars::CJK_FENCE_BEGIN:
- int prevStat = SpecialChars::getCJKAttr(m_story.text(lastChar - 1));
if ((prevStat & SpecialChars::CJK_CHAR_MASK) == SpecialChars::CJK_FENCE_BEGIN)
{
run.extraWidth -= halfEM;