From 04d40ff247a5777d454416faed2819f16b4990e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 11 Mar 2006 12:58:31 +0000 Subject: [PATCH] * 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 --- src/kits/interface/BTextView/TextView.cpp | 115 +++++++++++----------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/src/kits/interface/BTextView/TextView.cpp b/src/kits/interface/BTextView/TextView.cpp index 39b618eb70..162aacd72e 100644 --- a/src/kits/interface/BTextView/TextView.cpp +++ b/src/kits/interface/BTextView/TextView.cpp @@ -72,14 +72,15 @@ struct flattened_text_run { uint16 _reserved_; /* 0 */ }; - struct flattened_text_run_array { - uchar magic[4]; /* 41 6c 69 21 */ - uchar version[4]; /* 00 00 00 00 */ + uint32 magic; + uint32 version; int32 count; flattened_text_run styles[1]; }; +static const uint32 kFlattenedTextRunArrayMagic = 'Ali!'; +static const uint32 kFlattenedTextRunArrayVersion = 0; enum { B_SEPARATOR_CHARACTER, @@ -2492,17 +2493,18 @@ BTextView::AllocRunArray(int32 entryCount, int32 *outSize) *outSize = 0; return NULL; } - + memset(runArray, 0, sizeof(size)); runArray->count = entryCount; // Call constructors explicitly as the text_run_array - // was allocated with malloc - for (int32 i = 0; i < runArray->count; i++) + // was allocated with malloc (and has to, for backwards + // compatibility) + for (int32 i = 0; i < runArray->count; i++) { new (&runArray->runs[i].font) BFont; - //runArray->runs[i].font = new BFont; - + } + if (outSize != NULL) *outSize = size; @@ -2540,44 +2542,39 @@ BTextView::FreeRunArray(text_run_array *array) /* static */ void * -BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) +BTextView::FlattenRunArray(const text_run_array* runArray, int32* _size) { CALLED(); - int32 size = sizeof(flattened_text_run_array) + (inArray->count - 1) * - sizeof(flattened_text_run); + int32 size = sizeof(flattened_text_run_array) + (runArray->count - 1) + * sizeof(flattened_text_run); flattened_text_run_array *array = (flattened_text_run_array *)malloc(size); if (array == NULL) { - *outSize = 0; + if (_size) + *_size = 0; return NULL; } - array->magic[0] = 0x41; - array->magic[1] = 0x6c; - array->magic[2] = 0x69; - array->magic[3] = 0x21; - array->version[0] = 0x00; - array->version[1] = 0x00; - array->version[2] = 0x00; - array->version[3] = 0x00; - array->count = inArray->count; + array->magic = B_HOST_TO_BENDIAN_INT32(kFlattenedTextRunArrayMagic); + array->version = B_HOST_TO_BENDIAN_INT32(kFlattenedTextRunArrayVersion); + array->count = B_HOST_TO_BENDIAN_INT32(runArray->count); - for (int32 i = 0; i < inArray->count; i++) { - array->styles[i].offset = inArray->runs[i].offset; - inArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family, + for (int32 i = 0; i < runArray->count; i++) { + array->styles[i].offset = B_HOST_TO_BENDIAN_INT32(runArray->runs[i].offset); + runArray->runs[i].font.GetFamilyAndStyle(&array->styles[i].family, &array->styles[i].style); - array->styles[i].size = inArray->runs[i].font.Size(); - array->styles[i].shear = inArray->runs[i].font.Shear(); - array->styles[i].face = inArray->runs[i].font.Face(); - array->styles[i].red = inArray->runs[i].color.red; - array->styles[i].green = inArray->runs[i].color.green; - array->styles[i].blue = inArray->runs[i].color.blue; + array->styles[i].size = B_HOST_TO_BENDIAN_FLOAT(runArray->runs[i].font.Size()); + array->styles[i].shear = B_HOST_TO_BENDIAN_FLOAT(runArray->runs[i].font.Shear()); + array->styles[i].face = B_HOST_TO_BENDIAN_INT16(runArray->runs[i].font.Face()); + array->styles[i].red = runArray->runs[i].color.red; + array->styles[i].green = runArray->runs[i].color.green; + array->styles[i].blue = runArray->runs[i].color.blue; array->styles[i].alpha = 255; array->styles[i]._reserved_ = 0; } - if (outSize) - *outSize = size; + if (_size) + *_size = size; return array; } @@ -2585,43 +2582,49 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) /* static */ text_run_array * -BTextView::UnflattenRunArray(const void *data, int32 *outSize) +BTextView::UnflattenRunArray(const void* data, int32* _size) { CALLED(); flattened_text_run_array *array = (flattened_text_run_array *)data; - if (array->magic[0] != 0x41 || array->magic[1] != 0x6c || - array->magic[2] != 0x69 || array->magic[3] != 0x21 || - array->version[0] != 0x00 || array->version[1] != 0x00 || - array->version[2] != 0x00 || array->version[3] != 0x00) { - - if (outSize) - *outSize = 0; + if (B_BENDIAN_TO_HOST_INT32(array->magic) != kFlattenedTextRunArrayMagic + || B_BENDIAN_TO_HOST_INT32(array->version) != kFlattenedTextRunArrayVersion) { + if (_size) + *_size = 0; return NULL; } - - text_run_array *run_array = AllocRunArray(array->count, outSize); - if (run_array == NULL) + int32 count = B_BENDIAN_TO_HOST_INT32(array->count); + + text_run_array *runArray = AllocRunArray(count, _size); + if (runArray == NULL) return NULL; - for (int32 i = 0; i < array->count; i++) { - run_array->runs[i].offset = 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); + for (int32 i = 0; i < count; i++) { + runArray->runs[i].offset = B_BENDIAN_TO_HOST_INT32(array->styles[i].offset); - run_array->runs[i].color.red = array->styles[i].red; - run_array->runs[i].color.green = array->styles[i].green; - run_array->runs[i].color.blue = array->styles[i].blue; - run_array->runs[i].color.alpha = array->styles[i].alpha; + // Set family and style independently from each other, so that + // even if the family doesn't exist, we try to preserve the style + runArray->runs[i].font.SetFamilyAndStyle(array->styles[i].family, NULL); + 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; }