r16876 by jghali - #10292: cjk line breaking and alignment
scribus-commit
scribus-commit at lists.scribus.net
Tue Oct 4 20:53:49 UTC 2011
Author: jghali
Date: Tue Oct 4 20:53:49 2011
New Revision: 16876
URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=16876
Log:
#10292: cjk line breaking and alignment
Modified:
trunk/Scribus/scribus/pageitem_textframe.cpp
Modified: trunk/Scribus/scribus/pageitem_textframe.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=16876&path=/trunk/Scribus/scribus/pageitem_textframe.cpp
==============================================================================
--- trunk/Scribus/scribus/pageitem_textframe.cpp (original)
+++ trunk/Scribus/scribus/pageitem_textframe.cpp Tue Oct 4 20:53:49 2011
@@ -695,7 +695,67 @@
double lineCorr;
};
-
+static int checkCJK(QChar ch) {
+ unsigned int code = ch.unicode();
+ if ( (0x2E80 < code && code < 0x2EFF) || // CJK Radicals Supplement
+ (0x3000 < code && code < 0x303F) || // CJK Symbols and Punctuation
+ (0x31C0 < code && code < 0x31EF) || // CJK Strokes
+ (0x3200 < code && code < 0x32FF) || // Enclosed CJK Letters and Months
+ (0x3300 < code && code < 0x33FF) || // CJK Compatibility
+ (0x3400 < code && code < 0x4DBF) || // CJK Unified Ideographs Extension A
+ (0x4E00 < code && code < 0x9FFF) || // CJK Unified Ideographs
+ (0xF900 < code && code < 0xFAFF) || // CJK Compatibility Ideographs
+ (0xFE30 < code && code < 0xFE4F) || // CJK Compatibility Forms
+ (0x20000 < code && code < 0x2A6DF) || // CJK Unified Ideographs Extension B
+ (0x2A700 < code && code < 0x2B73F) || // CJK Unified Ideographs Extension C
+ (0x2B740 < code && code < 0x2B81F) || // CJK Unified Ideographs Extension D
+ (0x2F800 < code && code < 0x2FA1F) || // CJK Compatibility Ideographs Supplement
+ (0xFF01 < code && code < 0xFF0F) ||
+ (0xFF1A < code && code < 0xFF20) ||
+ (0xFF58 < code && code < 0xFFDC) ||
+ (code == 0x3000) ||
+ (code == 0x3002) ||
+ (code == 0x201C) ||
+ (code == 0x201D))
+ return 1;
+ else
+ return 0;
+}
+
+static int checkCJKBreakAfter(QChar ch) {
+ unsigned int code[] = {0x201C, 0xFF08, 0xFF3B, 0xFF5B, 0xFF5F, 0xFF62, 0xFF0D, 0};
+ for (int i = 0; code[i]; ++i)
+ if (code[i] == ch.unicode())
+ return 0;
+ return 1;
+}
+
+static int checkCJKBreakBefore(QChar ch) {
+ unsigned int code[] =
+ {0x201D, 0x3002, 0xFF01, 0xFF09, 0xFF0C, 0xFF0E, 0xFF1A,
+ 0xFF1B, 0xFF1F, 0xFF3D, 0xFF5D, 0xFF60, 0xFF63, 0xFF64, 0};
+ for (int i = 0; code[i]; ++i)
+ if (code[i] == ch.unicode())
+ return 0;
+ return 1;
+}
+
+static int implicitSpace(ScText *f, ScText *s) {
+ if (checkCJK(f->ch) && checkCJK(s->ch))
+ return 1;
+ else
+ return 0;
+}
+
+static int implicitBreak(ScText *f, ScText *s) {
+ if (checkCJK(f->ch) && checkCJK(s->ch)) {
+ if (!checkCJKBreakAfter(f->ch)
+ || !checkCJKBreakBefore(s->ch))
+ return 0;
+ return 1;
+ } else
+ return 0;
+}
/// called when line length is known and line is to be justified
static void justifyLine(StoryText& itemText, LineSpec& line)
@@ -705,6 +765,8 @@
double spaceNatural = 0;
double glyphExtension;
double spaceExtension;
+ int spaceInsertion = 0;
+ double imSpace = -1;
const ParagraphStyle& style(itemText.paragraphStyle(line.firstItem));
@@ -718,28 +780,53 @@
else if ( (itemText.item(sof)->effects() & ScStyle_SuppressSpace) == 0)
{
spaceNatural += itemText.item(sof)->glyph.wide();
- }
- }
-
- // decision: prio 1: stretch glyph; prio 2: stretch spaces
+ if (imSpace < 0.0 || imSpace > itemText.item(sof)->glyph.wide())
+ imSpace = itemText.item(sof)->glyph.wide();
+ }
+ if (sof != line.firstItem && implicitSpace(itemText.item(sof - 1), itemText.item(sof))) {
+ spaceInsertion += 1;
+ }
+ }
+
+ imSpace /= 2;
+
+ // decision: prio 1: stretch glyph; prio 2: insert spaces; prio 3: stretch spaces
if (line.width < spaceNatural + glyphNatural * style.minGlyphExtension() && spaceNatural > 0)
{
glyphExtension = style.minGlyphExtension() - 1;
spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1;
+ imSpace = 0;
}
else if (line.width < spaceNatural + glyphNatural * style.maxGlyphExtension() && glyphNatural > 0)
{
spaceExtension = 0;
glyphExtension = (line.width - spaceNatural) / glyphNatural - 1;
+ imSpace = 0;
}
else
{
glyphExtension = style.maxGlyphExtension() - 1;
- if (spaceNatural > 0)
- spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1;
- else
- spaceExtension = 0;
+ if (spaceInsertion) {
+ double remaining = line.width - glyphNatural * (1 + glyphExtension) - spaceNatural;
+ if (imSpace > 0) {
+ if (remaining / spaceInsertion < imSpace) {
+ imSpace = remaining / spaceInsertion;
+ spaceExtension = 0;
+ } else {
+ spaceExtension = (remaining + spaceNatural) / (spaceNatural + spaceInsertion * imSpace) - 1;
+ imSpace *= spaceExtension + 1;
+ }
+ } else {
+ imSpace = remaining / spaceInsertion;
+ spaceExtension = 0;
+ }
+ } else {
+ if (spaceNatural > 0)
+ spaceExtension = (line.width - glyphNatural * (1+glyphExtension) ) / spaceNatural - 1;
+ else
+ spaceExtension = 0;
+ }
}
double glyphScale = 1 + glyphExtension;
@@ -772,6 +859,9 @@
else if ((itemText.item(yof)->effects() & ScStyle_SuppressSpace) == 0)
{
itemText.item(yof)->glyph.last()->xadvance += wide * spaceExtension;
+ }
+ if (yof != line.firstItem && implicitSpace(itemText.item(yof - 1), itemText.item(yof))) {
+ itemText.item(yof - 1)->glyph.last()->xadvance += imSpace;
}
}
}
@@ -1913,6 +2003,9 @@
goNoRoom = true;
if ((hl->ch == SpecialChars::COLBREAK) && (Cols > 1))
goNextColumn = true;
+
+ if (a != firstInFrame() && implicitBreak(itemText.item(a - 1), itemText.item(a)))
+ current.rememberBreak(a - 1, breakPos);
++current.itemsInLine;
More information about the scribus-commit
mailing list