* Fixed flattening/unflattening text_run_arrays; they have to be converted to

and from big endian - this fixes our StyledEdit not being able to read files
  written under BeOS and vice versa.
* Made UnflattenRunArray() more robust against missing fonts; the style is now
  tried to be preserved. Note that BeOS doesn't maintain the "face" field in
  the flattened run arrays correctly.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16701 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-03-11 12:58:31 +00:00
parent 9acf186f65
commit 04d40ff247
+59 -56
View File
@@ -72,14 +72,15 @@ struct flattened_text_run {
uint16 _reserved_; /* 0 */ uint16 _reserved_; /* 0 */
}; };
struct flattened_text_run_array { struct flattened_text_run_array {
uchar magic[4]; /* 41 6c 69 21 */ uint32 magic;
uchar version[4]; /* 00 00 00 00 */ uint32 version;
int32 count; int32 count;
flattened_text_run styles[1]; flattened_text_run styles[1];
}; };
static const uint32 kFlattenedTextRunArrayMagic = 'Ali!';
static const uint32 kFlattenedTextRunArrayVersion = 0;
enum { enum {
B_SEPARATOR_CHARACTER, B_SEPARATOR_CHARACTER,
@@ -2492,17 +2493,18 @@ BTextView::AllocRunArray(int32 entryCount, int32 *outSize)
*outSize = 0; *outSize = 0;
return NULL; return NULL;
} }
memset(runArray, 0, sizeof(size)); memset(runArray, 0, sizeof(size));
runArray->count = entryCount; runArray->count = entryCount;
// Call constructors explicitly as the text_run_array // Call constructors explicitly as the text_run_array
// was allocated with malloc // was allocated with malloc (and has to, for backwards
for (int32 i = 0; i < runArray->count; i++) // compatibility)
for (int32 i = 0; i < runArray->count; i++) {
new (&runArray->runs[i].font) BFont; new (&runArray->runs[i].font) BFont;
//runArray->runs[i].font = new BFont; }
if (outSize != NULL) if (outSize != NULL)
*outSize = size; *outSize = size;
@@ -2540,44 +2542,39 @@ BTextView::FreeRunArray(text_run_array *array)
/* static */ /* static */
void * void *
BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) BTextView::FlattenRunArray(const text_run_array* runArray, int32* _size)
{ {
CALLED(); CALLED();
int32 size = sizeof(flattened_text_run_array) + (inArray->count - 1) * int32 size = sizeof(flattened_text_run_array) + (runArray->count - 1)
sizeof(flattened_text_run); * sizeof(flattened_text_run);
flattened_text_run_array *array = (flattened_text_run_array *)malloc(size); flattened_text_run_array *array = (flattened_text_run_array *)malloc(size);
if (array == NULL) { if (array == NULL) {
*outSize = 0; if (_size)
*_size = 0;
return NULL; return NULL;
} }
array->magic[0] = 0x41; array->magic = B_HOST_TO_BENDIAN_INT32(kFlattenedTextRunArrayMagic);
array->magic[1] = 0x6c; array->version = B_HOST_TO_BENDIAN_INT32(kFlattenedTextRunArrayVersion);
array->magic[2] = 0x69; array->count = B_HOST_TO_BENDIAN_INT32(runArray->count);
array->magic[3] = 0x21;
array->version[0] = 0x00;
array->version[1] = 0x00;
array->version[2] = 0x00;
array->version[3] = 0x00;
array->count = inArray->count;
for (int32 i = 0; i < inArray->count; i++) { for (int32 i = 0; i < runArray->count; i++) {
array->styles[i].offset = inArray->runs[i].offset; array->styles[i].offset = B_HOST_TO_BENDIAN_INT32(runArray->runs[i].offset);
inArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family, runArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family,
&array->styles[i].style); &array->styles[i].style);
array->styles[i].size = inArray->runs[i].font.Size(); array->styles[i].size = B_HOST_TO_BENDIAN_FLOAT(runArray->runs[i].font.Size());
array->styles[i].shear = inArray->runs[i].font.Shear(); array->styles[i].shear = B_HOST_TO_BENDIAN_FLOAT(runArray->runs[i].font.Shear());
array->styles[i].face = inArray->runs[i].font.Face(); array->styles[i].face = B_HOST_TO_BENDIAN_INT16(runArray->runs[i].font.Face());
array->styles[i].red = inArray->runs[i].color.red; array->styles[i].red = runArray->runs[i].color.red;
array->styles[i].green = inArray->runs[i].color.green; array->styles[i].green = runArray->runs[i].color.green;
array->styles[i].blue = inArray->runs[i].color.blue; array->styles[i].blue = runArray->runs[i].color.blue;
array->styles[i].alpha = 255; array->styles[i].alpha = 255;
array->styles[i]._reserved_ = 0; array->styles[i]._reserved_ = 0;
} }
if (outSize) if (_size)
*outSize = size; *_size = size;
return array; return array;
} }
@@ -2585,43 +2582,49 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize)
/* static */ /* static */
text_run_array * text_run_array *
BTextView::UnflattenRunArray(const void *data, int32 *outSize) BTextView::UnflattenRunArray(const void* data, int32* _size)
{ {
CALLED(); CALLED();
flattened_text_run_array *array = (flattened_text_run_array *)data; flattened_text_run_array *array = (flattened_text_run_array *)data;
if (array->magic[0] != 0x41 || array->magic[1] != 0x6c || if (B_BENDIAN_TO_HOST_INT32(array->magic) != kFlattenedTextRunArrayMagic
array->magic[2] != 0x69 || array->magic[3] != 0x21 || || B_BENDIAN_TO_HOST_INT32(array->version) != kFlattenedTextRunArrayVersion) {
array->version[0] != 0x00 || array->version[1] != 0x00 || if (_size)
array->version[2] != 0x00 || array->version[3] != 0x00) { *_size = 0;
if (outSize)
*outSize = 0;
return NULL; return NULL;
} }
text_run_array *run_array = AllocRunArray(array->count, outSize); int32 count = B_BENDIAN_TO_HOST_INT32(array->count);
if (run_array == NULL)
text_run_array *runArray = AllocRunArray(count, _size);
if (runArray == NULL)
return NULL; return NULL;
for (int32 i = 0; i < array->count; i++) { for (int32 i = 0; i < count; i++) {
run_array->runs[i].offset = array->styles[i].offset; runArray->runs[i].offset = B_BENDIAN_TO_HOST_INT32(array->styles[i].offset);
run_array->runs[i].font.SetFamilyAndStyle(array->styles[i].family,
array->styles[i].style);
run_array->runs[i].font.SetSize(array->styles[i].size);
run_array->runs[i].font.SetShear(array->styles[i].shear);
run_array->runs[i].font.SetFace(array->styles[i].face);
run_array->runs[i].color.red = array->styles[i].red; // Set family and style independently from each other, so that
run_array->runs[i].color.green = array->styles[i].green; // even if the family doesn't exist, we try to preserve the style
run_array->runs[i].color.blue = array->styles[i].blue; runArray->runs[i].font.SetFamilyAndStyle(array->styles[i].family, NULL);
run_array->runs[i].color.alpha = array->styles[i].alpha; runArray->runs[i].font.SetFamilyAndStyle(NULL, array->styles[i].style);
runArray->runs[i].font.SetSize(B_BENDIAN_TO_HOST_FLOAT(array->styles[i].size));
runArray->runs[i].font.SetShear(B_BENDIAN_TO_HOST_FLOAT(array->styles[i].shear));
uint16 face = B_BENDIAN_TO_HOST_INT16(array->styles[i].face);
if (face != B_REGULAR_FACE) {
// Be's version doesn't seem to set this correctly
runArray->runs[i].font.SetFace(face);
}
runArray->runs[i].color.red = array->styles[i].red;
runArray->runs[i].color.green = array->styles[i].green;
runArray->runs[i].color.blue = array->styles[i].blue;
runArray->runs[i].color.alpha = array->styles[i].alpha;
} }
return run_array; return runArray;
} }