HaikuDepot: Text stuff: ParagraphLayout compiles and maybe works

This commit is contained in:
Stephan Aßmus
2013-09-05 10:59:39 +02:00
parent f668e7dd19
commit 15990b01a2
3 changed files with 285 additions and 266 deletions
+1
View File
@@ -30,6 +30,7 @@ Application HaikuDepot :
CharacterStyle.cpp CharacterStyle.cpp
CharacterStyleData.cpp CharacterStyleData.cpp
Paragraph.cpp Paragraph.cpp
ParagraphLayout.cpp
ParagraphStyle.cpp ParagraphStyle.cpp
ParagraphStyleData.cpp ParagraphStyleData.cpp
TextDocument.cpp TextDocument.cpp
+174 -239
View File
@@ -19,10 +19,6 @@
#include <utf8_functions.h> #include <utf8_functions.h>
#include <View.h> #include <View.h>
#include "GlyphInfo.h"
#include "List.h"
#include "TextStyle.h"
enum { enum {
CHAR_CLASS_DEFAULT, CHAR_CLASS_DEFAULT,
@@ -98,22 +94,24 @@ get_char_classification(uint32 charCode)
inline bool 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) if (offset == count - 1)
return true; return true;
if (offset < 0 || offset > count) if (offset < 0 || offset > count)
return false; return false;
uint32 charCode = buffer[offset].charCode; uint32 charCode = glyphInfos.ItemAtFast(offset).charCode;
uint32 classification = get_char_classification(charCode); uint32 classification = get_char_classification(charCode);
// wrapping is always allowed at end of text and at newlines // wrapping is always allowed at end of text and at newlines
if (classification == CHAR_CLASS_END_OF_TEXT || charCode == '\n') if (classification == CHAR_CLASS_END_OF_TEXT || charCode == '\n')
return true; return true;
uint32 nextCharCode = buffer[offset + 1].charCode; uint32 nextCharCode = glyphInfos.ItemAtFast(offset + 1).charCode;
uint32 nextClassification = get_char_classification(nextCharCode); uint32 nextClassification = get_char_classification(nextCharCode);
// never separate a punctuation char from its preceding word // 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() ParagraphLayout::ParagraphLayout()
: :
fTextSpans(), fTextSpans(),
fWidth(0.0f), fParagraphStyle(),
fWidth(0.0f),
fLayoutValid(false), fLayoutValid(false),
fGlyphInfoBuffer(NULL), fGlyphInfos(),
fGlpyhInfoBufferSize(0), fLineInfos()
fGlyphInfoCount(0),
fLayoutLines()
{ {
} }
@@ -182,15 +178,13 @@ ParagraphLayout::ParagraphLayout()
ParagraphLayout::ParagraphLayout(const Paragraph& paragraph) ParagraphLayout::ParagraphLayout(const Paragraph& paragraph)
: :
fTextSpans(paragraph.TextSpans()), fTextSpans(paragraph.TextSpans()),
fWidth(other.fWidth), fParagraphStyle(paragraph.Style()),
fWidth(0.0f),
fLayoutValid(false), fLayoutValid(false),
fGlyphInfoBuffer(NULL), fGlyphInfos(),
fGlpyhInfoBufferSize(0), fLineInfos()
fGlyphInfoCount(0),
fLayoutLines()
{ {
_Init(); _Init();
} }
@@ -199,15 +193,13 @@ ParagraphLayout::ParagraphLayout(const Paragraph& paragraph)
ParagraphLayout::ParagraphLayout(const ParagraphLayout& other) ParagraphLayout::ParagraphLayout(const ParagraphLayout& other)
: :
fTextSpans(other.fTextSpans), fTextSpans(other.fTextSpans),
fParagraphStyle(other.fParagraphStyle),
fWidth(other.fWidth), fWidth(other.fWidth),
fLayoutValid(false), fLayoutValid(false),
fGlyphInfoBuffer(NULL), fGlyphInfos(),
fGlpyhInfoBufferSize(0), fLineInfos()
fGlyphInfoCount(0),
fLayoutLines()
{ {
_Init(); _Init();
} }
@@ -215,7 +207,18 @@ ParagraphLayout::ParagraphLayout(const ParagraphLayout& other)
ParagraphLayout::~ParagraphLayout() 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; float height = 0.0f;
if (fLayoutLines.CountItems() > 0) { if (fLineInfos.CountItems() > 0) {
const LayoutLine& lastLine = fLayoutLines.LastItem(); const LineInfo& lastLine = fLineInfos.LastItem();
height = lastLine.y + lastLine.height; height = lastLine.y + lastLine.height;
} }
@@ -250,9 +253,9 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset)
{ {
_ValidateLayout(); _ValidateLayout();
int lineCount = fLayoutLines.CountItems(); int lineCount = fLineInfos.CountItems();
for (int i = 0; i < lineCount; i++) { for (int i = 0; i < lineCount; i++) {
const LayoutLine& line = fLayoutLines.ItemAtFast(i); const LineInfo& line = fLineInfos.ItemAtFast(i);
_DrawLine(view, line); _DrawLine(view, line);
} }
} }
@@ -272,51 +275,26 @@ ParagraphLayout::_ValidateLayout()
void void
ParagraphLayout::_Layout() ParagraphLayout::_Layout()
{ {
fLayoutLines.Clear(); fLineInfos.Clear();
// int charCount = fText.CountChars(); float x = fParagraphStyle.FirstLineInset();
// if (charCount == 0) float y = 0.0f;
// return; int lineIndex = 0;
// int lineStart = 0;
// // Allocate arrays
// float* escapementArray = new (std::nothrow) float[charCount]; int glyphCount = fGlyphInfos.CountItems();
// if (escapementArray == NULL) for (int i = 0; i < glyphCount; i++) {
// return; GlyphInfo glyph = fGlyphInfos.ItemAtFast(i);
// ArrayDeleter<float> escapementDeleter(escapementArray);
// uint32 charClassification = get_char_classification(glyph.charCode);
// // Fetch glyph spacing information
// fDefaultFont.GetEscapements(fText.String(), charCount, escapementArray); float advanceX = glyph.width;
// float advanceY = 0.0f;
// // Convert to glyph buffer
// fGlyphInfoCount = charCount; bool nextLine = false;
// fGlyphInfoBuffer = new (std::nothrow) GlyphInfo[fGlyphInfoCount]; bool lineBreak = false;
//
// // Init glyph buffer and convert escapement scale // if (glyph.charCode == '\t') {
// 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') {
// // Figure out tab width, it's the width between the last two tab // // Figure out tab width, it's the width between the last two tab
// // stops. // // stops.
// float tabWidth = 0.0f; // float tabWidth = 0.0f;
@@ -342,92 +320,90 @@ ParagraphLayout::_Layout()
// if (tabOffset - x > 0.0) // if (tabOffset - x > 0.0)
// advanceX = tabOffset - x; // advanceX = tabOffset - x;
// } // }
//
// fGlyphInfoBuffer[i].advanceX = advanceX; glyph.advanceX = advanceX;
//
// if (fGlyphInfoBuffer[i].charCode == '\n') { if (glyph.charCode == '\n') {
// nextLine = true; nextLine = true;
// lineBreak = true; lineBreak = true;
// fGlyphInfoBuffer[i].x = x; glyph.x = x;
// fGlyphInfoBuffer[i].y = y; fGlyphInfos.Replace(i, glyph);
// } else if (fWidth > 0.0f && x + advanceX > fWidth) { } else if (fWidth > 0.0f && x + advanceX > fWidth) {
// if (charClassification == CHAR_CLASS_WHITESPACE) { fGlyphInfos.Replace(i, glyph);
// advanceX = 0.0f; if (charClassification == CHAR_CLASS_WHITESPACE) {
// } else if (i > lineStart) { advanceX = 0.0f;
// nextLine = true; } else if (i > lineStart) {
// // The current glyph extends outside the width, we need to wrap nextLine = true;
// // to the next line. See what previous offset can be the end // The current glyph extends outside the width, we need to wrap
// // of the line. // to the next line. See what previous offset can be the end
// int lineEnd = i - 1; // of the line.
// while (lineEnd > lineStart int lineEnd = i - 1;
// && !can_end_line(fGlyphInfoBuffer, lineEnd, while (lineEnd > lineStart
// fGlyphInfoCount)) { && !can_end_line(fGlyphInfos, lineEnd)) {
// lineEnd--; lineEnd--;
// } }
//
// if (lineEnd > lineStart) { if (lineEnd > lineStart) {
// // Found a place to perform a line break. // Found a place to perform a line break.
// i = lineEnd + 1; i = lineEnd + 1;
// // Adjust the glyph info to point at the changed buffer
// // position // Adjust the glyph info to point at the changed buffer
// _GetGlyphAdvance(i, advanceX, advanceY, escapementArray); // position
// } else { glyph = fGlyphInfos.ItemAtFast(i);
// // Just break where we are. 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 if (nextLine) {
// // * Adjust the baseline offset according to the max ascent // * Initialize the max ascent/descent of all preceding glyph infos
// // * Fill in the line index. // on the current/last line
// unsigned lineEnd; // * Adjust the baseline offset according to the max ascent
// if (lineBreak) // * Fill in the line index.
// lineEnd = i; unsigned lineEnd;
// else if (lineBreak)
// lineEnd = i - 1; lineEnd = i;
// else
// float lineHeight = 0.0; lineEnd = i - 1;
// _FinalizeLine(lineStart, lineEnd, lineIndex, y,
// lineHeight); float lineHeight = 0.0;
// _FinalizeLine(lineStart, lineEnd, lineIndex, y, lineHeight);
// // Start position of the next line
// x = fLineInset; // Start position of the next line
// y += lineHeight + fLineSpacing; x = fParagraphStyle.LineInset();
// y += lineHeight + fParagraphStyle.LineSpacing();
// if (lineBreak)
// lineStart = i + 1; if (lineBreak)
// else lineStart = i + 1;
// lineStart = i; else
// lineStart = i;
// lineIndex++;
// } lineIndex++;
// }
// if (!lineBreak && i < fGlyphInfoCount) {
// fGlyphInfoBuffer[i].x = x; if (!lineBreak && i < glyphCount) {
// fGlyphInfoBuffer[i].y = y; glyph.x = x;
// } fGlyphInfos.Replace(i, glyph);
// }
// x += advanceX;
// y += advanceY; x += advanceX;
// } y += advanceY;
// }
// // The last line may not have been appended and initialized yet.
// if (lineStart <= fGlyphInfoCount - 1) { // The last line may not have been appended and initialized yet.
// float lineHeight; if (lineStart <= glyphCount - 1) {
// _FinalizeLine(lineStart, fGlyphInfoCount - 1, lineIndex, y, lineHeight); float lineHeight;
// } _FinalizeLine(lineStart, glyphCount - 1, lineIndex, y, lineHeight);
}
} }
void void
ParagraphLayout::_Init() ParagraphLayout::_Init()
{ {
delete[] fGlyphInfoBuffer; fGlyphInfos.Clear();
fGlyphInfoBuffer = NULL;
fGlpyhInfoBufferSize = 0;
fGlyphInfoCount = 0;
int spanCount = fTextSpans.CountItems(); int spanCount = fTextSpans.CountItems();
for (int i = 0; i < spanCount; i++) { for (int i = 0; i < spanCount; i++) {
@@ -449,7 +425,7 @@ ParagraphLayout::_AppendGlyphInfos(const TextSpan& span)
return true; return true;
const BString& text = span.Text(); const BString& text = span.Text();
const BFont& font = span.Style().font; const BFont& font = span.Style().Font();
// Allocate arrays // Allocate arrays
float* escapementArray = new (std::nothrow) float[charCount]; float* escapementArray = new (std::nothrow) float[charCount];
@@ -464,112 +440,68 @@ ParagraphLayout::_AppendGlyphInfos(const TextSpan& span)
float size = font.Size(); float size = font.Size();
const char* c = text.String(); const char* c = text.String();
for (int i = 0; i < charCount; i++) { for (int i = 0; i < charCount; i++) {
_AppendGlyphInfo(UTF8ToCharCode(&c), ); if (!_AppendGlyphInfo(UTF8ToCharCode(&c), escapementArray[i] * size,
fGlyphInfoBuffer[i].charCode = ; span.Style())) {
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)
return false; 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; return true;
} }
void bool
ParagraphLayout::_GetGlyphAdvance(int offset, float& advanceX, float& advanceY, ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float width,
float escapementArray[]) const const CharacterStyle& style)
{ {
float additionalGlyphSpacing = 0.0f; if (style.Width() >= 0.0f) {
if (fGlyphInfoBuffer[offset].style.Get() != NULL) // Use the metrics provided by the CharacterStyle and override
additionalGlyphSpacing = fGlyphInfoBuffer[offset].style->glyphSpacing; // the font provided metrics passed in "width"
else width = style.Width();
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;
} }
width += style.GlyphSpacing();
GlyphInfo glyph(charCode, 0.0f, width, width, 0, style);
return fGlyphInfos.Add(glyph);
} }
void void
ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex, float y, ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex,
float& lineHeight) float y, float& lineHeight)
{ {
lineHeight = 0.0f; lineHeight = 0.0f;
float maxAscent = 0.0f; float maxAscent = 0.0f;
float maxDescent = 0.0f; float maxDescent = 0.0f;
for (int i = lineStart; i <= lineEnd; i++) { for (int i = lineStart; i <= lineEnd; i++) {
if (fGlyphInfoBuffer[i].style.Get() != NULL) { GlyphInfo glyph = fGlyphInfos.ItemAtFast(i);
if (fGlyphInfoBuffer[i].style->font.Size() > lineHeight) glyph.lineIndex = lineIndex;
lineHeight = fGlyphInfoBuffer[i].style->font.Size(); fGlyphInfos.Replace(i, glyph);
if (fGlyphInfoBuffer[i].style->ascent > maxAscent)
maxAscent = fGlyphInfoBuffer[i].style->ascent; const CharacterStyle& style = glyph.style;
if (fGlyphInfoBuffer[i].style->descent > maxDescent)
maxDescent = fGlyphInfoBuffer[i].style->descent; if (style.Font().Size() > lineHeight)
} else { lineHeight = style.Font().Size();
if (fDefaultFont.Size() > lineHeight)
lineHeight = fDefaultFont.Size(); if (style.Ascent() > maxAscent)
if (fAscent > maxAscent) maxAscent = style.Ascent();
maxAscent = fAscent;
if (fDescent > maxDescent) if (style.Descent() > maxDescent)
maxDescent = fDescent; maxDescent = style.Descent();
}
} }
fLayoutLines.Add(LayoutLine(lineStart, y, lineHeight, maxAscent, maxDescent)); fLineInfos.Add(LineInfo(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;
}
} }
void void
ParagraphLayout::_DrawLine(BView* view, const LayoutLine& line) const ParagraphLayout::_DrawLine(BView* view, const LineInfo& line) const
{ {
int textOffset = line.textOffset; int textOffset = line.textOffset;
int spanCount = line.layoutedSpans.CountItems(); 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); const TextSpan& span = line.layoutedSpans.ItemAtFast(i);
_DrawSpan(view, span, textOffset); _DrawSpan(view, span, textOffset);
textOffset += span.CharCount(); textOffset += span.CharCount();
@@ -579,15 +511,18 @@ ParagraphLayout::_DrawLine(BView* view, const LayoutLine& line) const
void void
ParagraphLayout::_DrawSpan(BView* view, const TextSpan& span, ParagraphLayout::_DrawSpan(BView* view, const TextSpan& span,
int textOffset) const int32 textOffset) const
{ {
float x = fGlyphInfoBuffer[textOffset].x; const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset);
float y = fGlyphInfoBuffer[textOffset].y; 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->SetFont(&style.Font());
view->SetHighColor(style.fgColor); view->SetHighColor(style.ForegroundColor());
// TODO: Implement other style properties // TODO: Implement other style properties
// TODO: Implement correct glyph spacing // TODO: Implement correct glyph spacing
+110 -27
View File
@@ -9,26 +9,117 @@
#include <Referenceable.h> #include <Referenceable.h>
#include <String.h> #include <String.h>
#include "GlyphInfo.h"
#include "Paragraph.h" #include "Paragraph.h"
#include "CharacterStyle.h"
class BView; class BView;
class LayoutLine { class GlyphInfo {
public: 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), textOffset(0),
y(0.0f), y(0.0f),
height(0.0f), height(0.0f),
maxAscent(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), textOffset(other.textOffset),
y(other.y), y(other.y),
@@ -39,7 +130,7 @@ public:
{ {
} }
LayoutLine& operator=(const LayoutLine& other) LineInfo& operator=(const LineInfo& other)
{ {
textOffset = other.textOffset; textOffset = other.textOffset;
y = other.y; y = other.y;
@@ -50,23 +141,23 @@ public:
return *this; return *this;
} }
bool operator==(const LayoutLine& other) const bool operator==(const LineInfo& other) const
{ {
return textOffset == other.textOffset return textOffset == other.textOffset
&& y == other.y && y == other.y
&& height == other.height && height == other.height
&& maxAscent == other.maxAscent && maxAscent == other.maxAscent
&& maxDescent == other.maxDescent && maxDescent == other.maxDescent
&& layoutedSpans == otner.layoutedSpans; && layoutedSpans == other.layoutedSpans;
} }
bool operator!=(const LayoutLine& other) const bool operator!=(const LineInfo& other) const
{ {
return !(*this == other); return !(*this == other);
} }
public: public:
int textOffset; int32 textOffset;
float y; float y;
float height; float height;
float maxAscent; float maxAscent;
@@ -76,7 +167,7 @@ public:
}; };
typedef List<LayoutLine, false> LayoutLineList; typedef List<LineInfo, false> LineInfoList;
class ParagraphLayout : public BReferenceable { class ParagraphLayout : public BReferenceable {
@@ -86,9 +177,7 @@ public:
ParagraphLayout(const ParagraphLayout& other); ParagraphLayout(const ParagraphLayout& other);
virtual ~ParagraphLayout(); virtual ~ParagraphLayout();
void SetParagraph(const ::Paragraph& paragraph); void SetParagraph(const Paragraph& paragraph);
const ::Paragraph& Paragraph() const
{ return fParagraph; }
void SetWidth(float width); void SetWidth(float width);
float Width() const float Width() const
@@ -104,32 +193,26 @@ private:
void _Init(); void _Init();
bool _AppendGlyphInfos(const TextSpan& span); bool _AppendGlyphInfos(const TextSpan& span);
bool _AppendGlyphInfo(uint32 charCode, 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, void _FinalizeLine(int lineStart, int lineEnd,
int lineIndex, float y, float& lineHeight); int lineIndex, float y, float& lineHeight);
void _DrawLine(BView* view, void _DrawLine(BView* view,
const LayoutLine& line) const; const LineInfo& line) const;
void _DrawSpan(BView* view, const TextSpan& span, void _DrawSpan(BView* view, const TextSpan& span,
int textOffset) const; int32 textOffset) const;
private: private:
TextSpanList fTextSpans; TextSpanList fTextSpans;
ParagraphStyle fParagraphStyle;
float fWidth; float fWidth;
bool fLayoutValid; bool fLayoutValid;
GlyphInfo* fGlyphInfoBuffer; GlyphInfoList fGlyphInfos;
int fGlpyhInfoBufferSize; LineInfoList fLineInfos;
int fGlyphInfoCount;
LayoutLineList fLayoutLines;
}; };
#endif // PARAGRAPH_LAYOUT_H #endif // PARAGRAPH_LAYOUT_H