HaikuDepot: Removed first iteration of text layout classes.
This commit is contained in:
@@ -24,9 +24,7 @@ local textDocumentSources =
|
|||||||
TextDocument.cpp
|
TextDocument.cpp
|
||||||
TextDocumentLayout.cpp
|
TextDocumentLayout.cpp
|
||||||
TextDocumentView.cpp
|
TextDocumentView.cpp
|
||||||
TextLayout.cpp
|
|
||||||
TextSpan.cpp
|
TextSpan.cpp
|
||||||
TextStyle.cpp
|
|
||||||
TextView.cpp
|
TextView.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -44,7 +42,7 @@ Application HaikuDepot :
|
|||||||
PackageManager.cpp
|
PackageManager.cpp
|
||||||
support.cpp
|
support.cpp
|
||||||
|
|
||||||
# textview stuff
|
# text view stuff
|
||||||
$(textDocumentSources)
|
$(textDocumentSources)
|
||||||
|
|
||||||
: be translation libcolumnlistview.a libshared.a $(TARGET_LIBSUPC++)
|
: be translation libcolumnlistview.a libshared.a $(TARGET_LIBSUPC++)
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef GLYPH_INFO_H
|
|
||||||
#define GLYPH_INFO_H
|
|
||||||
|
|
||||||
#include "TextStyle.h"
|
|
||||||
|
|
||||||
|
|
||||||
class GlyphInfo {
|
|
||||||
public:
|
|
||||||
GlyphInfo()
|
|
||||||
:
|
|
||||||
charCode(0),
|
|
||||||
x(0.0f),
|
|
||||||
y(0.0f),
|
|
||||||
advanceX(0.0f),
|
|
||||||
maxAscent(0.0f),
|
|
||||||
maxDescent(0.0f),
|
|
||||||
lineIndex(0),
|
|
||||||
style()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GlyphInfo(uint32 charCode, float x, float y, float advanceX,
|
|
||||||
float maxAscent, float maxDescent, int lineIndex,
|
|
||||||
const TextStyleRef& style)
|
|
||||||
:
|
|
||||||
charCode(charCode),
|
|
||||||
x(x),
|
|
||||||
y(y),
|
|
||||||
advanceX(advanceX),
|
|
||||||
maxAscent(maxAscent),
|
|
||||||
maxDescent(maxDescent),
|
|
||||||
lineIndex(lineIndex),
|
|
||||||
style(style)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GlyphInfo(const GlyphInfo& other)
|
|
||||||
:
|
|
||||||
charCode(other.charCode),
|
|
||||||
x(other.x),
|
|
||||||
y(other.y),
|
|
||||||
advanceX(other.advanceX),
|
|
||||||
maxAscent(other.maxAscent),
|
|
||||||
maxDescent(other.maxDescent),
|
|
||||||
lineIndex(other.lineIndex),
|
|
||||||
style(other.style)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GlyphInfo& operator=(const GlyphInfo& other)
|
|
||||||
{
|
|
||||||
charCode = other.charCode;
|
|
||||||
x = other.x;
|
|
||||||
y = other.y;
|
|
||||||
advanceX = other.advanceX;
|
|
||||||
maxAscent = other.maxAscent;
|
|
||||||
maxDescent = other.maxDescent;
|
|
||||||
lineIndex = other.lineIndex;
|
|
||||||
style = other.style;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const GlyphInfo& other) const
|
|
||||||
{
|
|
||||||
return charCode == other.charCode
|
|
||||||
&& x == other.x
|
|
||||||
&& y == other.y
|
|
||||||
&& advanceX == other.advanceX
|
|
||||||
&& maxAscent == other.maxAscent
|
|
||||||
&& maxDescent == other.maxDescent
|
|
||||||
&& lineIndex == other.lineIndex
|
|
||||||
&& style == other.style;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const GlyphInfo& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint32 charCode;
|
|
||||||
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float advanceX;
|
|
||||||
|
|
||||||
float maxAscent;
|
|
||||||
float maxDescent;
|
|
||||||
|
|
||||||
int lineIndex;
|
|
||||||
|
|
||||||
TextStyleRef style;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // GLYPH_INFO_H
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef LINE_INFO_H
|
|
||||||
#define LINE_INFO_H
|
|
||||||
|
|
||||||
#include "List.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LineInfo {
|
|
||||||
public:
|
|
||||||
LineInfo()
|
|
||||||
:
|
|
||||||
textOffset(0),
|
|
||||||
y(0.0f),
|
|
||||||
height(0.0f),
|
|
||||||
maxAscent(0.0f),
|
|
||||||
maxDescent(0.0f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LineInfo(int textOffset, float y, float height, float maxAscent,
|
|
||||||
float maxDescent)
|
|
||||||
:
|
|
||||||
textOffset(textOffset),
|
|
||||||
y(y),
|
|
||||||
height(height),
|
|
||||||
maxAscent(maxAscent),
|
|
||||||
maxDescent(maxDescent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LineInfo(const LineInfo& other)
|
|
||||||
:
|
|
||||||
textOffset(other.textOffset),
|
|
||||||
y(other.y),
|
|
||||||
height(other.height),
|
|
||||||
maxAscent(other.maxAscent),
|
|
||||||
maxDescent(other.maxDescent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LineInfo& operator=(const LineInfo& other)
|
|
||||||
{
|
|
||||||
textOffset = other.textOffset;
|
|
||||||
y = other.y;
|
|
||||||
height = other.height;
|
|
||||||
maxAscent = other.maxAscent;
|
|
||||||
maxDescent = other.maxDescent;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const LineInfo& other) const
|
|
||||||
{
|
|
||||||
return textOffset == other.textOffset
|
|
||||||
&& y == other.y
|
|
||||||
&& height == other.height
|
|
||||||
&& maxAscent == other.maxAscent
|
|
||||||
&& maxDescent == other.maxDescent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const LineInfo& other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
int textOffset;
|
|
||||||
float y;
|
|
||||||
float height;
|
|
||||||
float maxAscent;
|
|
||||||
float maxDescent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef List<LineInfo, false> LineInfoList;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // LINE_INFO_H
|
|
||||||
@@ -1,562 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2001-2013, Haiku, Inc. All rights reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Stephan Aßmus, [email protected]
|
|
||||||
* Stefano Ceccherini, [email protected]
|
|
||||||
* Marc Flerackers, [email protected]
|
|
||||||
* Hiroshi Lockheimer (BTextView is based on his STEEngine)
|
|
||||||
* Oliver Tappe, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "TextLayout.h"
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
|
||||||
#include <utf8_functions.h>
|
|
||||||
#include <View.h>
|
|
||||||
|
|
||||||
#include "GlyphInfo.h"
|
|
||||||
#include "List.h"
|
|
||||||
#include "TextStyle.h"
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
CHAR_CLASS_DEFAULT,
|
|
||||||
CHAR_CLASS_WHITESPACE,
|
|
||||||
CHAR_CLASS_GRAPHICAL,
|
|
||||||
CHAR_CLASS_QUOTE,
|
|
||||||
CHAR_CLASS_PUNCTUATION,
|
|
||||||
CHAR_CLASS_PARENS_OPEN,
|
|
||||||
CHAR_CLASS_PARENS_CLOSE,
|
|
||||||
CHAR_CLASS_END_OF_TEXT
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
inline uint32
|
|
||||||
get_char_classification(uint32 charCode)
|
|
||||||
{
|
|
||||||
// TODO: Should check against a list of characters containing also
|
|
||||||
// word breakers from other languages.
|
|
||||||
|
|
||||||
switch (charCode) {
|
|
||||||
case '\0':
|
|
||||||
return CHAR_CLASS_END_OF_TEXT;
|
|
||||||
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
case '\n':
|
|
||||||
return CHAR_CLASS_WHITESPACE;
|
|
||||||
|
|
||||||
case '=':
|
|
||||||
case '+':
|
|
||||||
case '@':
|
|
||||||
case '#':
|
|
||||||
case '$':
|
|
||||||
case '%':
|
|
||||||
case '^':
|
|
||||||
case '&':
|
|
||||||
case '*':
|
|
||||||
case '\\':
|
|
||||||
case '|':
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
case '/':
|
|
||||||
case '~':
|
|
||||||
return CHAR_CLASS_GRAPHICAL;
|
|
||||||
|
|
||||||
case '\'':
|
|
||||||
case '"':
|
|
||||||
return CHAR_CLASS_QUOTE;
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
case '.':
|
|
||||||
case '?':
|
|
||||||
case '!':
|
|
||||||
case ';':
|
|
||||||
case ':':
|
|
||||||
case '-':
|
|
||||||
return CHAR_CLASS_PUNCTUATION;
|
|
||||||
|
|
||||||
case '(':
|
|
||||||
case '[':
|
|
||||||
case '{':
|
|
||||||
return CHAR_CLASS_PARENS_OPEN;
|
|
||||||
|
|
||||||
case ')':
|
|
||||||
case ']':
|
|
||||||
case '}':
|
|
||||||
return CHAR_CLASS_PARENS_CLOSE;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return CHAR_CLASS_DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
can_end_line(const GlyphInfo* buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
if (offset == count - 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (offset < 0 || offset > count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint32 charCode = buffer[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 nextClassification = get_char_classification(nextCharCode);
|
|
||||||
|
|
||||||
// never separate a punctuation char from its preceding word
|
|
||||||
if (classification == CHAR_CLASS_DEFAULT
|
|
||||||
&& nextClassification == CHAR_CLASS_PUNCTUATION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((classification == CHAR_CLASS_WHITESPACE
|
|
||||||
&& nextClassification != CHAR_CLASS_WHITESPACE)
|
|
||||||
|| (classification != CHAR_CLASS_WHITESPACE
|
|
||||||
&& nextClassification == CHAR_CLASS_WHITESPACE)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow wrapping after whitespace, unless more whitespace (except for
|
|
||||||
// newline) follows
|
|
||||||
if (classification == CHAR_CLASS_WHITESPACE
|
|
||||||
&& (nextClassification != CHAR_CLASS_WHITESPACE
|
|
||||||
|| nextCharCode == '\n')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow wrapping after punctuation chars, unless more punctuation, closing
|
|
||||||
// parenthesis or quotes follow
|
|
||||||
if (classification == CHAR_CLASS_PUNCTUATION
|
|
||||||
&& nextClassification != CHAR_CLASS_PUNCTUATION
|
|
||||||
&& nextClassification != CHAR_CLASS_PARENS_CLOSE
|
|
||||||
&& nextClassification != CHAR_CLASS_QUOTE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allow wrapping after quotes, graphical chars and closing parenthesis only
|
|
||||||
// if whitespace follows (not perfect, but seems to do the right thing most
|
|
||||||
// of the time)
|
|
||||||
if ((classification == CHAR_CLASS_QUOTE
|
|
||||||
|| classification == CHAR_CLASS_GRAPHICAL
|
|
||||||
|| classification == CHAR_CLASS_PARENS_CLOSE)
|
|
||||||
&& nextClassification == CHAR_CLASS_WHITESPACE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - TextLayout
|
|
||||||
|
|
||||||
|
|
||||||
TextLayout::TextLayout()
|
|
||||||
:
|
|
||||||
fText(),
|
|
||||||
|
|
||||||
fDefaultFont(),
|
|
||||||
fAscent(0.0f),
|
|
||||||
fDescent(0.0f),
|
|
||||||
fWidth(0.0f),
|
|
||||||
fGlyphSpacing(0.0f),
|
|
||||||
fFirstLineInset(0.0f),
|
|
||||||
fLineInset(0.0f),
|
|
||||||
fLineSpacing(0.0f),
|
|
||||||
|
|
||||||
fLayoutValid(false),
|
|
||||||
fGlyphInfoBuffer(NULL),
|
|
||||||
fGlyphInfoCount(0)
|
|
||||||
{
|
|
||||||
// Init fAscent and fDescent
|
|
||||||
SetFont(BFont(be_plain_font));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TextLayout::TextLayout(const TextLayout& other)
|
|
||||||
:
|
|
||||||
fText(other.fText),
|
|
||||||
|
|
||||||
fDefaultFont(other.fDefaultFont),
|
|
||||||
fAscent(other.fAscent),
|
|
||||||
fDescent(other.fDescent),
|
|
||||||
fWidth(other.fWidth),
|
|
||||||
fGlyphSpacing(other.fGlyphSpacing),
|
|
||||||
fFirstLineInset(other.fFirstLineInset),
|
|
||||||
fLineInset(other.fLineInset),
|
|
||||||
fLineSpacing(other.fLineSpacing),
|
|
||||||
|
|
||||||
fLayoutValid(false),
|
|
||||||
fGlyphInfoBuffer(NULL),
|
|
||||||
fGlyphInfoCount(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TextLayout::~TextLayout()
|
|
||||||
{
|
|
||||||
delete[] fGlyphInfoBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetText(const BString& text)
|
|
||||||
{
|
|
||||||
if (fText != text) {
|
|
||||||
fText = text;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetFont(const BFont& font)
|
|
||||||
{
|
|
||||||
if (fDefaultFont != font || fAscent == 0.0f) {
|
|
||||||
fDefaultFont = font;
|
|
||||||
|
|
||||||
font_height fontHeight;
|
|
||||||
font.GetHeight(&fontHeight);
|
|
||||||
|
|
||||||
fAscent = fontHeight.ascent;
|
|
||||||
fDescent = fontHeight.descent;
|
|
||||||
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetGlyphSpacing(float glyphSpacing)
|
|
||||||
{
|
|
||||||
if (fGlyphSpacing != glyphSpacing) {
|
|
||||||
fGlyphSpacing = glyphSpacing;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetFirstLineInset(float inset)
|
|
||||||
{
|
|
||||||
if (fFirstLineInset != inset) {
|
|
||||||
fFirstLineInset = inset;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetLineInset(float inset)
|
|
||||||
{
|
|
||||||
if (fLineInset != inset) {
|
|
||||||
fLineInset = inset;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetLineSpacing(float spacing)
|
|
||||||
{
|
|
||||||
if (fLineSpacing != spacing) {
|
|
||||||
fLineSpacing = spacing;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::SetWidth(float width)
|
|
||||||
{
|
|
||||||
if (fWidth != width) {
|
|
||||||
fWidth = width;
|
|
||||||
fLayoutValid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
float
|
|
||||||
TextLayout::Height()
|
|
||||||
{
|
|
||||||
_ValidateLayout();
|
|
||||||
|
|
||||||
float height = fDefaultFont.Size();
|
|
||||||
|
|
||||||
if (fLineInfos.CountItems() > 0) {
|
|
||||||
const LineInfo& lastLine = fLineInfos.LastItem();
|
|
||||||
height = lastLine.y + lastLine.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::Draw(BView* view, const BPoint& offset)
|
|
||||||
{
|
|
||||||
_ValidateLayout();
|
|
||||||
|
|
||||||
// TODO: Support styles and all
|
|
||||||
view->SetFont(&fDefaultFont);
|
|
||||||
view->SetHighColor(0, 0, 0);
|
|
||||||
|
|
||||||
int lineCount = fLineInfos.CountItems();
|
|
||||||
for (int i = 0; i < lineCount; i++) {
|
|
||||||
const LineInfo& line = fLineInfos.ItemAtFast(i);
|
|
||||||
|
|
||||||
int startOffset = line.textOffset;
|
|
||||||
int endOffset;
|
|
||||||
if (i < lineCount - 1) {
|
|
||||||
const LineInfo& nextLine = fLineInfos.ItemAtFast(i + 1);
|
|
||||||
endOffset = nextLine.textOffset;
|
|
||||||
} else {
|
|
||||||
endOffset = fGlyphInfoCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
BString string;
|
|
||||||
fText.CopyCharsInto(string, startOffset, endOffset - startOffset);
|
|
||||||
|
|
||||||
float x = fGlyphInfoBuffer[startOffset].x;
|
|
||||||
float y = fGlyphInfoBuffer[startOffset].y;
|
|
||||||
|
|
||||||
//printf("%p->%.1f,%.1f: '%s'\n", this, x, y, string.String());
|
|
||||||
view->DrawString(string, BPoint(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - private
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::_ValidateLayout()
|
|
||||||
{
|
|
||||||
if (!fLayoutValid)
|
|
||||||
_Layout();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::_Layout()
|
|
||||||
{
|
|
||||||
fLineInfos.Clear();
|
|
||||||
delete[] fGlyphInfoBuffer;
|
|
||||||
fGlyphInfoBuffer = NULL;
|
|
||||||
|
|
||||||
fGlyphInfoCount = fText.CountChars();
|
|
||||||
if (fGlyphInfoCount == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Allocate arrays
|
|
||||||
float* escapementArray = new (std::nothrow) float[fGlyphInfoCount];
|
|
||||||
if (escapementArray == NULL)
|
|
||||||
return;
|
|
||||||
ArrayDeleter<float> escapementDeleter(escapementArray);
|
|
||||||
|
|
||||||
// Fetch glyph spacing information
|
|
||||||
fDefaultFont.GetEscapements(fText.String(), fGlyphInfoCount,
|
|
||||||
escapementArray);
|
|
||||||
|
|
||||||
// Convert to glyph buffer
|
|
||||||
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') {
|
|
||||||
// // Figure out tab width, it's the width between the last two tab
|
|
||||||
// // stops.
|
|
||||||
// float tabWidth = 0.0f;
|
|
||||||
// if (fTabCount > 0)
|
|
||||||
// tabWidth = fTabBuffer[fTabCount - 1];
|
|
||||||
// if (fTabCount > 1)
|
|
||||||
// tabWidth -= fTabBuffer[fTabCount - 2];
|
|
||||||
//
|
|
||||||
// // Try to find a tab stop that is farther than the current x
|
|
||||||
// // offset
|
|
||||||
// double tabOffset = 0.0;
|
|
||||||
// for (unsigned tabIndex = 0; tabIndex < fTabCount; tabIndex++) {
|
|
||||||
// tabOffset = fTabBuffer[tabIndex];
|
|
||||||
// if (tabOffset > x)
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // If no tab stop has been found, make the tab stop a multiple of
|
|
||||||
// // the tab width
|
|
||||||
// if (tabOffset <= x && tabWidth > 0.0)
|
|
||||||
// tabOffset = ((int) (x / tabWidth) + 1) * tabWidth;
|
|
||||||
//
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::_GetGlyphAdvance(int offset, float& advanceX, float& advanceY,
|
|
||||||
float escapementArray[]) const
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
TextLayout::_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef TEXT_LAYOUT_H
|
|
||||||
#define TEXT_LAYOUT_H
|
|
||||||
|
|
||||||
#include <Font.h>
|
|
||||||
#include <Referenceable.h>
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
#include "GlyphInfo.h"
|
|
||||||
#include "LineInfo.h"
|
|
||||||
|
|
||||||
|
|
||||||
class BView;
|
|
||||||
|
|
||||||
|
|
||||||
class TextLayout : public BReferenceable {
|
|
||||||
public:
|
|
||||||
TextLayout();
|
|
||||||
TextLayout(const TextLayout& other);
|
|
||||||
virtual ~TextLayout();
|
|
||||||
|
|
||||||
void SetText(const BString& text);
|
|
||||||
const BString& Text() const
|
|
||||||
{ return fText; }
|
|
||||||
|
|
||||||
void SetFont(const BFont& font);
|
|
||||||
const BFont& Font() const
|
|
||||||
{ return fDefaultFont; }
|
|
||||||
|
|
||||||
void SetGlyphSpacing(float glyphSpacing);
|
|
||||||
float GlyphSpacing() const
|
|
||||||
{ return fGlyphSpacing; }
|
|
||||||
|
|
||||||
void SetFirstLineInset(float inset);
|
|
||||||
float FirstLineInset() const
|
|
||||||
{ return fFirstLineInset; }
|
|
||||||
|
|
||||||
void SetLineInset(float inset);
|
|
||||||
float LineInset() const
|
|
||||||
{ return fLineInset; }
|
|
||||||
|
|
||||||
void SetLineSpacing(float spacing);
|
|
||||||
float LineSpacing() const
|
|
||||||
{ return fLineSpacing; }
|
|
||||||
|
|
||||||
void SetWidth(float width);
|
|
||||||
float Width() const
|
|
||||||
{ return fWidth; }
|
|
||||||
|
|
||||||
float Height();
|
|
||||||
void Draw(BView* view, const BPoint& offset);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void _ValidateLayout();
|
|
||||||
void _Layout();
|
|
||||||
void _GetGlyphAdvance(int offset,
|
|
||||||
float& advanceX, float& advanceY,
|
|
||||||
float escapementArray[]) const;
|
|
||||||
|
|
||||||
void _FinalizeLine(int lineStart, int lineEnd,
|
|
||||||
int lineIndex, float y, float& lineHeight);
|
|
||||||
private:
|
|
||||||
BString fText;
|
|
||||||
|
|
||||||
BFont fDefaultFont;
|
|
||||||
float fAscent;
|
|
||||||
float fDescent;
|
|
||||||
float fWidth;
|
|
||||||
float fGlyphSpacing;
|
|
||||||
float fFirstLineInset;
|
|
||||||
float fLineInset;
|
|
||||||
float fLineSpacing;
|
|
||||||
|
|
||||||
bool fLayoutValid;
|
|
||||||
|
|
||||||
GlyphInfo* fGlyphInfoBuffer;
|
|
||||||
int fGlyphInfoCount;
|
|
||||||
LineInfoList fLineInfos;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // TEXT_LAYOUT_H
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "TextStyle.h"
|
|
||||||
|
|
||||||
|
|
||||||
TextStyle::TextStyle()
|
|
||||||
:
|
|
||||||
font(),
|
|
||||||
|
|
||||||
ascent(0.0f),
|
|
||||||
descent(0.0f),
|
|
||||||
width(-1.0f),
|
|
||||||
glyphSpacing(0.0f),
|
|
||||||
|
|
||||||
fgColor((rgb_color){ 0, 0, 0, 255 }),
|
|
||||||
bgColor((rgb_color){ 255, 255, 255, 255 }),
|
|
||||||
|
|
||||||
strikeOut(false),
|
|
||||||
strikeOutColor((rgb_color){ 0, 0, 0, 255 }),
|
|
||||||
|
|
||||||
underline(false),
|
|
||||||
underlineStyle(0),
|
|
||||||
underlineColor((rgb_color){ 0, 0, 0, 255 })
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TextStyle::TextStyle(const BFont& font, float ascent, float descent,
|
|
||||||
float width, float glyphSpacing, rgb_color fgColor, rgb_color bgColor,
|
|
||||||
bool strikeOut, rgb_color strikeOutColor, bool underline,
|
|
||||||
uint32 underlineStyle, rgb_color underlineColor)
|
|
||||||
:
|
|
||||||
font(font),
|
|
||||||
|
|
||||||
ascent(ascent),
|
|
||||||
descent(descent),
|
|
||||||
width(width),
|
|
||||||
glyphSpacing(glyphSpacing),
|
|
||||||
|
|
||||||
fgColor(fgColor),
|
|
||||||
bgColor(bgColor),
|
|
||||||
|
|
||||||
strikeOut(strikeOut),
|
|
||||||
strikeOutColor(strikeOutColor),
|
|
||||||
|
|
||||||
underline(underline),
|
|
||||||
underlineStyle(underlineStyle),
|
|
||||||
underlineColor(underlineColor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TextStyle::TextStyle(const TextStyle& other)
|
|
||||||
:
|
|
||||||
font(other.font),
|
|
||||||
|
|
||||||
ascent(other.ascent),
|
|
||||||
descent(other.descent),
|
|
||||||
width(other.width),
|
|
||||||
glyphSpacing(other.glyphSpacing),
|
|
||||||
|
|
||||||
fgColor(other.fgColor),
|
|
||||||
bgColor(other.bgColor),
|
|
||||||
|
|
||||||
strikeOut(other.strikeOut),
|
|
||||||
strikeOutColor(other.strikeOutColor),
|
|
||||||
|
|
||||||
underline(other.underline),
|
|
||||||
underlineStyle(other.underlineStyle),
|
|
||||||
underlineColor(other.underlineColor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
TextStyle::operator==(const TextStyle& other) const
|
|
||||||
{
|
|
||||||
return font == other.font
|
|
||||||
|
|
||||||
&& ascent == other.ascent
|
|
||||||
&& descent == other.descent
|
|
||||||
&& width == other.width
|
|
||||||
&& glyphSpacing == other.glyphSpacing
|
|
||||||
|
|
||||||
&& fgColor == other.fgColor
|
|
||||||
&& bgColor == other.bgColor
|
|
||||||
|
|
||||||
&& strikeOut == other.strikeOut
|
|
||||||
&& strikeOutColor == other.strikeOutColor
|
|
||||||
|
|
||||||
&& underline == other.underline
|
|
||||||
&& underlineStyle == other.underlineStyle
|
|
||||||
&& underlineColor == other.underlineColor;
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013, Stephan Aßmus <[email protected]>.
|
|
||||||
* All rights reserved. Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef TEXT_STYLE_H
|
|
||||||
#define TEXT_STYLE_H
|
|
||||||
|
|
||||||
#include <Font.h>
|
|
||||||
#include <GraphicsDefs.h>
|
|
||||||
#include <Referenceable.h>
|
|
||||||
|
|
||||||
|
|
||||||
class TextStyle : public BReferenceable {
|
|
||||||
public:
|
|
||||||
TextStyle();
|
|
||||||
TextStyle(const BFont& font, float ascent, float descent, float width,
|
|
||||||
float glyphSpacing,
|
|
||||||
rgb_color fgColor, rgb_color bgColor, bool strikeOut,
|
|
||||||
rgb_color strikeOutColor, bool underline,
|
|
||||||
uint32 underlineStyle, rgb_color underlineColor);
|
|
||||||
|
|
||||||
TextStyle(const TextStyle& other);
|
|
||||||
|
|
||||||
bool operator==(const TextStyle& other) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
BFont font;
|
|
||||||
|
|
||||||
// The following three values override glyph metrics unless -1
|
|
||||||
float ascent;
|
|
||||||
float descent;
|
|
||||||
float width;
|
|
||||||
float glyphSpacing;
|
|
||||||
|
|
||||||
rgb_color fgColor;
|
|
||||||
rgb_color bgColor;
|
|
||||||
|
|
||||||
bool strikeOut;
|
|
||||||
rgb_color strikeOutColor;
|
|
||||||
|
|
||||||
bool underline;
|
|
||||||
uint32 underlineStyle;
|
|
||||||
rgb_color underlineColor;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef BReference<TextStyle> TextStyleRef;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // TEXT_STYLE_H
|
|
||||||
Reference in New Issue
Block a user