              for ( i=pos; i<m_length; i++ ) {
                  if ( x + m_widths[i]-w0 > maxWidth + spaceReduceWidth - firstCharMargin)
                      break;
-@@ -952,7 +977,7 @@ public:
+@@ -952,7 +978,7 @@ public:
                      lastMandatoryWrap = i;
                      break;
                  }

+    }
+
+    bool isCJKLeftPunctuation(lChar16 c) {
+       return c==L'“' || c==L'‘' || c==L'「' || c==L'『' || c==L'《' || c==L'〈' || c==L'（' || c==L'【';
+    }
+
     /// Split paragraph into lines
     void processParagraph( int start, int end )
     {
@@ -927,7 +951,6 @@ public:
                     }
                 }
             }

diff --git a/crengine/src/lvfntman.cpp b/crengine/src/lvfntman.cpp
index 49125a7..2fd9f6a 100644
--- a/crengine/src/lvfntman.cpp
+++ b/crengine/src/lvfntman.cpp
@@ -232,7 +232,7 @@ bool LVEmbeddedFontList::deserialize(SerialBuf & buf) {
 int LVFont::getVisualAligmentWidth()
 {
     if ( _visual_alignment_width==-1 ) {
-        lChar16 chars[] = { getHyphChar(), ',', '.', '!', ':', ';', 0 };
+        lChar16 chars[] = { getHyphChar(), ',', '.', '!', ':', ';', L'，', L'。', L'！', 0 };
         int maxw = 0;
         for ( int i=0; chars[i]; i++ ) {
             int w = getCharWidth( chars[i] );
diff --git a/crengine/src/lvtextfm.cpp b/crengine/src/lvtextfm.cpp
index 57bbf3b..e6f5913 100755
--- a/crengine/src/lvtextfm.cpp
+++ b/crengine/src/lvtextfm.cpp
@@ -712,7 +712,7 @@ public:
