r17253 by fschmid - Applied Patch from Bug 10547: "Japanese text line composition rule is not supported."

scribus-commit scribus-commit at lists.scribus.net
Sat Jan 28 09:10:05 UTC 2012


Author: fschmid
Date: Sat Jan 28 09:10:04 2012
New Revision: 17253

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=17253
Log:
Applied Patch from Bug 10547: "Japanese text line composition rule is not supported."

Modified:
    branches/Version14x/Scribus/scribus/pageitem_textframe.cpp
    branches/Version14x/Scribus/scribus/text/specialchars.cpp
    branches/Version14x/Scribus/scribus/text/specialchars.h

Modified: branches/Version14x/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17253&path=/branches/Version14x/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- branches/Version14x/Scribus/scribus/pageitem_textframe.cpp (original)
+++ branches/Version14x/Scribus/scribus/pageitem_textframe.cpp Sat Jan 28 09:10:04 2012
@@ -1137,10 +1137,12 @@
 		current.rightMargin = 0.0;
 		current.mustLineEnd = current.colRight;
 		current.restartX = 0;
+		int lastStat = 0, curStat = 0;
 
 		for (int a = firstInFrame(); a < itemText.length(); ++a)
 		{
 			hl = itemText.item(a);
+			curStat = SpecialChars::getCJKAttr(hl->ch);
 			if (a > 0 && itemText.text(a-1) == SpecialChars::PARSEP)
 				style = itemText.paragraphStyle(a);
 			if (current.itemsInLine == 0)
@@ -1323,6 +1325,81 @@
 					double kern= charStyle.font().glyphKerning(hl->glyph.glyph, glyph2, chs / 10.0) * hl->glyph.scaleH;
 					wide += kern;
 					hl->glyph.xadvance += kern;
+		// change xadvance, xoffset according to JIS X4051
+					ScText *hl2 = itemText.item(a+1);
+					int nextStat = SpecialChars::getCJKAttr(hl2->ch);
+					int prevStat;
+					if(curStat != 0){	// current char is CJK
+						if(nextStat == 0 && !SpecialChars::isBreakingSpace(hl2->ch)){
+							switch(curStat & SpecialChars::CJK_CHAR_MASK){
+							case SpecialChars::CJK_KANJI:
+							case SpecialChars::CJK_KANA:
+							case SpecialChars::CJK_NOTOP:
+								kern = wide / 4;
+								wide += kern;
+								hl->glyph.xadvance += kern;
+							}
+						} else {	// next char is CJK, too
+							switch(curStat & SpecialChars::CJK_CHAR_MASK){
+							case SpecialChars::CJK_FENCE_END:
+								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+								case SpecialChars::CJK_FENCE_BEGIN:
+								case SpecialChars::CJK_FENCE_END:
+								case SpecialChars::CJK_COMMA:
+								case SpecialChars::CJK_PERIOD:
+								case SpecialChars::CJK_MIDPOINT:
+									kern = -wide / 2;
+									wide += kern;
+									hl->glyph.xadvance += kern;
+								}
+								break;
+							case SpecialChars::CJK_COMMA:
+							case SpecialChars::CJK_PERIOD:
+								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+								case SpecialChars::CJK_FENCE_BEGIN:
+								case SpecialChars::CJK_FENCE_END:
+									kern = -wide / 2;
+									wide += kern;
+									hl->glyph.xadvance += kern;
+								}
+								break;
+							case SpecialChars::CJK_MIDPOINT:
+								switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+								case SpecialChars::CJK_FENCE_BEGIN:
+									kern = -wide / 2;
+									wide += kern;
+									hl->glyph.xadvance += kern;
+								}
+								break;
+							case SpecialChars::CJK_FENCE_BEGIN:
+								if(a == current.line.firstItem){ // first char of the line
+									prevStat = SpecialChars::CJK_FENCE_BEGIN;
+								} else {
+									hl2 = itemText.item(a-1);
+									prevStat = SpecialChars::getCJKAttr(hl2->ch) & SpecialChars::CJK_CHAR_MASK;
+								}
+								if(prevStat == SpecialChars::CJK_FENCE_BEGIN){
+									kern = -wide / 2;
+									wide += kern;
+									hl->glyph.xadvance += kern;
+									hl->glyph.xoffset += kern;
+								}
+								break;
+							}
+
+						}
+					} else {	// current char is not CJK
+						if(nextStat != 0 && !SpecialChars::isBreakingSpace(hl->ch)){
+							switch(nextStat & SpecialChars::CJK_CHAR_MASK){
+							case SpecialChars::CJK_KANJI:
+							case SpecialChars::CJK_KANA:
+							case SpecialChars::CJK_NOTOP:
+								kern = hl2->glyph.wide() / 4;
+								wide += kern;
+								hl->glyph.xadvance += kern;
+							}
+						}
+					}
 				}
 			}
 			if (DropCmode)
@@ -1724,6 +1801,20 @@
 					current.rememberBreak(a, breakPos, style.rightMargin());
 				}
 			}
+			// CJK break
+			if(a > current.line.firstItem){ // not the first char
+				if( (lastStat == 0) && (curStat == 0)){	// both non-CJK
+					// do nothing
+				} else {
+					// non-CJK char does not have CJK_NOBREAK_AFTER/CJK_NOBREAK_BEFORE
+					if((lastStat & SpecialChars::CJK_NOBREAK_AFTER) == 0 &&
+					   (curStat & SpecialChars::CJK_NOBREAK_BEFORE) == 0){
+						current.rememberBreak(a-1, breakPos, style.rightMargin());
+					}
+				}
+				
+			}
+			lastStat = curStat;
 			//check against space before PARSEP
 			/*if (SpecialChars::isBreakingSpace(hl->ch) && (a + 1 < itemText.length()) && (itemText.item(a+1)->ch == SpecialChars::PARSEP))
 			{
@@ -2554,6 +2645,14 @@
 							&& (m_Doc->appMode == modeEdit))
 						{
 							double xcoZli = selX + hls->glyph.xoffset;
+							// ugly hack to make selection correct, as xoffset is used to
+							// remove left-half of CJK lparen , which is blank.
+							if(hls->glyph.xoffset){
+								int attr = SpecialChars::getCJKAttr(hls->ch) & SpecialChars::CJK_CHAR_MASK;
+								if( attr == SpecialChars::CJK_FENCE_BEGIN){
+									xcoZli -= hls->glyph.xoffset;
+								}
+							}
 							desc = - charStyleS.font().descent(charStyleS.fontSize() / 10.0);
 							asce = charStyleS.font().ascent(charStyleS.fontSize() / 10.0);
 							wide = hls->glyph.wide();

Modified: branches/Version14x/Scribus/scribus/text/specialchars.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17253&path=/branches/Version14x/Scribus/scribus/text/specialchars.cpp
==============================================================================
--- branches/Version14x/Scribus/scribus/text/specialchars.cpp (original)
+++ branches/Version14x/Scribus/scribus/text/specialchars.cpp Sat Jan 28 09:10:04 2012
@@ -59,3 +59,122 @@
 			|| (includeColBreak && c == COLBREAK));
 }
 
+int SpecialChars::getCJKAttr(QChar c)
+{
+	static uchar attr_3000[0x100] = {
+		// 0x3000 - 0x3007
+		CJK_SPACE,CJK_COMMA,CJK_PERIOD,CJK_NOTOP,CJK_KANJI,CJK_NOTOP,CJK_KANJI,CJK_KANJI,
+		// 0x3008 - 0x300f
+		CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_BEGIN,CJK_FENCE_END,
+		// 0x3010 - 0x3017
+		CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_KANJI,CJK_KANJI,CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_BEGIN,CJK_FENCE_END,
+		// 0x3018 - 0x301f
+		CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_HYPHEN,CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_FENCE_END,
+		// 0x3020 - 0x3027
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0x3028 - 0x302f
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0x3030 - 0x3037
+		CJK_BETWEEN,CJK_BETWEEN,CJK_BETWEEN,CJK_BETWEEN,CJK_BETWEEN,CJK_BETWEEN,CJK_KANJI,CJK_KANJI,
+		// 0x3038 - 0x303f
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0x3040 - 0x3047
+		CJK_KANJI,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,
+		// 0x3048 - 0x304f
+		CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3050 - 0x3057
+		CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3058 - 0x305f
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3060 - 0x3067
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3068 - 0x306f
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3070 - 0x3077
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3078 - 0x307f
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x3080 - 0x3087
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,
+		// 0x3088 - 0x308f
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_KANA,
+		// 0x3090 - 0x3097
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_NOTOP,CJK_KANJI,
+		// 0x3098 - 0x309f
+		CJK_KANJI,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_NOTOP,CJK_KANA,
+		
+		// 0x30a0 - 0x30a7
+		CJK_KANJI,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,
+		// 0x30a8 - 0x30af
+		CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30b0 - 0x30b7
+		CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30b8 - 0x30bf
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30c0 - 0x30c7
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30c8 - 0x30cf
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30d0 - 0x30d7
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30d8 - 0x30df
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,
+		// 0x30e0 - 0x30e7
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,CJK_KANA,CJK_NOTOP,
+		// 0x30e8 - 0x30ef
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_KANA,
+		// 0x30f0 - 0x30f7
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_KANA,CJK_NOTOP,CJK_NOTOP,CJK_KANA,
+		// 0x30f8 - 0x30ff
+		CJK_KANA,CJK_KANA,CJK_KANA,CJK_MIDPOINT,CJK_NOTOP,CJK_NOTOP,CJK_NOTOP,CJK_KANA
+	};
+	
+	static uchar attr_ff00[0x61] = {
+		// 0xff00 - 0xff07
+		CJK_SPACE,CJK_DELMITER,CJK_KANJI,CJK_PREFIX,CJK_PREFIX,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff08 - 0xff0f
+		CJK_FENCE_BEGIN,CJK_FENCE_END,CJK_KANJI,CJK_KANJI,CJK_COMMA,CJK_BETWEEN,CJK_PERIOD,CJK_KANJI,
+		// 0xff10 - 0xff17
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff18 - 0xff1f
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff20 - 0xff27
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff28 - 0xff2f
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff30 - 0xff37
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff38 - 0xff3f
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_FENCE_BEGIN,CJK_KANJI,CJK_FENCE_END,CJK_KANJI,CJK_KANJI,
+		// 0xff40 - 0xff47
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff48 - 0xff4f
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff50 - 0xff57
+		CJK_KANJI,CJK_KANJI,CJK_MIDPOINT,CJK_MIDPOINT,CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_KANJI,
+		// 0xff58 - 0xff5f
+		CJK_KANJI,CJK_KANJI,CJK_KANJI,CJK_FENCE_BEGIN,CJK_KANJI,CJK_FENCE_END,CJK_BETWEEN,CJK_FENCE_BEGIN,
+		// 0xff60
+		CJK_FENCE_END
+	};
+	ushort code = c.unicode();
+	if(code >= 0x3100 && code < 0xa000){
+		return CJK_KANJI;
+	}
+	
+	int attr = 0;
+	if(code >= 0x3000 && code < 0x3100){
+		attr = attr_3000[code - 0x3000];
+	} else if( code >= 0xff00 && code <= 0xff60 ){
+		attr = attr_ff00[code - 0xff00];
+	}
+	if( attr != 0 ){
+		if(attr == CJK_COMMA || attr == CJK_PERIOD || attr == CJK_NOTOP || attr == CJK_FENCE_END )
+			attr |= CJK_NOBREAK_BEFORE;
+		else if(attr == CJK_FENCE_BEGIN )
+			attr |= CJK_NOBREAK_AFTER;
+		else if(attr == CJK_MIDPOINT || attr == CJK_HYPHEN || attr == CJK_DELMITER )
+			attr |= CJK_NOBREAK_BEFORE;
+	}
+	return attr;
+}

Modified: branches/Version14x/Scribus/scribus/text/specialchars.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=17253&path=/branches/Version14x/Scribus/scribus/text/specialchars.h
==============================================================================
--- branches/Version14x/Scribus/scribus/text/specialchars.h (original)
+++ branches/Version14x/Scribus/scribus/text/specialchars.h Sat Jan 28 09:10:04 2012
@@ -52,6 +52,28 @@
 	static bool isBreakingSpace(QChar c);
 	static bool isExpandingSpace(QChar c);
 
+	enum {
+		CJK_FENCE_BEGIN = 0x0001,
+		CJK_FENCE_END = 0x0002,
+		CJK_NOTOP = 0x0003,
+		CJK_HYPHEN = 0x0004,
+		CJK_DELMITER = 0x0005,
+		CJK_MIDPOINT = 0x0006,
+		CJK_PERIOD = 0x0007,
+		CJK_COMMA = 0x0008,
+		CJK_BETWEEN = 0x0009,
+		CJK_PREFIX = 0x000a,
+		CJK_POSTFIX = 0x000b,
+		CJK_SPACE = 0x000c,
+		CJK_KANA = 0x000d,
+		CJK_KANJI = 0x000e,
+
+		CJK_CHAR_MASK = 0x00ff,
+
+		CJK_NOBREAK_BEFORE = 0x0100,
+		CJK_NOBREAK_AFTER = 0x0200,
+	};
+	static int getCJKAttr(QChar c);
 };
 
 #endif




More information about the scribus-commit mailing list