hrev46019 adds 9 changesets to branch 'master' old head: 9fc96190794f1ae996a483258d5c3848a29aa5f6 new head: 68dfaf0f9d49a713685e93133b37c249535b62d7 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=68dfaf0+%5E9fc9619 ---------------------------------------------------------------------------- 2b7ea89: HaikuDepot: Give access to glyph spacing * The implementation for the get-accessors was missing from CharacterStyle. a452d51: HaikuDepot: Text stuff: Added line spacing to ParagraphStyle 036fabe: HaikuDepot: List: Changed parameter order for Replace() (index first) f668e7d: HaikuDepot: Text stuff: Switched from TextStyle to CharacterStyle 15990b0: HaikuDepot: Text stuff: ParagraphLayout compiles and maybe works d922357: HaikuDepot: CharacterStyle: Added convenience methods 4b810a1: HaikuDepot: TextDocument: Added Paragraph access by index. 24523b8: HaikuDepot: ParagraphLayout: Debugged and now working. * The biggest problem was that adding the wrapped sub-TextSpan to the LineInfos was missing. Other problems included missing handling of ascent and descent per CharacterStyle. 68dfaf0: HaikuDepot: New TextDocumentView and test app. * TextDocumentView still only shows the first paragraph of a TextDocument, but this time using the new ParagraphLayout. A class for layouting all paragraphs of a TextDocument is up next. * A simple test app shows that TextSpans with different CharacterStyles already work in one Paragraph. The test is nowhere extensive and does not test for bugs in corner cases. [ Stephan Aßmus <superstippi@xxxxxx> ] ---------------------------------------------------------------------------- 21 files changed, 893 insertions(+), 319 deletions(-) src/apps/haiku-depot/Jamfile | 33 +- src/apps/haiku-depot/List.h | 2 +- src/apps/haiku-depot/textview/CharacterStyle.cpp | 112 +++++ src/apps/haiku-depot/textview/CharacterStyle.h | 11 + .../haiku-depot/textview/CharacterStyleData.cpp | 39 ++ .../haiku-depot/textview/CharacterStyleData.h | 10 +- src/apps/haiku-depot/textview/Paragraph.cpp | 6 +- .../haiku-depot/textview/ParagraphLayout.cpp | 450 +++++++++---------- src/apps/haiku-depot/textview/ParagraphLayout.h | 142 ++++-- src/apps/haiku-depot/textview/ParagraphStyle.cpp | 61 +++ src/apps/haiku-depot/textview/ParagraphStyle.h | 3 + .../haiku-depot/textview/ParagraphStyleData.cpp | 15 + .../haiku-depot/textview/ParagraphStyleData.h | 5 + src/apps/haiku-depot/textview/TextDocument.cpp | 42 +- src/apps/haiku-depot/textview/TextDocument.h | 25 +- .../haiku-depot/textview/TextDocumentTest.cpp | 75 ++++ src/apps/haiku-depot/textview/TextDocumentTest.h | 21 + .../haiku-depot/textview/TextDocumentView.cpp | 105 +++++ src/apps/haiku-depot/textview/TextDocumentView.h | 41 ++ src/apps/haiku-depot/textview/TextSpan.cpp | 4 +- src/apps/haiku-depot/textview/TextSpan.h | 10 +- ############################################################################ Commit: 2b7ea89d14cc75ede0c96b67c3eb126545016d6b URL: http://cgit.haiku-os.org/haiku/commit/?id=2b7ea89 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 08:23:11 2013 UTC HaikuDepot: Give access to glyph spacing * The implementation for the get-accessors was missing from CharacterStyle. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/CharacterStyle.cpp b/src/apps/haiku-depot/textview/CharacterStyle.cpp index 9923bb2..07a120e 100644 --- a/src/apps/haiku-depot/textview/CharacterStyle.cpp +++ b/src/apps/haiku-depot/textview/CharacterStyle.cpp @@ -66,6 +66,13 @@ CharacterStyle::SetFont(const BFont& font) } +const BFont& +CharacterStyle::Font() const +{ + return fStyleData->Font(); +} + + bool CharacterStyle::SetAscent(float ascent) { @@ -78,6 +85,13 @@ CharacterStyle::SetAscent(float ascent) } +float +CharacterStyle::Ascent() const +{ + return fStyleData->Ascent(); +} + + bool CharacterStyle::SetDescent(float descent) { @@ -90,6 +104,13 @@ CharacterStyle::SetDescent(float descent) } +float +CharacterStyle::Descent() const +{ + return fStyleData->Descent(); +} + + bool CharacterStyle::SetWidth(float width) { @@ -102,6 +123,32 @@ CharacterStyle::SetWidth(float width) } +float +CharacterStyle::Width() const +{ + return fStyleData->Width(); +} + + +bool +CharacterStyle::SetGlyphSpacing(float spacing) +{ + CharacterStyleDataRef data = fStyleData->SetGlyphSpacing(spacing); + if (data == fStyleData) + return data->GlyphSpacing() == spacing; + + fStyleData = data; + return true; +} + + +float +CharacterStyle::GlyphSpacing() const +{ + return fStyleData->GlyphSpacing(); +} + + bool CharacterStyle::SetForegroundColor(rgb_color color) { @@ -114,6 +161,13 @@ CharacterStyle::SetForegroundColor(rgb_color color) } +rgb_color +CharacterStyle::ForegroundColor() const +{ + return fStyleData->ForegroundColor(); +} + + bool CharacterStyle::SetBackgroundColor(rgb_color color) { @@ -126,6 +180,13 @@ CharacterStyle::SetBackgroundColor(rgb_color color) } +rgb_color +CharacterStyle::BackgroundColor() const +{ + return fStyleData->BackgroundColor(); +} + + bool CharacterStyle::SetStrikeOutColor(rgb_color color) { @@ -138,6 +199,13 @@ CharacterStyle::SetStrikeOutColor(rgb_color color) } +rgb_color +CharacterStyle::StrikeOutColor() const +{ + return fStyleData->StrikeOutColor(); +} + + bool CharacterStyle::SetUnderlineColor(rgb_color color) { @@ -150,6 +218,13 @@ CharacterStyle::SetUnderlineColor(rgb_color color) } +rgb_color +CharacterStyle::UnderlineColor() const +{ + return fStyleData->UnderlineColor(); +} + + bool CharacterStyle::SetStrikeOut(uint8 strikeOut) { @@ -162,6 +237,13 @@ CharacterStyle::SetStrikeOut(uint8 strikeOut) } +uint8 +CharacterStyle::StrikeOut() const +{ + return fStyleData->StrikeOut(); +} + + bool CharacterStyle::SetUnderline(uint8 underline) { @@ -174,3 +256,10 @@ CharacterStyle::SetUnderline(uint8 underline) } +uint8 +CharacterStyle::Underline() const +{ + return fStyleData->Underline(); +} + + diff --git a/src/apps/haiku-depot/textview/CharacterStyle.h b/src/apps/haiku-depot/textview/CharacterStyle.h index eb6a7e6..c294eeb 100644 --- a/src/apps/haiku-depot/textview/CharacterStyle.h +++ b/src/apps/haiku-depot/textview/CharacterStyle.h @@ -29,6 +29,9 @@ public: bool SetWidth(float width); float Width() const; + bool SetGlyphSpacing(float spacing); + float GlyphSpacing() const; + bool SetForegroundColor(rgb_color color); rgb_color ForegroundColor() const; diff --git a/src/apps/haiku-depot/textview/CharacterStyleData.cpp b/src/apps/haiku-depot/textview/CharacterStyleData.cpp index a5a0401..d5f23fa 100644 --- a/src/apps/haiku-depot/textview/CharacterStyleData.cpp +++ b/src/apps/haiku-depot/textview/CharacterStyleData.cpp @@ -141,6 +141,21 @@ CharacterStyleData::SetWidth(float width) CharacterStyleDataRef +CharacterStyleData::SetGlyphSpacing(float glyphSpacing) +{ + if (fGlyphSpacing == glyphSpacing) + return CharacterStyleDataRef(this); + + CharacterStyleData* ret = new(std::nothrow) CharacterStyleData(*this); + if (ret == NULL) + return CharacterStyleDataRef(this); + + ret->fGlyphSpacing = glyphSpacing; + return CharacterStyleDataRef(ret, true); +} + + +CharacterStyleDataRef CharacterStyleData::SetForegroundColor(rgb_color color) { if (fFgColor == color) diff --git a/src/apps/haiku-depot/textview/CharacterStyleData.h b/src/apps/haiku-depot/textview/CharacterStyleData.h index c445aa8..3578994 100644 --- a/src/apps/haiku-depot/textview/CharacterStyleData.h +++ b/src/apps/haiku-depot/textview/CharacterStyleData.h @@ -57,6 +57,10 @@ public: inline float Width() const { return fWidth; } + CharacterStyleDataRef SetGlyphSpacing(float glyphSpacing); + inline float GlyphSpacing() const + { return fGlyphSpacing; } + CharacterStyleDataRef SetForegroundColor(rgb_color color); inline rgb_color ForegroundColor() const { return fFgColor; } ############################################################################ Commit: a452d517051e06b65914dca36bf8af219b21b2ac URL: http://cgit.haiku-os.org/haiku/commit/?id=a452d51 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 08:57:19 2013 UTC HaikuDepot: Text stuff: Added line spacing to ParagraphStyle ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/ParagraphStyle.cpp b/src/apps/haiku-depot/textview/ParagraphStyle.cpp index 21a96a6..2fd6b3e 100644 --- a/src/apps/haiku-depot/textview/ParagraphStyle.cpp +++ b/src/apps/haiku-depot/textview/ParagraphStyle.cpp @@ -66,6 +66,13 @@ ParagraphStyle::SetAlignment(::Alignment alignment) } +::Alignment +ParagraphStyle::Alignment() const +{ + return fStyleData->Alignment(); +} + + bool ParagraphStyle::SetJustify(bool justify) { @@ -79,6 +86,13 @@ ParagraphStyle::SetJustify(bool justify) bool +ParagraphStyle::Justify() const +{ + return fStyleData->Justify(); +} + + +bool ParagraphStyle::SetFirstLineInset(float inset) { ParagraphStyleDataRef data = fStyleData->SetFirstLineInset(inset); @@ -90,6 +104,13 @@ ParagraphStyle::SetFirstLineInset(float inset) } +float +ParagraphStyle::FirstLineInset() const +{ + return fStyleData->FirstLineInset(); +} + + bool ParagraphStyle::SetLineInset(float inset) { @@ -102,6 +123,32 @@ ParagraphStyle::SetLineInset(float inset) } +float +ParagraphStyle::LineInset() const +{ + return fStyleData->LineInset(); +} + + +bool +ParagraphStyle::SetLineSpacing(float spacing) +{ + ParagraphStyleDataRef data = fStyleData->SetLineSpacing(spacing); + if (data == fStyleData) + return data->LineSpacing() == spacing; + + fStyleData = data; + return true; +} + + +float +ParagraphStyle::LineSpacing() const +{ + return fStyleData->LineSpacing(); +} + + bool ParagraphStyle::SetSpacingTop(float spacing) { @@ -114,6 +161,13 @@ ParagraphStyle::SetSpacingTop(float spacing) } +float +ParagraphStyle::SpacingTop() const +{ + return fStyleData->SpacingTop(); +} + + bool ParagraphStyle::SetSpacingBottom(float spacing) { @@ -126,3 +180,10 @@ ParagraphStyle::SetSpacingBottom(float spacing) } +float +ParagraphStyle::SpacingBottom() const +{ + return fStyleData->SpacingBottom(); +} + + diff --git a/src/apps/haiku-depot/textview/ParagraphStyle.h b/src/apps/haiku-depot/textview/ParagraphStyle.h index 8c9de53..ec52573 100644 --- a/src/apps/haiku-depot/textview/ParagraphStyle.h +++ b/src/apps/haiku-depot/textview/ParagraphStyle.h @@ -29,6 +29,9 @@ public: bool SetLineInset(float inset); float LineInset() const; + bool SetLineSpacing(float spacing); + float LineSpacing() const; + bool SetSpacingTop(float spacing); float SpacingTop() const; diff --git a/src/apps/haiku-depot/textview/ParagraphStyleData.cpp b/src/apps/haiku-depot/textview/ParagraphStyleData.cpp index d943c21..d36a0ac 100644 --- a/src/apps/haiku-depot/textview/ParagraphStyleData.cpp +++ b/src/apps/haiku-depot/textview/ParagraphStyleData.cpp @@ -119,6 +119,21 @@ ParagraphStyleData::SetLineInset(float inset) ParagraphStyleDataRef +ParagraphStyleData::SetLineSpacing(float spacing) +{ + if (fLineSpacing == spacing) + return ParagraphStyleDataRef(this); + + ParagraphStyleData* ret = new(std::nothrow) ParagraphStyleData(*this); + if (ret == NULL) + return ParagraphStyleDataRef(this); + + ret->fLineSpacing = spacing; + return ParagraphStyleDataRef(ret, true); +} + + +ParagraphStyleDataRef ParagraphStyleData::SetSpacingTop(float spacing) { if (fSpacingTop == spacing) diff --git a/src/apps/haiku-depot/textview/ParagraphStyleData.h b/src/apps/haiku-depot/textview/ParagraphStyleData.h index c209643..cce60a1 100644 --- a/src/apps/haiku-depot/textview/ParagraphStyleData.h +++ b/src/apps/haiku-depot/textview/ParagraphStyleData.h @@ -48,6 +48,10 @@ public: inline float LineInset() const { return fLineInset; } + ParagraphStyleDataRef SetLineSpacing(float spacing); + inline float LineSpacing() const + { return fLineSpacing; } + ParagraphStyleDataRef SetSpacingTop(float spacing); inline float SpacingTop() const { return fSpacingTop; } @@ -65,6 +69,7 @@ private: float fFirstLineInset; float fLineInset; + float fLineSpacing; float fSpacingTop; float fSpacingBottom; ############################################################################ Commit: 036fabe903c1ba8f6f6dad8ac5a09f5b10eb7026 URL: http://cgit.haiku-os.org/haiku/commit/?id=036fabe Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 08:58:16 2013 UTC HaikuDepot: List: Changed parameter order for Replace() (index first) ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/List.h b/src/apps/haiku-depot/List.h index 0c216e3..eb229aa 100644 --- a/src/apps/haiku-depot/List.h +++ b/src/apps/haiku-depot/List.h @@ -172,7 +172,7 @@ public: } - inline bool Replace(const ItemType& copyFrom, int32 index) + inline bool Replace(int32 index, const ItemType& copyFrom) { if (index < 0 || index >= (int32)fCount) return false; diff --git a/src/apps/haiku-depot/textview/Paragraph.cpp b/src/apps/haiku-depot/textview/Paragraph.cpp index b5eede5..43157eb3 100644 --- a/src/apps/haiku-depot/textview/Paragraph.cpp +++ b/src/apps/haiku-depot/textview/Paragraph.cpp @@ -99,7 +99,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan) TextSpan span = fTextSpans.ItemAtFast(index); if (span.Style() == newSpan.Style()) { span.Insert(offset, newSpan.Text()); - return fTextSpans.Replace(span, index); + return fTextSpans.Replace(index, span); } if (offset == 0) { @@ -108,7 +108,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan) TextSpan span = fTextSpans.ItemAtFast(index - 1); if (span.Style() == newSpan.Style()) { span.Insert(span.CharCount(), newSpan.Text()); - return fTextSpans.Replace(span, index - 1); + return fTextSpans.Replace(index - 1, span); } } // Just insert the new span before the one at index @@ -119,7 +119,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan) TextSpan spanBefore = span.SubSpan(0, offset); TextSpan spanAfter = span.SubSpan(offset, span.CharCount() - offset); - return fTextSpans.Replace(spanBefore, index) + return fTextSpans.Replace(index, spanBefore) && fTextSpans.Add(newSpan, index + 1) && fTextSpans.Add(spanAfter, index + 2); } ############################################################################ Commit: f668e7dd19aad3ef5b3ce0a5235af5193b5a6463 URL: http://cgit.haiku-os.org/haiku/commit/?id=f668e7d Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 08:59:03 2013 UTC HaikuDepot: Text stuff: Switched from TextStyle to CharacterStyle ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/TextDocument.cpp b/src/apps/haiku-depot/textview/TextDocument.cpp index 7bb089f..e77d51b 100644 --- a/src/apps/haiku-depot/textview/TextDocument.cpp +++ b/src/apps/haiku-depot/textview/TextDocument.cpp @@ -10,17 +10,17 @@ TextDocument::TextDocument() : fParagraphs(), fEmptyLastParagraph(), - fDefaultTextStyle() + fDefaultCharacterStyle() { } -TextDocument::TextDocument(const TextStyle& textStyle, +TextDocument::TextDocument(const CharacterStyle& CharacterStyle, const ParagraphStyle& paragraphStyle) : fParagraphs(), fEmptyLastParagraph(paragraphStyle), - fDefaultTextStyle(textStyle) + fDefaultCharacterStyle(CharacterStyle) { } @@ -29,7 +29,7 @@ TextDocument::TextDocument(const TextDocument& other) : fParagraphs(other.fParagraphs), fEmptyLastParagraph(other.fEmptyLastParagraph), - fDefaultTextStyle(other.fDefaultTextStyle) + fDefaultCharacterStyle(other.fDefaultCharacterStyle) { } @@ -39,7 +39,7 @@ TextDocument::operator=(const TextDocument& other) { fParagraphs = other.fParagraphs; fEmptyLastParagraph = other.fEmptyLastParagraph; - fDefaultTextStyle = other.fDefaultTextStyle; + fDefaultCharacterStyle = other.fDefaultCharacterStyle; return *this; } @@ -52,7 +52,7 @@ TextDocument::operator==(const TextDocument& other) const return true; return fEmptyLastParagraph == other.fEmptyLastParagraph - && fDefaultTextStyle == other.fDefaultTextStyle + && fDefaultCharacterStyle == other.fDefaultCharacterStyle && fParagraphs == other.fParagraphs; } @@ -70,12 +70,12 @@ TextDocument::operator!=(const TextDocument& other) const status_t TextDocument::Insert(int32 offset, const BString& text) { - return Insert(offset, text, TextStyleAt(offset)); + return Insert(offset, text, CharacterStyleAt(offset)); } status_t -TextDocument::Insert(int32 offset, const BString& text, const TextStyle& style) +TextDocument::Insert(int32 offset, const BString& text, const CharacterStyle& style) { return Insert(offset, text, style, ParagraphStyleAt(offset)); } @@ -83,9 +83,9 @@ TextDocument::Insert(int32 offset, const BString& text, const TextStyle& style) status_t TextDocument::Insert(int32 offset, const BString& text, - const TextStyle& textStyle, const ParagraphStyle& paragraphStyle) + const CharacterStyle& CharacterStyle, const ParagraphStyle& paragraphStyle) { - return Replace(offset, 0, text, textStyle, paragraphStyle); + return Replace(offset, 0, text, CharacterStyle, paragraphStyle); } @@ -106,13 +106,13 @@ TextDocument::Remove(int32 offset, int32 length) status_t TextDocument::Replace(int32 offset, int32 length, const BString& text) { - return Replace(offset, length, text, TextStyleAt(offset)); + return Replace(offset, length, text, CharacterStyleAt(offset)); } status_t TextDocument::Replace(int32 offset, int32 length, const BString& text, - const TextStyle& style) + const CharacterStyle& style) { return Replace(offset, length, text, style, ParagraphStyleAt(offset)); } @@ -120,7 +120,7 @@ TextDocument::Replace(int32 offset, int32 length, const BString& text, status_t TextDocument::Replace(int32 offset, int32 length, const BString& text, - const TextStyle& textStyle, const ParagraphStyle& paragraphStyle) + const CharacterStyle& CharacterStyle, const ParagraphStyle& paragraphStyle) { // TODO: Implement return B_ERROR; @@ -130,8 +130,8 @@ TextDocument::Replace(int32 offset, int32 length, const BString& text, // #pragma mark - -const TextStyle& -TextDocument::TextStyleAt(int32 textOffset) const +const CharacterStyle& +TextDocument::CharacterStyleAt(int32 textOffset) const { int32 paragraphOffset; const Paragraph& paragraph = ParagraphAt(textOffset, paragraphOffset); @@ -147,8 +147,7 @@ TextDocument::TextStyleAt(int32 textOffset) const textOffset -= span.CharCount(); } - // TODO: Document should have a default TextStyle? - return fDefaultTextStyle; + return fDefaultCharacterStyle; } diff --git a/src/apps/haiku-depot/textview/TextDocument.h b/src/apps/haiku-depot/textview/TextDocument.h index 542daa3..0dbe42e 100644 --- a/src/apps/haiku-depot/textview/TextDocument.h +++ b/src/apps/haiku-depot/textview/TextDocument.h @@ -5,6 +5,7 @@ #ifndef TEXT_DOCUMENT_H #define TEXT_DOCUMENT_H +#include "CharacterStyle.h" #include "List.h" #include "Paragraph.h" @@ -15,7 +16,8 @@ typedef List<Paragraph, false> ParagraphList; class TextDocument { public: TextDocument(); - TextDocument(const TextStyle& textStyle, + TextDocument( + const CharacterStyle& characterStyle, const ParagraphStyle& paragraphStyle); TextDocument(const TextDocument& other); @@ -26,9 +28,9 @@ public: // Text insertion and removing status_t Insert(int32 offset, const BString& text); status_t Insert(int32 offset, const BString& text, - const TextStyle& style); + const CharacterStyle& style); status_t Insert(int32 offset, const BString& text, - const TextStyle& textStyle, + const CharacterStyle& characterStyle, const ParagraphStyle& paragraphStyle); status_t Remove(int32 offset, int32 length); @@ -37,14 +39,14 @@ public: const BString& text); status_t Replace(int32 offset, int32 length, const BString& text, - const TextStyle& style); + const CharacterStyle& style); status_t Replace(int32 offset, int32 length, const BString& text, - const TextStyle& textStyle, + const CharacterStyle& characterStyle, const ParagraphStyle& paragraphStyle); // Style access - const TextStyle& TextStyleAt(int32 textOffset) const; + const CharacterStyle& CharacterStyleAt(int32 textOffset) const; const ParagraphStyle& ParagraphStyleAt(int32 textOffset) const; // Paragraph access @@ -59,7 +61,7 @@ public: private: ParagraphList fParagraphs; Paragraph fEmptyLastParagraph; - TextStyle fDefaultTextStyle; + CharacterStyle fDefaultCharacterStyle; }; diff --git a/src/apps/haiku-depot/textview/TextSpan.cpp b/src/apps/haiku-depot/textview/TextSpan.cpp index daa0e69..e13d84d 100644 --- a/src/apps/haiku-depot/textview/TextSpan.cpp +++ b/src/apps/haiku-depot/textview/TextSpan.cpp @@ -15,7 +15,7 @@ TextSpan::TextSpan() } -TextSpan::TextSpan(const BString& text, const TextStyle& style) +TextSpan::TextSpan(const BString& text, const CharacterStyle& style) : fText(text), fCharCount(text.CountChars()), @@ -69,7 +69,7 @@ TextSpan::SetText(const BString& text) void -TextSpan::SetStyle(const TextStyle& style) +TextSpan::SetStyle(const CharacterStyle& style) { fStyle = style; } diff --git a/src/apps/haiku-depot/textview/TextSpan.h b/src/apps/haiku-depot/textview/TextSpan.h index 88bbddc..b662525 100644 --- a/src/apps/haiku-depot/textview/TextSpan.h +++ b/src/apps/haiku-depot/textview/TextSpan.h @@ -8,14 +8,14 @@ #include <String.h> -#include "TextStyle.h" +#include "CharacterStyle.h" class TextSpan { public: TextSpan(); TextSpan(const BString& text, - const TextStyle& style); + const CharacterStyle& style); TextSpan(const TextSpan& other); TextSpan& operator=(const TextSpan& other); @@ -26,8 +26,8 @@ public: inline const BString& Text() const { return fText; } - void SetStyle(const TextStyle& style); - inline const TextStyle& Style() const + void SetStyle(const CharacterStyle& style); + inline const CharacterStyle& Style() const { return fStyle; } inline int32 CharCount() const @@ -46,7 +46,7 @@ private: private: BString fText; int32 fCharCount; - TextStyle fStyle; + CharacterStyle fStyle; }; ############################################################################ Commit: 15990b01a269a7f5af9eddeb98a70417f8e59197 URL: http://cgit.haiku-os.org/haiku/commit/?id=15990b0 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 08:59:39 2013 UTC HaikuDepot: Text stuff: ParagraphLayout compiles and maybe works ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/Jamfile b/src/apps/haiku-depot/Jamfile index b9ed0aa..22335f5 100644 --- a/src/apps/haiku-depot/Jamfile +++ b/src/apps/haiku-depot/Jamfile @@ -30,6 +30,7 @@ Application HaikuDepot : CharacterStyle.cpp CharacterStyleData.cpp Paragraph.cpp + ParagraphLayout.cpp ParagraphStyle.cpp ParagraphStyleData.cpp TextDocument.cpp diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.cpp b/src/apps/haiku-depot/textview/ParagraphLayout.cpp index c0ff872..ef8336c 100644 --- a/src/apps/haiku-depot/textview/ParagraphLayout.cpp +++ b/src/apps/haiku-depot/textview/ParagraphLayout.cpp @@ -19,10 +19,6 @@ #include <utf8_functions.h> #include <View.h> -#include "GlyphInfo.h" -#include "List.h" -#include "TextStyle.h" - enum { CHAR_CLASS_DEFAULT, @@ -98,22 +94,24 @@ get_char_classification(uint32 charCode) inline bool -can_end_line(const GlyphInfo* buffer, int offset, int count) +can_end_line(const GlyphInfoList& glyphInfos, int offset) { + int count = glyphInfos.CountItems(); + if (offset == count - 1) return true; if (offset < 0 || offset > count) return false; - uint32 charCode = buffer[offset].charCode; + uint32 charCode = glyphInfos.ItemAtFast(offset).charCode; uint32 classification = get_char_classification(charCode); // wrapping is always allowed at end of text and at newlines if (classification == CHAR_CLASS_END_OF_TEXT || charCode == '\n') return true; - uint32 nextCharCode = buffer[offset + 1].charCode; + uint32 nextCharCode = glyphInfos.ItemAtFast(offset + 1).charCode; uint32 nextClassification = get_char_classification(nextCharCode); // never separate a punctuation char from its preceding word @@ -166,15 +164,13 @@ can_end_line(const GlyphInfo* buffer, int offset, int count) ParagraphLayout::ParagraphLayout() : fTextSpans(), - fWidth(0.0f), + fParagraphStyle(), + fWidth(0.0f), fLayoutValid(false), - fGlyphInfoBuffer(NULL), - fGlpyhInfoBufferSize(0), - fGlyphInfoCount(0), - - fLayoutLines() + fGlyphInfos(), + fLineInfos() { } @@ -182,15 +178,13 @@ ParagraphLayout::ParagraphLayout() ParagraphLayout::ParagraphLayout(const Paragraph& paragraph) : fTextSpans(paragraph.TextSpans()), - fWidth(other.fWidth), + fParagraphStyle(paragraph.Style()), + fWidth(0.0f), fLayoutValid(false), - fGlyphInfoBuffer(NULL), - fGlpyhInfoBufferSize(0), - fGlyphInfoCount(0), - - fLayoutLines() + fGlyphInfos(), + fLineInfos() { _Init(); } @@ -199,15 +193,13 @@ ParagraphLayout::ParagraphLayout(const Paragraph& paragraph) ParagraphLayout::ParagraphLayout(const ParagraphLayout& other) : fTextSpans(other.fTextSpans), + fParagraphStyle(other.fParagraphStyle), + fWidth(other.fWidth), - fLayoutValid(false), - fGlyphInfoBuffer(NULL), - fGlpyhInfoBufferSize(0), - fGlyphInfoCount(0), - - fLayoutLines() + fGlyphInfos(), + fLineInfos() { _Init(); } @@ -215,7 +207,18 @@ ParagraphLayout::ParagraphLayout(const ParagraphLayout& other) ParagraphLayout::~ParagraphLayout() { - delete[] fGlyphInfoBuffer; +} + + +void +ParagraphLayout::SetParagraph(const Paragraph& paragraph) +{ + fTextSpans = paragraph.TextSpans(); + fParagraphStyle = paragraph.Style(); + + _Init(); + + fLayoutValid = false; } @@ -236,8 +239,8 @@ ParagraphLayout::Height() float height = 0.0f; - if (fLayoutLines.CountItems() > 0) { - const LayoutLine& lastLine = fLayoutLines.LastItem(); + if (fLineInfos.CountItems() > 0) { + const LineInfo& lastLine = fLineInfos.LastItem(); height = lastLine.y + lastLine.height; } @@ -250,9 +253,9 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset) { _ValidateLayout(); - int lineCount = fLayoutLines.CountItems(); + int lineCount = fLineInfos.CountItems(); for (int i = 0; i < lineCount; i++) { - const LayoutLine& line = fLayoutLines.ItemAtFast(i); + const LineInfo& line = fLineInfos.ItemAtFast(i); _DrawLine(view, line); } } @@ -272,51 +275,26 @@ ParagraphLayout::_ValidateLayout() void ParagraphLayout::_Layout() { - fLayoutLines.Clear(); - -// int charCount = fText.CountChars(); -// if (charCount == 0) -// return; -// -// // Allocate arrays -// float* escapementArray = new (std::nothrow) float[charCount]; -// if (escapementArray == NULL) -// return; -// ArrayDeleter<float> escapementDeleter(escapementArray); -// -// // Fetch glyph spacing information -// fDefaultFont.GetEscapements(fText.String(), charCount, escapementArray); -// -// // Convert to glyph buffer -// fGlyphInfoCount = charCount; -// fGlyphInfoBuffer = new (std::nothrow) GlyphInfo[fGlyphInfoCount]; -// -// // Init glyph buffer and convert escapement scale -// float size = fDefaultFont.Size(); -// const char* c = fText.String(); -// for (int i = 0; i < fGlyphInfoCount; i++) { -// fGlyphInfoBuffer[i].charCode = UTF8ToCharCode(&c); -// escapementArray[i] *= size; -// } -// -// -// float x = fFirstLineInset; -// float y = 0.0f; -// int lineIndex = 0; -// int lineStart = 0; -// -// for (int i = 0; i < fGlyphInfoCount; i++) { -// uint32 charClassification = get_char_classification( -// fGlyphInfoBuffer[i].charCode); -// -// float advanceX = 0.0f; -// float advanceY = 0.0f; -// _GetGlyphAdvance(i, advanceX, advanceY, escapementArray); -// -// bool nextLine = false; -// bool lineBreak = false; -// -// if (fGlyphInfoBuffer[i].charCode == '\t') { + fLineInfos.Clear(); + + float x = fParagraphStyle.FirstLineInset(); + float y = 0.0f; + int lineIndex = 0; + int lineStart = 0; + + int glyphCount = fGlyphInfos.CountItems(); + for (int i = 0; i < glyphCount; i++) { + GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); + + uint32 charClassification = get_char_classification(glyph.charCode); + + float advanceX = glyph.width; + float advanceY = 0.0f; + + bool nextLine = false; + bool lineBreak = false; + +// if (glyph.charCode == '\t') { // // Figure out tab width, it's the width between the last two tab // // stops. // float tabWidth = 0.0f; @@ -342,92 +320,90 @@ ParagraphLayout::_Layout() // if (tabOffset - x > 0.0) // advanceX = tabOffset - x; // } -// -// fGlyphInfoBuffer[i].advanceX = advanceX; -// -// if (fGlyphInfoBuffer[i].charCode == '\n') { -// nextLine = true; -// lineBreak = true; -// fGlyphInfoBuffer[i].x = x; -// fGlyphInfoBuffer[i].y = y; -// } else if (fWidth > 0.0f && x + advanceX > fWidth) { -// if (charClassification == CHAR_CLASS_WHITESPACE) { -// advanceX = 0.0f; -// } else if (i > lineStart) { -// nextLine = true; -// // The current glyph extends outside the width, we need to wrap -// // to the next line. See what previous offset can be the end -// // of the line. -// int lineEnd = i - 1; -// while (lineEnd > lineStart -// && !can_end_line(fGlyphInfoBuffer, lineEnd, -// fGlyphInfoCount)) { -// lineEnd--; -// } -// -// if (lineEnd > lineStart) { -// // Found a place to perform a line break. -// i = lineEnd + 1; -// // Adjust the glyph info to point at the changed buffer -// // position -// _GetGlyphAdvance(i, advanceX, advanceY, escapementArray); -// } else { -// // Just break where we are. -// } -// } -// } -// -// if (nextLine) { -// // * Initialize the max ascent/descent of all preceding glyph infos -// // on the current/last line -// // * Adjust the baseline offset according to the max ascent -// // * Fill in the line index. -// unsigned lineEnd; -// if (lineBreak) -// lineEnd = i; -// else -// lineEnd = i - 1; -// -// float lineHeight = 0.0; -// _FinalizeLine(lineStart, lineEnd, lineIndex, y, -// lineHeight); -// -// // Start position of the next line -// x = fLineInset; -// y += lineHeight + fLineSpacing; -// -// if (lineBreak) -// lineStart = i + 1; -// else -// lineStart = i; -// -// lineIndex++; -// } -// -// if (!lineBreak && i < fGlyphInfoCount) { -// fGlyphInfoBuffer[i].x = x; -// fGlyphInfoBuffer[i].y = y; -// } -// -// x += advanceX; -// y += advanceY; -// } -// -// // The last line may not have been appended and initialized yet. -// if (lineStart <= fGlyphInfoCount - 1) { -// float lineHeight; -// _FinalizeLine(lineStart, fGlyphInfoCount - 1, lineIndex, y, lineHeight); -// } + + glyph.advanceX = advanceX; + + if (glyph.charCode == '\n') { + nextLine = true; + lineBreak = true; + glyph.x = x; + fGlyphInfos.Replace(i, glyph); + } else if (fWidth > 0.0f && x + advanceX > fWidth) { + fGlyphInfos.Replace(i, glyph); + if (charClassification == CHAR_CLASS_WHITESPACE) { + advanceX = 0.0f; + } else if (i > lineStart) { + nextLine = true; + // The current glyph extends outside the width, we need to wrap + // to the next line. See what previous offset can be the end + // of the line. + int lineEnd = i - 1; + while (lineEnd > lineStart + && !can_end_line(fGlyphInfos, lineEnd)) { + lineEnd--; + } + + if (lineEnd > lineStart) { + // Found a place to perform a line break. + i = lineEnd + 1; + + // Adjust the glyph info to point at the changed buffer + // position + glyph = fGlyphInfos.ItemAtFast(i); + advanceX = glyph.width; + } else { + // Just break where we are. + } + } + } + + if (nextLine) { + // * Initialize the max ascent/descent of all preceding glyph infos + // on the current/last line + // * Adjust the baseline offset according to the max ascent + // * Fill in the line index. + unsigned lineEnd; + if (lineBreak) + lineEnd = i; + else + lineEnd = i - 1; + + float lineHeight = 0.0; + _FinalizeLine(lineStart, lineEnd, lineIndex, y, lineHeight); + + // Start position of the next line + x = fParagraphStyle.LineInset(); + y += lineHeight + fParagraphStyle.LineSpacing(); + + if (lineBreak) + lineStart = i + 1; + else + lineStart = i; + + lineIndex++; + } + + if (!lineBreak && i < glyphCount) { + glyph.x = x; + fGlyphInfos.Replace(i, glyph); + } + + x += advanceX; + y += advanceY; + } + + // The last line may not have been appended and initialized yet. + if (lineStart <= glyphCount - 1) { + float lineHeight; + _FinalizeLine(lineStart, glyphCount - 1, lineIndex, y, lineHeight); + } } void ParagraphLayout::_Init() { - delete[] fGlyphInfoBuffer; - fGlyphInfoBuffer = NULL; - fGlpyhInfoBufferSize = 0; - fGlyphInfoCount = 0; + fGlyphInfos.Clear(); int spanCount = fTextSpans.CountItems(); for (int i = 0; i < spanCount; i++) { @@ -449,7 +425,7 @@ ParagraphLayout::_AppendGlyphInfos(const TextSpan& span) return true; const BString& text = span.Text(); - const BFont& font = span.Style().font; + const BFont& font = span.Style().Font(); // Allocate arrays float* escapementArray = new (std::nothrow) float[charCount]; @@ -464,112 +440,68 @@ ParagraphLayout::_AppendGlyphInfos(const TextSpan& span) float size = font.Size(); const char* c = text.String(); for (int i = 0; i < charCount; i++) { - _AppendGlyphInfo(UTF8ToCharCode(&c), ); - fGlyphInfoBuffer[i].charCode = ; - escapementArray[i] *= size; - } - -} - - -bool -ParagraphLayout::_AppendGlyphInfo(uint32 charCode, const TextStyleRef& style) -{ - // Enlarge buffer if necessary - if (fGlyphInfoCount == fGlyphInfoBufferSize) { - int size = fGlyphInfoBufferSize + 64; - - GlyphInfo* buffer = (GlyphInfo*) realloc(fGlyphInfoBuffer, - size * sizeof(GlyphInfo)); - if (buffer == NULL) + if (!_AppendGlyphInfo(UTF8ToCharCode(&c), escapementArray[i] * size, + span.Style())) { return false; - - fGlyphInfoBufferSize = size; - fGlyphInfoBuffer = buffer; + } } - // Store given information - fGlyphInfoBuffer[fGlyphInfoCount].charCode = charCode; - fGlyphInfoBuffer[fGlyphInfoCount].glyph = glyph; - fGlyphInfoBuffer[fGlyphInfoCount].x = 0; - fGlyphInfoBuffer[fGlyphInfoCount].y = 0; - fGlyphInfoBuffer[fGlyphInfoCount].advanceX = 0; - fGlyphInfoBuffer[fGlyphInfoCount].maxAscend = 0; - fGlyphInfoBuffer[fGlyphInfoCount].maxDescend = 0; - fGlyphInfoBuffer[fGlyphInfoCount].lineIndex = 0; - fGlyphInfoBuffer[fGlyphInfoCount].styleRun = styleRun; - - fGlyphInfoCount++; - return true; } -void -ParagraphLayout::_GetGlyphAdvance(int offset, float& advanceX, float& advanceY, - float escapementArray[]) const +bool +ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float width, + const CharacterStyle& style) { - float additionalGlyphSpacing = 0.0f; - if (fGlyphInfoBuffer[offset].style.Get() != NULL) - additionalGlyphSpacing = fGlyphInfoBuffer[offset].style->glyphSpacing; - else - additionalGlyphSpacing = fGlyphSpacing; - - if (fGlyphInfoBuffer[offset].style.Get() != NULL - && fGlyphInfoBuffer[offset].style->width > 0.0f) { - // Use the metrics provided by the TextStyle - advanceX = fGlyphInfoBuffer[offset].style->width - + additionalGlyphSpacing; - } else { - advanceX = escapementArray[offset] + additionalGlyphSpacing; - advanceY = 0.0f; + if (style.Width() >= 0.0f) { + // Use the metrics provided by the CharacterStyle and override + // the font provided metrics passed in "width" + width = style.Width(); } + + width += style.GlyphSpacing(); + + GlyphInfo glyph(charCode, 0.0f, width, width, 0, style); + return fGlyphInfos.Add(glyph); } void -ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex, float y, - float& lineHeight) +ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex, + float y, float& lineHeight) { lineHeight = 0.0f; float maxAscent = 0.0f; float maxDescent = 0.0f; for (int i = lineStart; i <= lineEnd; i++) { - if (fGlyphInfoBuffer[i].style.Get() != NULL) { - if (fGlyphInfoBuffer[i].style->font.Size() > lineHeight) - lineHeight = fGlyphInfoBuffer[i].style->font.Size(); - if (fGlyphInfoBuffer[i].style->ascent > maxAscent) - maxAscent = fGlyphInfoBuffer[i].style->ascent; - if (fGlyphInfoBuffer[i].style->descent > maxDescent) - maxDescent = fGlyphInfoBuffer[i].style->descent; - } else { - if (fDefaultFont.Size() > lineHeight) - lineHeight = fDefaultFont.Size(); - if (fAscent > maxAscent) - maxAscent = fAscent; - if (fDescent > maxDescent) - maxDescent = fDescent; - } + GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); + glyph.lineIndex = lineIndex; + fGlyphInfos.Replace(i, glyph); + + const CharacterStyle& style = glyph.style; + + if (style.Font().Size() > lineHeight) + lineHeight = style.Font().Size(); + + if (style.Ascent() > maxAscent) + maxAscent = style.Ascent(); + + if (style.Descent() > maxDescent) + maxDescent = style.Descent(); } - fLayoutLines.Add(LayoutLine(lineStart, y, lineHeight, maxAscent, maxDescent)); - - for (int i = lineStart; i <= lineEnd; i++) { - fGlyphInfoBuffer[i].maxAscent = maxAscent; - fGlyphInfoBuffer[i].maxDescent = maxDescent; - fGlyphInfoBuffer[i].lineIndex = lineIndex; - fGlyphInfoBuffer[i].y += maxAscent; - } + fLineInfos.Add(LineInfo(lineStart, y, lineHeight, maxAscent, maxDescent)); } void -ParagraphLayout::_DrawLine(BView* view, const LayoutLine& line) const +ParagraphLayout::_DrawLine(BView* view, const LineInfo& line) const { int textOffset = line.textOffset; int spanCount = line.layoutedSpans.CountItems(); - for (int i = 0; i < spanCount) { + for (int i = 0; i < spanCount; i++) { const TextSpan& span = line.layoutedSpans.ItemAtFast(i); _DrawSpan(view, span, textOffset); textOffset += span.CharCount(); @@ -579,15 +511,18 @@ ParagraphLayout::_DrawLine(BView* view, const LayoutLine& line) const void ParagraphLayout::_DrawSpan(BView* view, const TextSpan& span, - int textOffset) const + int32 textOffset) const { - float x = fGlyphInfoBuffer[textOffset].x; - float y = fGlyphInfoBuffer[textOffset].y; + const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset); + const LineInfo& line = fLineInfos.ItemAtFast(glyph.lineIndex); + + float x = glyph.x; + float y = line.y + line.maxAscent; - const TextStyle& style = span.Style(); + const CharacterStyle& style = span.Style(); - view->SetFont(&style.font); - view->SetHighColor(style.fgColor); + view->SetFont(&style.Font()); + view->SetHighColor(style.ForegroundColor()); // TODO: Implement other style properties // TODO: Implement correct glyph spacing diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.h b/src/apps/haiku-depot/textview/ParagraphLayout.h index 0ff8599..be838e5 100644 --- a/src/apps/haiku-depot/textview/ParagraphLayout.h +++ b/src/apps/haiku-depot/textview/ParagraphLayout.h @@ -9,26 +9,117 @@ #include <Referenceable.h> #include <String.h> -#include "GlyphInfo.h" #include "Paragraph.h" +#include "CharacterStyle.h" class BView; -class LayoutLine { +class GlyphInfo { public: - LayoutLine() + GlyphInfo() + : + charCode(0), + x(0.0f), + width(0.0f), + advanceX(0.0f), + lineIndex(0), + style() + { + } + + GlyphInfo(uint32 charCode, float x, float width, float advanceX, + int32 lineIndex, const CharacterStyle& style) + : + charCode(charCode), + x(x), + width(width), + advanceX(advanceX), + lineIndex(lineIndex), + style(style) + { + } + + GlyphInfo(const GlyphInfo& other) + : + charCode(other.charCode), + x(other.x), + width(other.width), + advanceX(other.advanceX), + lineIndex(other.lineIndex), + style(other.style) + { + } + + GlyphInfo& operator=(const GlyphInfo& other) + { + charCode = other.charCode; + x = other.x; + width = other.width; + advanceX = other.advanceX; + lineIndex = other.lineIndex; + style = other.style; + return *this; + } + + bool operator==(const GlyphInfo& other) const + { + return charCode == other.charCode + && x == other.x + && width == other.width + && advanceX == other.advanceX + && lineIndex == other.lineIndex + && style == other.style; + } + + bool operator!=(const GlyphInfo& other) const + { + return !(*this == other); + } + +public: + uint32 charCode; + + float x; + float width; + float advanceX; + + int32 lineIndex; + + CharacterStyle style; +}; + + +typedef List<GlyphInfo, false> GlyphInfoList; + + +class LineInfo { +public: + LineInfo() : textOffset(0), y(0.0f), height(0.0f), maxAscent(0.0f), - maxDescent(0.0f) + maxDescent(0.0f), + layoutedSpans() { } - LayoutLine(const LayoutLine& other) + LineInfo(int32 textOffset, float y, float height, float maxAscent, + float maxDescent) + : + textOffset(textOffset), + y(y), + height(height), + maxAscent(maxAscent), + maxDescent(maxDescent), + layoutedSpans() + { + } + + LineInfo(const LineInfo& other) : textOffset(other.textOffset), y(other.y), @@ -39,7 +130,7 @@ public: { } - LayoutLine& operator=(const LayoutLine& other) + LineInfo& operator=(const LineInfo& other) { textOffset = other.textOffset; y = other.y; @@ -50,23 +141,23 @@ public: return *this; } - bool operator==(const LayoutLine& other) const + bool operator==(const LineInfo& other) const { return textOffset == other.textOffset && y == other.y && height == other.height && maxAscent == other.maxAscent && maxDescent == other.maxDescent - && layoutedSpans == otner.layoutedSpans; + && layoutedSpans == other.layoutedSpans; } - bool operator!=(const LayoutLine& other) const + bool operator!=(const LineInfo& other) const { return !(*this == other); } public: - int textOffset; + int32 textOffset; float y; float height; float maxAscent; @@ -76,7 +167,7 @@ public: }; -typedef List<LayoutLine, false> LayoutLineList; +typedef List<LineInfo, false> LineInfoList; class ParagraphLayout : public BReferenceable { @@ -86,9 +177,7 @@ public: ParagraphLayout(const ParagraphLayout& other); virtual ~ParagraphLayout(); - void SetParagraph(const ::Paragraph& paragraph); - const ::Paragraph& Paragraph() const - { return fParagraph; } + void SetParagraph(const Paragraph& paragraph); void SetWidth(float width); float Width() const @@ -104,32 +193,26 @@ private: void _Init(); bool _AppendGlyphInfos(const TextSpan& span); bool _AppendGlyphInfo(uint32 charCode, - const TextStyleRef& span); + float advanceX, + const CharacterStyle& style); - void _GetGlyphAdvance(int offset, - float& advanceX, float& advanceY, - float escapementArray[]) const; - void _FinalizeLine(int lineStart, int lineEnd, int lineIndex, float y, float& lineHeight); void _DrawLine(BView* view, - const LayoutLine& line) const; + const LineInfo& line) const; void _DrawSpan(BView* view, const TextSpan& span, - int textOffset) const; + int32 textOffset) const; private: TextSpanList fTextSpans; + ParagraphStyle fParagraphStyle; float fWidth; - bool fLayoutValid; - GlyphInfo* fGlyphInfoBuffer; - int fGlpyhInfoBufferSize; - int fGlyphInfoCount; - - LayoutLineList fLayoutLines; + GlyphInfoList fGlyphInfos; + LineInfoList fLineInfos; }; #endif // PARAGRAPH_LAYOUT_H ############################################################################ Commit: d922357fa13df25e4024e6ac6baeac59507bf4d7 URL: http://cgit.haiku-os.org/haiku/commit/?id=d922357 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 11:21:32 2013 UTC HaikuDepot: CharacterStyle: Added convenience methods ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/CharacterStyle.cpp b/src/apps/haiku-depot/textview/CharacterStyle.cpp index 07a120e..3e1c7ea 100644 --- a/src/apps/haiku-depot/textview/CharacterStyle.cpp +++ b/src/apps/haiku-depot/textview/CharacterStyle.cpp @@ -74,6 +74,15 @@ CharacterStyle::Font() const bool +CharacterStyle::SetFontSize(float size) +{ + BFont font(Font()); + font.SetSize(size); + return SetFont(font); +} + + +bool CharacterStyle::SetAscent(float ascent) { CharacterStyleDataRef data = fStyleData->SetAscent(ascent); @@ -150,6 +159,13 @@ CharacterStyle::GlyphSpacing() const bool +CharacterStyle::SetForegroundColor(uint8 r, uint8 g, uint8 b, uint8 a) +{ + return SetForegroundColor((rgb_color){ r, g, b, a }); +} + + +bool CharacterStyle::SetForegroundColor(rgb_color color) { CharacterStyleDataRef data = fStyleData->SetForegroundColor(color); @@ -169,6 +185,13 @@ CharacterStyle::ForegroundColor() const bool +CharacterStyle::SetBackgroundColor(uint8 r, uint8 g, uint8 b, uint8 a) +{ + return SetBackgroundColor((rgb_color){ r, g, b, a }); +} + + +bool CharacterStyle::SetBackgroundColor(rgb_color color) { CharacterStyleDataRef data = fStyleData->SetBackgroundColor(color); diff --git a/src/apps/haiku-depot/textview/CharacterStyle.h b/src/apps/haiku-depot/textview/CharacterStyle.h index c294eeb..7e6615b 100644 --- a/src/apps/haiku-depot/textview/CharacterStyle.h +++ b/src/apps/haiku-depot/textview/CharacterStyle.h @@ -20,6 +20,8 @@ public: bool SetFont(const BFont& font); const BFont& Font() const; + bool SetFontSize(float size); + bool SetAscent(float ascent); float Ascent() const; @@ -32,9 +34,15 @@ public: bool SetGlyphSpacing(float spacing); float GlyphSpacing() const; + bool SetForegroundColor( + uint8 r, uint8 g, uint8 b, + uint8 a = 255); bool SetForegroundColor(rgb_color color); rgb_color ForegroundColor() const; + bool SetBackgroundColor( + uint8 r, uint8 g, uint8 b, + uint8 a = 255); bool SetBackgroundColor(rgb_color color); rgb_color BackgroundColor() const; diff --git a/src/apps/haiku-depot/textview/CharacterStyleData.cpp b/src/apps/haiku-depot/textview/CharacterStyleData.cpp index d5f23fa..50ed806 100644 --- a/src/apps/haiku-depot/textview/CharacterStyleData.cpp +++ b/src/apps/haiku-depot/textview/CharacterStyleData.cpp @@ -110,6 +110,18 @@ CharacterStyleData::SetAscent(float ascent) } +float +CharacterStyleData::Ascent() const +{ + if (fAscent >= 0.0f) + return fAscent; + + font_height fontHeight; + fFont.GetHeight(&fontHeight); + return fontHeight.ascent; +} + + CharacterStyleDataRef CharacterStyleData::SetDescent(float descent) { @@ -125,6 +137,18 @@ CharacterStyleData::SetDescent(float descent) } +float +CharacterStyleData::Descent() const +{ + if (fDescent >= 0.0f) + return fDescent; + + font_height fontHeight; + fFont.GetHeight(&fontHeight); + return fontHeight.descent; +} + + CharacterStyleDataRef CharacterStyleData::SetWidth(float width) { diff --git a/src/apps/haiku-depot/textview/CharacterStyleData.h b/src/apps/haiku-depot/textview/CharacterStyleData.h index 3578994..20377b4 100644 --- a/src/apps/haiku-depot/textview/CharacterStyleData.h +++ b/src/apps/haiku-depot/textview/CharacterStyleData.h @@ -46,12 +46,10 @@ public: { return fFont; } CharacterStyleDataRef SetAscent(float ascent); - inline float Ascent() const - { return fAscent; } + float Ascent() const; CharacterStyleDataRef SetDescent(float descent); - inline float Descent() const - { return fDescent; } + float Descent() const; CharacterStyleDataRef SetWidth(float width); inline float Width() const ############################################################################ Commit: 4b810a1e92178747688488db78f468b5dc902937 URL: http://cgit.haiku-os.org/haiku/commit/?id=4b810a1 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 11:24:01 2013 UTC HaikuDepot: TextDocument: Added Paragraph access by index. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/TextDocument.cpp b/src/apps/haiku-depot/textview/TextDocument.cpp index e77d51b..b8cbb2d 100644 --- a/src/apps/haiku-depot/textview/TextDocument.cpp +++ b/src/apps/haiku-depot/textview/TextDocument.cpp @@ -178,6 +178,15 @@ TextDocument::ParagraphAt(int32 textOffset, int32& paragraphOffset) const } +const Paragraph& +TextDocument::ParagraphAt(int32 index) const +{ + if (index >= 0 && index < fParagraphs.CountItems()) + return fParagraphs.ItemAtFast(index); + return fEmptyLastParagraph; +} + + bool TextDocument::Append(const Paragraph& paragraph) { diff --git a/src/apps/haiku-depot/textview/TextDocument.h b/src/apps/haiku-depot/textview/TextDocument.h index 0dbe42e..5bb23c4 100644 --- a/src/apps/haiku-depot/textview/TextDocument.h +++ b/src/apps/haiku-depot/textview/TextDocument.h @@ -5,6 +5,8 @@ #ifndef TEXT_DOCUMENT_H #define TEXT_DOCUMENT_H +#include <Referenceable.h> + #include "CharacterStyle.h" #include "List.h" #include "Paragraph.h" @@ -13,7 +15,7 @@ typedef List<Paragraph, false> ParagraphList; -class TextDocument { +class TextDocument : public BReferenceable { public: TextDocument(); TextDocument( @@ -56,6 +58,8 @@ public: const Paragraph& ParagraphAt(int32 textOffset, int32& paragraphOffset) const; + const Paragraph& ParagraphAt(int32 index) const; + bool Append(const Paragraph& paragraph); private: @@ -65,4 +69,7 @@ private: }; +typedef BReference<TextDocument> TextDocumentRef; + + #endif // TEXT_DOCUMENT_H ############################################################################ Commit: 24523b867be4eb51db545260e350c7d5464ba65b URL: http://cgit.haiku-os.org/haiku/commit/?id=24523b8 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 11:24:31 2013 UTC HaikuDepot: ParagraphLayout: Debugged and now working. * The biggest problem was that adding the wrapped sub-TextSpan to the LineInfos was missing. Other problems included missing handling of ascent and descent per CharacterStyle. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.cpp b/src/apps/haiku-depot/textview/ParagraphLayout.cpp index ef8336c..0a1005a 100644 --- a/src/apps/haiku-depot/textview/ParagraphLayout.cpp +++ b/src/apps/haiku-depot/textview/ParagraphLayout.cpp @@ -198,10 +198,9 @@ ParagraphLayout::ParagraphLayout(const ParagraphLayout& other) fWidth(other.fWidth), fLayoutValid(false), - fGlyphInfos(), + fGlyphInfos(other.fGlyphInfos), fLineInfos() { - _Init(); } @@ -467,32 +466,66 @@ ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float width, } -void +bool ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex, float y, float& lineHeight) { - lineHeight = 0.0f; - float maxAscent = 0.0f; - float maxDescent = 0.0f; + LineInfo line(lineStart, y, 0.0f, 0.0f, 0.0f); + + int spanIndex = -1; + int spanStart = 0; + int spanEnd = 0; for (int i = lineStart; i <= lineEnd; i++) { + // Mark line index in glyph GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); glyph.lineIndex = lineIndex; fGlyphInfos.Replace(i, glyph); - const CharacterStyle& style = glyph.style; - - if (style.Font().Size() > lineHeight) - lineHeight = style.Font().Size(); - - if (style.Ascent() > maxAscent) - maxAscent = style.Ascent(); + // See if the next sub-span needs to be added to the LineInfo + bool addSpan = false; - if (style.Descent() > maxDescent) - maxDescent = style.Descent(); + while (i >= spanEnd) { + spanIndex++; + const TextSpan& span = fTextSpans.ItemAt(spanIndex); + spanStart = spanEnd; + spanEnd += span.CharCount(); + addSpan = true; + } + + if (addSpan) { + const TextSpan& span = fTextSpans.ItemAt(spanIndex); + TextSpan subSpan = span.SubSpan(i - spanStart, + (lineEnd - spanStart) - (i - spanStart)); + line.layoutedSpans.Add(subSpan); + _IncludeStyleInLine(line, span.Style()); + } } - fLineInfos.Add(LineInfo(lineStart, y, lineHeight, maxAscent, maxDescent)); + lineHeight = line.height; + + return fLineInfos.Add(line); +} + + +void +ParagraphLayout::_IncludeStyleInLine(LineInfo& line, + const CharacterStyle& style) +{ + float ascent = style.Ascent(); + if (ascent > line.maxAscent) + line.maxAscent = ascent; + + float descent = style.Descent(); + if (descent > line.maxDescent) + line.maxDescent = descent; + + float height = ascent + descent; + if (style.Font().Size() > height) + height = style.Font().Size(); + + if (height > line.height) + line.height = height; } diff --git a/src/apps/haiku-depot/textview/ParagraphLayout.h b/src/apps/haiku-depot/textview/ParagraphLayout.h index be838e5..ff228d2 100644 --- a/src/apps/haiku-depot/textview/ParagraphLayout.h +++ b/src/apps/haiku-depot/textview/ParagraphLayout.h @@ -196,9 +196,12 @@ private: float advanceX, const CharacterStyle& style); - void _FinalizeLine(int lineStart, int lineEnd, + bool _FinalizeLine(int lineStart, int lineEnd, int lineIndex, float y, float& lineHeight); + void _IncludeStyleInLine(LineInfo& line, + const CharacterStyle& style); + void _DrawLine(BView* view, const LineInfo& line) const; void _DrawSpan(BView* view, const TextSpan& span, ############################################################################ Revision: hrev46019 Commit: 68dfaf0f9d49a713685e93133b37c249535b62d7 URL: http://cgit.haiku-os.org/haiku/commit/?id=68dfaf0 Author: Stephan Aßmus <superstippi@xxxxxx> Date: Thu Sep 5 11:26:15 2013 UTC HaikuDepot: New TextDocumentView and test app. * TextDocumentView still only shows the first paragraph of a TextDocument, but this time using the new ParagraphLayout. A class for layouting all paragraphs of a TextDocument is up next. * A simple test app shows that TextSpans with different CharacterStyles already work in one Paragraph. The test is nowhere extensive and does not test for bugs in corner cases. ---------------------------------------------------------------------------- diff --git a/src/apps/haiku-depot/Jamfile b/src/apps/haiku-depot/Jamfile index 22335f5..13b48f1 100644 --- a/src/apps/haiku-depot/Jamfile +++ b/src/apps/haiku-depot/Jamfile @@ -12,6 +12,21 @@ for sourceDir in $(sourceDirs) { SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps haiku-depot $(sourceDir) ] ; } +local textDocumentSources = + CharacterStyle.cpp + CharacterStyleData.cpp + Paragraph.cpp + ParagraphLayout.cpp + ParagraphStyle.cpp + ParagraphStyleData.cpp + TextDocument.cpp + TextDocumentView.cpp + TextLayout.cpp + TextSpan.cpp + TextStyle.cpp + TextView.cpp +; + Application HaikuDepot : App.cpp BitmapButton.cpp @@ -27,17 +42,7 @@ Application HaikuDepot : support.cpp # textview stuff - CharacterStyle.cpp - CharacterStyleData.cpp - Paragraph.cpp - ParagraphLayout.cpp - ParagraphStyle.cpp - ParagraphStyleData.cpp - TextDocument.cpp - TextLayout.cpp - TextSpan.cpp - TextStyle.cpp - TextView.cpp + $(textDocumentSources) : be translation libcolumnlistview.a libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) @@ -55,3 +60,10 @@ DoCatalogs HaikuDepot : PackageListView.cpp PackageManager.cpp ; + +Application TextDocumentTest : + TextDocumentTest.cpp + $(textDocumentSources) + + : be translation libshared.a $(TARGET_LIBSUPC++) +; diff --git a/src/apps/haiku-depot/textview/TextDocumentTest.cpp b/src/apps/haiku-depot/textview/TextDocumentTest.cpp new file mode 100644 index 0000000..292b19b --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentTest.cpp @@ -0,0 +1,75 @@ +/* + * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "TextDocumentTest.h" + +#include <stdio.h> + +#include <LayoutBuilder.h> +#include <Window.h> + +#include "TextDocumentView.h" + +TextDocumentTest::TextDocumentTest() + : + BApplication("application/x-vnd.Haiku-TextDocumentTest") +{ +} + + +TextDocumentTest::~TextDocumentTest() +{ +} + + +void +TextDocumentTest::ReadyToRun() +{ + BRect frame(50.0, 50.0, 749.0, 549.0); + + BWindow* window = new BWindow(frame, "Text document test", + B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS); + + TextDocumentView* documentView = new TextDocumentView("text document view"); + + BLayoutBuilder::Group<>(window, B_VERTICAL) + .Add(documentView) + ; + + ParagraphStyle paragraphStyle; + + CharacterStyle regularStyle; + + CharacterStyle boldStyle(regularStyle); + boldStyle.SetFont(BFont(be_bold_font)); + + CharacterStyle bigStyle(regularStyle); + bigStyle.SetFontSize(24); + bigStyle.SetForegroundColor(255, 50, 50); + + Paragraph paragraph(paragraphStyle); + paragraph.Append(TextSpan("This is a ", regularStyle)); + paragraph.Append(TextSpan("test", bigStyle)); + paragraph.Append(TextSpan(" to see if ", regularStyle)); + paragraph.Append(TextSpan("different", boldStyle)); + paragraph.Append(TextSpan(" character styles already work.", regularStyle)); + + TextDocumentRef document(new TextDocument(), true); + document->Append(paragraph); + + documentView->SetTextDocument(document); + + window->Show(); +} + + +int +main(int argc, char* argv[]) +{ + TextDocumentTest().Run(); + return 0; +} + + diff --git a/src/apps/haiku-depot/textview/TextDocumentTest.h b/src/apps/haiku-depot/textview/TextDocumentTest.h new file mode 100644 index 0000000..1fd05c1 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentTest.h @@ -0,0 +1,21 @@ +/* + * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef TEXT_DOCUMENT_TEST_H +#define TEXT_DOCUMENT_TEST_H + + +#include <Application.h> + + +class TextDocumentTest : public BApplication { +public: + TextDocumentTest(); + virtual ~TextDocumentTest(); + + virtual void ReadyToRun(); +}; + + +#endif // TEXT_DOCUMENT_TEST_H diff --git a/src/apps/haiku-depot/textview/TextDocumentView.cpp b/src/apps/haiku-depot/textview/TextDocumentView.cpp new file mode 100644 index 0000000..c344f10 --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentView.cpp @@ -0,0 +1,105 @@ +/* + * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "TextDocumentView.h" + + +TextDocumentView::TextDocumentView(const char* name) + : + BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS) +{ + fParagraphLayout.SetWidth(Bounds().Width()); + + SetViewColor(B_TRANSPARENT_COLOR); +// SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetLowColor(255, 255, 255, 255); +} + + +TextDocumentView::~TextDocumentView() +{ +} + + +void +TextDocumentView::Draw(BRect updateRect) +{ + FillRect(updateRect, B_SOLID_LOW); + + fParagraphLayout.SetWidth(Bounds().Width()); + fParagraphLayout.Draw(this, B_ORIGIN); +} + + +void +TextDocumentView::AttachedToWindow() +{ + BView* parent = Parent(); + if (parent != NULL) + SetLowColor(parent->ViewColor()); +} + + +void +TextDocumentView::FrameResized(float width, float height) +{ + fParagraphLayout.SetWidth(width); +} + + +BSize +TextDocumentView::MinSize() +{ + return BSize(50.0f, 0.0f); +} + + +BSize +TextDocumentView::MaxSize() +{ + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); +} + + +BSize +TextDocumentView::PreferredSize() +{ + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); +} + + +bool +TextDocumentView::HasHeightForWidth() +{ + return true; +} + + +void +TextDocumentView::GetHeightForWidth(float width, float* min, float* max, + float* preferred) +{ + ParagraphLayout layout(fParagraphLayout); + layout.SetWidth(width); + + float height = layout.Height() + 1; + + if (min != NULL) + *min = height; + if (max != NULL) + *max = height; + if (preferred != NULL) + *preferred = height; +} + + +void +TextDocumentView::SetTextDocument(const TextDocumentRef& document) +{ + fTextDocument = document; + fParagraphLayout.SetParagraph(fTextDocument->ParagraphAt(0)); + InvalidateLayout(); +} + diff --git a/src/apps/haiku-depot/textview/TextDocumentView.h b/src/apps/haiku-depot/textview/TextDocumentView.h new file mode 100644 index 0000000..0e7f57c --- /dev/null +++ b/src/apps/haiku-depot/textview/TextDocumentView.h @@ -0,0 +1,41 @@ +/* + * Copyright 2013, Stephan Aßmus <superstippi@xxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef TEXT_DOCUMENT_VIEW_H +#define TEXT_DOCUMENT_VIEW_H + +#include <String.h> +#include <View.h> + +#include "ParagraphLayout.h" +#include "TextDocument.h" + + +class TextDocumentView : public BView { +public: + TextDocumentView(const char* name = NULL); + virtual ~TextDocumentView(); + + virtual void Draw(BRect updateRect); + + virtual void AttachedToWindow(); + virtual void FrameResized(float width, float height); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + + virtual bool HasHeightForWidth(); + virtual void GetHeightForWidth(float width, float* min, + float* max, float* preferred); + + void SetTextDocument( + const TextDocumentRef& document); + +private: + TextDocumentRef fTextDocument; + ParagraphLayout fParagraphLayout; +}; + +#endif // TEXT_DOCUMENT_VIEW_H