[haiku-commits] haiku: hrev46020 - src/apps/haiku-depot/textview

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 5 Sep 2013 16:55:48 +0200 (CEST)

hrev46020 adds 2 changesets to branch 'master'
old head: 68dfaf0f9d49a713685e93133b37c249535b62d7
new head: f1a08c0848e14a505cf5c47ba32c94528f71825c
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=f1a08c0+%5E68dfaf0

----------------------------------------------------------------------------

169de49: HaikuDepot: Removed no longer needed info from GlyphInfo.

f1a08c0: HaikuDepot: ParagraphLayout: Alignment and justify support.

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

3 files changed, 189 insertions(+), 35 deletions(-)
.../haiku-depot/textview/ParagraphLayout.cpp     | 180 +++++++++++++++++--
src/apps/haiku-depot/textview/ParagraphLayout.h  |  43 ++---
.../haiku-depot/textview/TextDocumentTest.cpp    |   1 +

############################################################################

Commit:      169de499b578d63cff0fd3d6aacc55548ddfd052
URL:         http://cgit.haiku-os.org/haiku/commit/?id=169de49
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Thu Sep  5 13:52:55 2013 UTC

HaikuDepot: Removed no longer needed info from GlyphInfo.

----------------------------------------------------------------------------

diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.cpp 
b/src/apps/haiku-depot/textview/ParagraphLayout.cpp
index 0a1005a..0b234b6 100644
--- a/src/apps/haiku-depot/textview/ParagraphLayout.cpp
+++ b/src/apps/haiku-depot/textview/ParagraphLayout.cpp
@@ -320,8 +320,6 @@ ParagraphLayout::_Layout()
 //                             advanceX = tabOffset - x;
 //             }
 
-               glyph.advanceX = advanceX;
-
                if (glyph.charCode == '\n') {
                        nextLine = true;
                        lineBreak = true;
@@ -461,8 +459,7 @@ ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float 
width,
 
        width += style.GlyphSpacing();
        
-       GlyphInfo glyph(charCode, 0.0f, width, width, 0, style);
-       return fGlyphInfos.Add(glyph);
+       return fGlyphInfos.Add(GlyphInfo(charCode, 0.0f, width, 0));
 }
 
 
diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.h 
b/src/apps/haiku-depot/textview/ParagraphLayout.h
index ff228d2..d0c3425 100644
--- a/src/apps/haiku-depot/textview/ParagraphLayout.h
+++ b/src/apps/haiku-depot/textview/ParagraphLayout.h
@@ -23,21 +23,16 @@ public:
                charCode(0),
                x(0.0f),
                width(0.0f),
-               advanceX(0.0f),
-               lineIndex(0),
-               style()
+               lineIndex(0)
        {
        }
 
-       GlyphInfo(uint32 charCode, float x, float width, float advanceX,
-                       int32 lineIndex, const CharacterStyle& style)
+       GlyphInfo(uint32 charCode, float x, float width, int32 lineIndex)
                :
                charCode(charCode),
                x(x),
                width(width),
-               advanceX(advanceX),
-               lineIndex(lineIndex),
-               style(style)
+               lineIndex(lineIndex)
        {
        }
        
@@ -46,9 +41,7 @@ public:
                charCode(other.charCode),
                x(other.x),
                width(other.width),
-               advanceX(other.advanceX),
-               lineIndex(other.lineIndex),
-               style(other.style)
+               lineIndex(other.lineIndex)
        {
        }
 
@@ -57,9 +50,7 @@ public:
                charCode = other.charCode;
                x = other.x;
                width = other.width;
-               advanceX = other.advanceX;
                lineIndex = other.lineIndex;
-               style = other.style;
                return *this;
        }
 
@@ -68,9 +59,7 @@ public:
                return charCode == other.charCode
                        && x == other.x
                        && width == other.width
-                       && advanceX == other.advanceX
-                       && lineIndex == other.lineIndex
-                       && style == other.style;
+                       && lineIndex == other.lineIndex;
        }
 
        bool operator!=(const GlyphInfo& other) const
@@ -83,11 +72,8 @@ public:
 
        float                                   x;
        float                                   width;
-       float                                   advanceX;
 
        int32                                   lineIndex;
-
-       CharacterStyle                  style;
 };
 
 

############################################################################

Revision:    hrev46020
Commit:      f1a08c0848e14a505cf5c47ba32c94528f71825c
URL:         http://cgit.haiku-os.org/haiku/commit/?id=f1a08c0
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Thu Sep  5 14:54:28 2013 UTC

HaikuDepot: ParagraphLayout: Alignment and justify support.

----------------------------------------------------------------------------

diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.cpp 
b/src/apps/haiku-depot/textview/ParagraphLayout.cpp
index 0b234b6..c7fc592 100644
--- a/src/apps/haiku-depot/textview/ParagraphLayout.cpp
+++ b/src/apps/haiku-depot/textview/ParagraphLayout.cpp
@@ -264,6 +264,23 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset)
 
 
 void
+ParagraphLayout::_Init()
+{
+       fGlyphInfos.Clear();
+
+       int spanCount = fTextSpans.CountItems();
+       for (int i = 0; i < spanCount; i++) {
+               const TextSpan& span = fTextSpans.ItemAtFast(i);
+               if (!_AppendGlyphInfos(span)) {
+                       fprintf(stderr, "%p->ParagraphLayout::_Init() - Out of 
memory\n",
+                               this);
+                       return;
+               }
+       }
+}
+
+
+void
 ParagraphLayout::_ValidateLayout()
 {
        if (!fLayoutValid)
@@ -394,21 +411,151 @@ ParagraphLayout::_Layout()
                float lineHeight;
                _FinalizeLine(lineStart, glyphCount - 1, lineIndex, y, 
lineHeight);
        }
+
+       _ApplyAlignment();
 }
 
 
 void
-ParagraphLayout::_Init()
+ParagraphLayout::_ApplyAlignment()
 {
-       fGlyphInfos.Clear();
+       Alignment alignment = fParagraphStyle.Alignment();
+       bool justify = fParagraphStyle.Justify();
 
-       int spanCount = fTextSpans.CountItems();
-       for (int i = 0; i < spanCount; i++) {
-               const TextSpan& span = fTextSpans.ItemAtFast(i);
-               if (!_AppendGlyphInfos(span)) {
-                       fprintf(stderr, "%p->ParagraphLayout::_Init() - Out of 
memory\n",
-                               this);
-                       return;
+       if (alignment == ALIGN_LEFT && !justify)
+               return;
+
+       int glyphCount = fGlyphInfos.CountItems();
+       if (glyphCount == 0)
+               return;
+
+       int lineIndex = -1;
+       float spaceLeft = 0.0f;
+       float charSpace = 0.0f;
+       float whiteSpace = 0.0f;
+       bool seenChar = false;
+
+       // Iterate all glyphs backwards. On the last character of the next line,
+       // the position of the character determines the available space to be
+       // distributed (spaceLeft).
+       for (int i = glyphCount - 1; i >= 0; i--) {
+               GlyphInfo glyph = fGlyphInfos.ItemAtFast(i);
+
+               if (glyph.lineIndex != lineIndex) {
+                       bool lineBreak = glyph.charCode == '\n' || i == 
glyphCount - 1;
+                       lineIndex = glyph.lineIndex;
+
+                       // The position of the last character determines the 
available
+                       // space.
+                       spaceLeft = fWidth - glyph.x;
+
+                       // If the character is visible, the width of the 
character needs to
+                       // be subtracted from the available space, otherwise it 
would be
+                       // pushed outside the line.
+                       uint32 charClassification = 
get_char_classification(glyph.charCode);
+                       if (charClassification != CHAR_CLASS_WHITESPACE)
+                               spaceLeft -= glyph.width;
+
+                       charSpace = 0.0f;
+                       whiteSpace = 0.0f;
+                       seenChar = false;
+
+                       if (lineBreak || !justify) {
+                               if (alignment == ALIGN_CENTER)
+                                       spaceLeft /= 2.0f;
+                               else if (alignment == ALIGN_LEFT)
+                                       spaceLeft = 0.0f;
+                       } else {
+                               // Figure out how much chars and white space 
chars are on the
+                               // line. Don't count trailing white space.
+                               int charCount = 0;
+                               int spaceCount = 0;
+                               for (int j = i; j >= 0; j--) {
+                                       const GlyphInfo& previousGlyph = 
fGlyphInfos.ItemAtFast(j);
+                                       if (previousGlyph.lineIndex != 
lineIndex) {
+                                               j++;
+                                               break;
+                                       }
+                                       uint32 classification = 
get_char_classification(
+                                               previousGlyph.charCode);
+                                       if (classification == 
CHAR_CLASS_WHITESPACE) {
+                                               if (charCount > 0)
+                                                       spaceCount++;
+                                               else if (j < i)
+                                                       spaceLeft += 
glyph.width;
+                                       } else {
+                                               charCount++;
+                                       }
+                               }
+
+                               // The first char is not shifted when 
justifying, so it doesn't
+                               // contribute.
+                               if (charCount > 0)
+                                       charCount--;
+
+                               // Check if it looks better if both whitespace 
and chars get
+                               // some space distributed, in case there are 
only 1 or two
+                               // space chars on the line.
+                               float spaceLeftForSpace = spaceLeft;
+                               float spaceLeftForChars = spaceLeft;
+
+                               if (spaceCount > 0) {
+                                       float spaceCharRatio = (float) 
spaceCount / charCount;
+                                       if (spaceCount < 3 && spaceCharRatio < 
0.4f) {
+                                               spaceLeftForSpace = spaceLeft * 
2.0f * spaceCharRatio;
+                                               spaceLeftForChars = spaceLeft - 
spaceLeftForSpace;
+                                       } else
+                                               spaceLeftForChars = 0.0f;
+                               }
+
+                               if (spaceCount > 0)
+                                       whiteSpace = spaceLeftForSpace / 
spaceCount;
+                               if (charCount > 0)
+                                       charSpace = spaceLeftForChars / 
charCount;
+                               
+                               LineInfo line = 
fLineInfos.ItemAtFast(lineIndex);
+                               line.extraGlyphSpacing = charSpace;
+                               line.extraWhiteSpacing = whiteSpace;
+
+                               fLineInfos.Replace(lineIndex, line);
+                       }
+               }
+
+               // Each character is pushed towards the right by the space that 
is
+               // still available. When justification is performed, the shift 
is
+               // gradually decreased. This works since the iteration is 
backwards
+               // and the characters on the right are pushed farthest.
+               glyph.x += spaceLeft;
+
+               unsigned classification = 
get_char_classification(glyph.charCode);
+
+               if (i < glyphCount - 1) {
+                       GlyphInfo nextGlyph = fGlyphInfos.ItemAtFast(i + 1);
+                       if (nextGlyph.lineIndex == lineIndex) {
+                               uint32 nextClassification
+                                       = 
get_char_classification(nextGlyph.charCode);
+                               if (nextClassification == CHAR_CLASS_WHITESPACE
+                                       && classification != 
CHAR_CLASS_WHITESPACE) {
+                                       // When a space character is right of a 
regular character,
+                                       // add the additional space to the 
space instead of the
+                                       // character
+                                       float shift = (nextGlyph.x - glyph.x) - 
glyph.width;
+                                       nextGlyph.x -= shift;
+                                       fGlyphInfos.Replace(i + 1, nextGlyph);
+                               }
+                       }
+               }
+
+               fGlyphInfos.Replace(i, glyph);
+
+               // The shift (spaceLeft) is reduced depending on the character
+               // classification.
+               if (classification == CHAR_CLASS_WHITESPACE) {
+                       if (seenChar)
+                               spaceLeft -= whiteSpace;
+               } else {
+                       seenChar = true;
+                       spaceLeft -= charSpace;
                }
        }
 }
@@ -555,7 +702,13 @@ ParagraphLayout::_DrawSpan(BView* view, const TextSpan& 
span,
        view->SetHighColor(style.ForegroundColor());
 
        // TODO: Implement other style properties
-       // TODO: Implement correct glyph spacing
 
-       view->DrawString(span.Text(), BPoint(x, y));
+       escapement_delta delta;
+       delta.nonspace = line.extraGlyphSpacing;
+       delta.space = line.extraWhiteSpacing;
+
+       // TODO: Fix in app_server: First glyph should not be shifted by delta.
+       x -= delta.nonspace;
+
+       view->DrawString(span.Text(), BPoint(x, y), &delta);
 }
diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.h 
b/src/apps/haiku-depot/textview/ParagraphLayout.h
index d0c3425..25cf2b7 100644
--- a/src/apps/haiku-depot/textview/ParagraphLayout.h
+++ b/src/apps/haiku-depot/textview/ParagraphLayout.h
@@ -89,6 +89,8 @@ public:
                height(0.0f),
                maxAscent(0.0f),
                maxDescent(0.0f),
+               extraGlyphSpacing(0.0f),
+               extraWhiteSpacing(0.0f),
                layoutedSpans()
        {
        }
@@ -101,6 +103,8 @@ public:
                height(height),
                maxAscent(maxAscent),
                maxDescent(maxDescent),
+               extraGlyphSpacing(0.0f),
+               extraWhiteSpacing(0.0f),
                layoutedSpans()
        {
        }
@@ -112,6 +116,8 @@ public:
                height(other.height),
                maxAscent(other.maxAscent),
                maxDescent(other.maxDescent),
+               extraGlyphSpacing(other.extraGlyphSpacing),
+               extraWhiteSpacing(other.extraWhiteSpacing),
                layoutedSpans(other.layoutedSpans)
        {
        }
@@ -123,6 +129,8 @@ public:
                height = other.height;
                maxAscent = other.maxAscent;
                maxDescent = other.maxDescent;
+               extraGlyphSpacing = other.extraGlyphSpacing;
+               extraWhiteSpacing = other.extraWhiteSpacing;
                layoutedSpans = other.layoutedSpans;
                return *this;
        }
@@ -134,6 +142,8 @@ public:
                        && height == other.height
                        && maxAscent == other.maxAscent
                        && maxDescent == other.maxDescent
+                       && extraGlyphSpacing == other.extraGlyphSpacing
+                       && extraWhiteSpacing == other.extraWhiteSpacing
                        && layoutedSpans == other.layoutedSpans;
        }
 
@@ -144,11 +154,16 @@ public:
 
 public:
        int32                   textOffset;
+
        float                   y;
        float                   height;
+
        float                   maxAscent;
        float                   maxDescent;
 
+       float                   extraGlyphSpacing;
+       float                   extraWhiteSpacing;
+
        TextSpanList    layoutedSpans;
 };
 
@@ -173,10 +188,12 @@ public:
                        void                            Draw(BView* view, const 
BPoint& offset);
 
 private:
+                       void                            _Init();
+
                        void                            _ValidateLayout();
                        void                            _Layout();
+                       void                            _ApplyAlignment();
 
-                       void                            _Init();
                        bool                            _AppendGlyphInfos(const 
TextSpan& span);
                        bool                            _AppendGlyphInfo(uint32 
charCode,
                                                                        float 
advanceX,
diff --git a/src/apps/haiku-depot/textview/TextDocumentTest.cpp 
b/src/apps/haiku-depot/textview/TextDocumentTest.cpp
index 292b19b..7d804b4 100644
--- a/src/apps/haiku-depot/textview/TextDocumentTest.cpp
+++ b/src/apps/haiku-depot/textview/TextDocumentTest.cpp
@@ -39,6 +39,7 @@ TextDocumentTest::ReadyToRun()
        ;
 
        ParagraphStyle paragraphStyle;
+       paragraphStyle.SetJustify(true);
        
        CharacterStyle regularStyle;
        


Other related posts:

  • » [haiku-commits] haiku: hrev46020 - src/apps/haiku-depot/textview - superstippi