WidthBuffer complete,

Changed some methods name,
reordered class members in TextViewSupportBuffer.h, now they are in the same order
OpenTracker says


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5679 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2003-12-17 07:48:58 +00:00
parent 16cb489052
commit 008cfb1db2
5 changed files with 326 additions and 53 deletions
+4 -4
View File
@@ -1670,8 +1670,8 @@ BTextView::LineWidth(int32 lineNum) const
{
if (lineNum < 0)
return (*fLines)[0]->width;
else if (lineNum > fLines->fItemCount - 2)
return (*fLines)[fLines->fItemCount - 2]->width;
else if (lineNum > fLines->NumLines() - 1)
return (*fLines)[fLines->NumLines() - 1]->width;
else
return (*fLines)[lineNum]->width;
}
@@ -1681,8 +1681,8 @@ BTextView::LineHeight(int32 lineNum) const
{
if (lineNum < 0)
return (*fLines)[0]->ascent;
else if (lineNum > fLines->fItemCount - 2)
return (*fLines)[fLines->fItemCount - 2]->ascent;
else if (lineNum > fLines->NumLines() - 1)
return (*fLines)[fLines->NumLines() - 1]->ascent;
else
return (*fLines)[lineNum]->ascent;
}
@@ -33,7 +33,7 @@
#include <cstring>
// System Includes -------------------------------------------------------------
#include "SupportDefs.h"
#include <SupportDefs.h>
// Project Includes ------------------------------------------------------------
@@ -48,8 +48,7 @@ template <class T>
class _BTextViewSupportBuffer_ {
public:
_BTextViewSupportBuffer_(long inExtraCount = 0,
long inCount = 0);
_BTextViewSupportBuffer_(int32 inExtraCount = 0, int32 inCount = 0);
virtual ~_BTextViewSupportBuffer_();
void InsertItemsAt(int32 inNumItems, int32 inAtIndex, const T *inItem);
@@ -57,20 +56,20 @@ virtual ~_BTextViewSupportBuffer_();
int32 ItemCount() const;
//protected:
protected:
int32 fExtraCount;
int32 fItemCount;
T* fBuffer;
int32 fItemCount;
int32 fBufferCount;
T* fBuffer;
};
//------------------------------------------------------------------------------
template <class T>
_BTextViewSupportBuffer_<T>::_BTextViewSupportBuffer_(long inExtraCount,
long inCount)
_BTextViewSupportBuffer_<T>::_BTextViewSupportBuffer_(int32 inExtraCount,
int32 inCount)
: fExtraCount(inExtraCount),
fItemCount(inCount),
fBuffer(NULL),
fBufferCount(fExtraCount + fItemCount)
fBufferCount(fExtraCount + fItemCount),
fBuffer(NULL)
{
fBuffer = (T *)calloc(fExtraCount + fItemCount, sizeof(T));
}
@@ -92,8 +91,8 @@ void _BTextViewSupportBuffer_<T>::InsertItemsAt(int32 inNumItems,
inAtIndex = (inAtIndex > fItemCount) ? fItemCount : inAtIndex;
inAtIndex = (inAtIndex < 0) ? 0 : inAtIndex;
long delta = inNumItems * sizeof(T);
long logSize = fItemCount * sizeof(T);
int32 delta = inNumItems * sizeof(T);
int32 logSize = fItemCount * sizeof(T);
if ((logSize + delta) >= fBufferCount) {
fBufferCount = logSize + delta + (fExtraCount * sizeof(T));
fBuffer = (T *)realloc(fBuffer, fBufferCount);
@@ -121,9 +120,9 @@ _BTextViewSupportBuffer_<T>::RemoveItemsAt(int32 inNumItems,
memmove(loc, loc + inNumItems,
(fItemCount - (inNumItems + inAtIndex)) * sizeof(T));
long delta = inNumItems * sizeof(T);
long logSize = fItemCount * sizeof(T);
long extraSize = fBufferCount - (logSize - delta);
int32 delta = inNumItems * sizeof(T);
int32 logSize = fItemCount * sizeof(T);
uint32 extraSize = fBufferCount - (logSize - delta);
if (extraSize > (fExtraCount * sizeof(T))) {
fBufferCount = (logSize - delta) + (fExtraCount * sizeof(T));
fBuffer = (T *)realloc(fBuffer, fBufferCount);
+3 -5
View File
@@ -321,7 +321,6 @@ _BTypingUndoBuffer_::InputCharacter(int32 len)
void
_BTypingUndoBuffer_::Reset()
{
printf("Reset\n");
free(fTextData);
fTextView->GetSelection(&fStart, &fEnd);
fTextLength = fEnd - fStart;
@@ -345,9 +344,8 @@ _BTypingUndoBuffer_::BackwardErase()
fTextView->GetSelection(&start, &end);
const char *text = fTextView->Text();
int32 charLen = UTF8CharLenBACK(text + start, text);
printf("Char Len: %d\n", charLen);
int32 charLen = UTF8PreviousCharLen(text + start, text);
if (start != fTypedEnd || end != fTypedEnd) {
Reset();
// if we've got a selection, we're already done
@@ -377,7 +375,7 @@ _BTypingUndoBuffer_::ForwardErase()
fTextView->GetSelection(&start, &end);
int32 charLen = UTF8CharLenFWD(fTextView->Text() + start);
int32 charLen = UTF8NextCharLen(fTextView->Text() + start);
printf("Char Len: %d\n", charLen);
if (start != fTypedEnd || end != fTypedEnd || fUndone > 0) {
+303 -25
View File
@@ -1,44 +1,174 @@
// A quick and dirty implementation of _BWidthBuffer_, needed to compile
// OpenTracker. We'll want to implement it correctly.
/*
* Copyright (c) 2003 Stefano Ceccherini
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <Debug.h>
#include <Font.h>
#include "moreUTF8.h"
#include "WidthBuffer.h"
_BWidthBuffer_::_BWidthBuffer_()
#include <cstdio>
const uint32 kTableCount = 128;
struct hashed_escapement
{
//TODO: Implement
uint32 code;
float escapement;
};
/*! \brief Convert a UTF8 char to a code, which will be used
to uniquely identify the charachter in the hash table.
\param text A pointer to the charachter to examine.
\param charLen the length of the charachter to examine.
\return The code for the given charachter,
*/
static inline uint32
CharToCode(const char *text, const int32 charLen)
{
uint32 value = 0;
int32 shiftVal = 24;
for (int32 c = 0; c < charLen; c++) {
uchar ch = text[c];
value |= (ch << shiftVal);
shiftVal -= 8;
}
return value;
}
/*! \brief Initializes the object.
*/
_BWidthBuffer_::_BWidthBuffer_()
:
_BTextViewSupportBuffer_<_width_table_>(1, 0)
{
}
/*! \brief Frees the allocated resources.
*/
_BWidthBuffer_::~_BWidthBuffer_()
{
//TODO: Implement
for (int32 x = 0; x < fItemCount; x++)
delete[] fBuffer[x].widths;
}
/*! \brief Returns how much room is required to draw a string in the font.
\param inText The string to be examined.
\param fromOffset The offset in the string where to begin the examination.
\param lenght The amount of bytes to be examined.
\param inStyle The font.
\return The space (in pixels) required to draw the given string.
*/
float
_BWidthBuffer_::StringWidth(const char *inText, int32 fromOffset, int32 length,
const BFont *inStyle)
{
// TODO: Should use local hashed items
return inStyle->StringWidth(inText + fromOffset, length);
if (inText == NULL)
return 0;
int32 index = 0;
if (!FindTable(inStyle, &index))
index = InsertTable(inStyle);
char *text = NULL;
int32 numChars = 0;
int32 textLen = 0;
float fontSize = inStyle->Size();
float stringWidth = 0;
if (length > 0) {
do {
int32 charLen = UTF8NextCharLen(inText + fromOffset);
// End of string, bail out
if (charLen == 0)
break;
// Some magic, to uniquely identify this charachter
uint32 value = CharToCode(inText + fromOffset, charLen);
float escapement;
if (GetEscapement(value, index, &escapement)) {
// Well, we've got a match for this charachter
stringWidth += escapement * fontSize;
} else {
// Store this charachter into an array, which we'll
// pass to HashEscapements() later
int32 offset = textLen;
textLen += charLen;
numChars++;
text = (char *)realloc(text, textLen);
for (int32 x = 0; x < charLen; x++)
text[offset + x] = inText[fromOffset + x];
}
fromOffset += charLen;
} while (fromOffset < length);
}
if (text != NULL) {
// We've found some charachters which aren't yet in the hash table.
// Get their width via HashEscapements()
stringWidth += HashEscapements(text, numChars, textLen, index, inStyle) * fontSize;
free(text);
}
return stringWidth;
}
/*! \brief Returns how much room is required to draw a string in the font.
\param inBuffer The _BTextGapBuffer_ to be examined.
\param fromOffset The offset in the _BTextGapBuffer_ where to begin the examination.
\param lenght The amount of bytes to be examined.
\param inStyle The font.
\return The space (in pixels) required to draw the given string.
*/
float
_BWidthBuffer_::StringWidth(_BTextGapBuffer_ &inBuffer, int32 fromOffset, int32 length,
const BFont *inStyle)
{
return inStyle->StringWidth(inBuffer.Text() + fromOffset, length);
return StringWidth(inBuffer.Text(), fromOffset, length, inStyle);
}
/*! \brief Searches for the table for the given font.
\param inStyle The font to search for.
\param outIndex a pointer to an int32, where the function will store
the index of the table, if found, or -1, if not.
\return \c true if the function founds the table,
\c false if not.
*/
bool
_BWidthBuffer_::FindTable(const BFont *inStyle, int32 *outIndex)
{
if (inStyle == NULL)
return false;
float fontSize = inStyle->Size();
int32 fontCode = inStyle->FamilyAndStyle();
int32 tableIndex = -1;
for (int32 i = 0; i < fItemCount; i++) {
#if B_BEOS_VERSION_DANO
@@ -46,43 +176,191 @@ _BWidthBuffer_::FindTable(const BFont *inStyle, int32 *outIndex)
#else
if (fontSize == fBuffer[i].fontSize && fontCode == fBuffer[i].fontCode) {
#endif
*outIndex = i;
return true;
tableIndex = i;
break;
}
}
*outIndex = -1;
}
if (outIndex != NULL)
*outIndex = tableIndex;
return false;
return tableIndex != -1;
}
/*! \brief Creates and insert an empty table for the given font.
\param font The font to create the table for.
\return The index of the newly created table.
*/
int32
_BWidthBuffer_::InsertTable(const BFont *font)
{
//TODO: Implement
return B_ERROR;
_width_table_ table;
hashed_escapement *deltas = new hashed_escapement[kTableCount];
#if B_BEOS_VERSION_DANO
table.font = font;
#else
table.fontSize = font->Size();
table.fontCode = font->FamilyAndStyle();
#endif
table.hashCount = 0;
table.tableCount = kTableCount;
table.widths = deltas;
for (uint32 i = 0; i < kTableCount; i++) {
deltas[i].code = (uint32)-1;
deltas[i].escapement = 0;
}
int32 position = fItemCount;
InsertItemsAt(1, position, &table);
return position;
}
/*! \brief Gets the escapement for the given charachter.
\param value An integer which uniquely identifies a charachter.
\param index The index of the table to search.
\param escapement A pointer to a float, where the function will
store the escapement.
\return \c true if the function could find the escapement
for the given charachter, \c false if not.
*/
bool
_BWidthBuffer_::GetEscapement(uint32 code, int32 index, float *escapement)
_BWidthBuffer_::GetEscapement(uint32 value, int32 index, float *escapement)
{
//TODO: Implement
return false;
_width_table_ *table = &fBuffer[index];
hashed_escapement *widths = static_cast<hashed_escapement *>(table->widths);
uint32 hashed = Hash(value) & (table->tableCount - 1);
DEBUG_ONLY(uint32 iterations = 1;)
uint32 found;
while ((found = widths[hashed].code) != (uint32)-1) {
if (found == value)
break;
hashed++;
if (hashed >= (uint32)table->tableCount)
hashed = 0;
DEBUG_ONLY(iterations++;)
}
if (found == (uint32)-1)
return false;
PRINT(("Value found with %d iterations\n", iterations));
if (escapement != NULL)
*escapement = widths[hashed].escapement;
return true;
}
uint32
_BWidthBuffer_::Hash(uint32 val)
{
//TODO: Implement
return B_ERROR;
uint32 shifted = val >> 24;
uint32 result = (val >> 15) + (shifted * 3);
result ^= (val >> 6) - (shifted * 22);
result ^= (val << 3);
return result;
}
void
_BWidthBuffer_::HashEscapements(const char *inText, int32 numChars, int32,
int32, const BFont *inStyle)
/*! \brief Gets the escapements for the given string, and put them into
the hash table.
\param inText The string to be examined.
\param numChars The amount of charachters contained in the string.
\param textLen the amount of bytes contained in the string.
\param tableIndex the index of the table where the escapements
should be put.
\param inStyle the font.
\return The width of the supplied string (which should be multiplied by
the size of the font).
*/
float
_BWidthBuffer_::HashEscapements(const char *inText, int32 numChars, int32 textLen,
int32 tableIndex, const BFont *inStyle)
{
//TODO: Implement
float *escapements = new float[numChars];
inStyle->GetEscapements(inText, numChars, escapements);
_width_table_ *table = &fBuffer[tableIndex];
hashed_escapement *widths = static_cast<hashed_escapement *>(table->widths);
int32 offset = 0;
int32 charCount = 0;
// Insert the escapements into the hash table
do {
int32 charLen = UTF8NextCharLen(inText + offset);
if (charLen == 0)
break;
uint32 value = CharToCode(inText + offset, charLen);
uint32 hashed = Hash(value) & (table->tableCount - 1);
uint32 found = widths[hashed].code;
// Check if the value is already in the table
if (found != value) {
while ((found = widths[hashed].code) != (uint32)-1) {
if (found == value)
break;
if (++hashed >= (uint32)table->tableCount)
hashed = 0;
}
if (found == (uint32)-1) {
// The value is not in the table. Add it.
widths[hashed].code = value;
widths[hashed].escapement = escapements[charCount];
table->hashCount++;
}
// We always keep some free space in the hash table
// TODO: Not sure how much space, currently we double
// the current size when hashCount is at least 2/3 of
// the total size.
if (table->tableCount * 2 / 3 <= table->hashCount) {
table->hashCount = 0;
int32 newSize = table->tableCount * 2;
// Create and initialize a new hash table
hashed_escapement *newWidths = new hashed_escapement[newSize];
for (int32 x = 0; x < newSize; x++) {
newWidths[x].code = (uint32)-1;
newWidths[x].escapement = 0;
}
// Rehash the values, and put them into the new table
for (int32 oldPos = 0; oldPos < table->tableCount; oldPos++) {
if (widths[oldPos].code != (uint32) -1) {
uint32 newPos = Hash(widths[oldPos].code) & (newSize - 1);
while (newWidths[newPos].code != (uint32)-1) {
if (++newPos >= (uint32)newSize)
newPos = 0;
}
newWidths[newPos].code = widths[oldPos].code;
newWidths[newPos].escapement = widths[oldPos].escapement;
table->hashCount++;
}
}
table->tableCount = newSize;
// Delete the old table, and put the new pointer into the _width_table_
delete[] widths;
widths = newWidths;
}
}
charCount++;
offset += charLen;
} while (offset < textLen);
// Calculate the width of the string
float width = 0;
for (int32 x = 0; x < numChars; x++)
width += escapements[x];
delete[] escapements;
return width;
}
+2 -4
View File
@@ -33,11 +33,9 @@ private:
int32 InsertTable(const BFont *font);
bool GetEscapement(uint32, int32, float *);
void HashEscapements(const char *, int32, int32, int32, const BFont *);
float HashEscapements(const char *, int32, int32, int32, const BFont *);
uint32 Hash(uint32);
void CCheck();
static uint32 Hash(uint32);
};
#endif // __WIDTHBUFFER_H