1fb07ece0SStephan Aßmus /* 2fb07ece0SStephan Aßmus * Copyright 2006, Haiku. All rights reserved. 3fb07ece0SStephan Aßmus * Distributed under the terms of the MIT License. 4fb07ece0SStephan Aßmus * 5fb07ece0SStephan Aßmus * Authors: 6fb07ece0SStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 7fb07ece0SStephan Aßmus */ 8fb07ece0SStephan Aßmus 9fb07ece0SStephan Aßmus #include "FlatIconImporter.h" 10fb07ece0SStephan Aßmus 11fb07ece0SStephan Aßmus #include <new> 12fb07ece0SStephan Aßmus #include <stdio.h> 13fb07ece0SStephan Aßmus 14fb07ece0SStephan Aßmus #include <Archivable.h> 15fb07ece0SStephan Aßmus #include <DataIO.h> 16fb07ece0SStephan Aßmus #include <Message.h> 17fb07ece0SStephan Aßmus 18fb07ece0SStephan Aßmus #include "AffineTransformer.h" 19fb07ece0SStephan Aßmus #include "AutoDeleter.h" 20fb07ece0SStephan Aßmus #include "ContourTransformer.h" 21fb07ece0SStephan Aßmus #include "FlatIconFormat.h" 22fb07ece0SStephan Aßmus #include "Gradient.h" 23fb07ece0SStephan Aßmus #include "Icon.h" 24fb07ece0SStephan Aßmus #include "LittleEndianBuffer.h" 25fb07ece0SStephan Aßmus #include "PathCommandQueue.h" 26fb07ece0SStephan Aßmus #include "PathContainer.h" 27fb07ece0SStephan Aßmus #include "PerspectiveTransformer.h" 28fb07ece0SStephan Aßmus #include "Shape.h" 29fb07ece0SStephan Aßmus #include "StrokeTransformer.h" 30fb07ece0SStephan Aßmus #include "Style.h" 31fb07ece0SStephan Aßmus #include "StyleContainer.h" 32fb07ece0SStephan Aßmus #include "VectorPath.h" 33fb07ece0SStephan Aßmus 34fb07ece0SStephan Aßmus using std::nothrow; 35fb07ece0SStephan Aßmus 36fb07ece0SStephan Aßmus // constructor 37fb07ece0SStephan Aßmus FlatIconImporter::FlatIconImporter() 38014c7e94SStephan Aßmus #ifdef ICON_O_MATIC 39014c7e94SStephan Aßmus : Importer() 40014c7e94SStephan Aßmus #endif 41fb07ece0SStephan Aßmus { 42fb07ece0SStephan Aßmus } 43fb07ece0SStephan Aßmus 44fb07ece0SStephan Aßmus // destructor 45fb07ece0SStephan Aßmus FlatIconImporter::~FlatIconImporter() 46fb07ece0SStephan Aßmus { 47fb07ece0SStephan Aßmus } 48fb07ece0SStephan Aßmus 49fb07ece0SStephan Aßmus // Import 50fb07ece0SStephan Aßmus status_t 51fb07ece0SStephan Aßmus FlatIconImporter::Import(Icon* icon, BPositionIO* stream) 52fb07ece0SStephan Aßmus { 53014c7e94SStephan Aßmus #ifdef ICON_O_MATIC 54014c7e94SStephan Aßmus status_t ret = Init(icon); 55014c7e94SStephan Aßmus if (ret < B_OK) 56014c7e94SStephan Aßmus return ret; 57014c7e94SStephan Aßmus #else 58014c7e94SStephan Aßmus status_t ret; 59014c7e94SStephan Aßmus #endif 60014c7e94SStephan Aßmus 61fb07ece0SStephan Aßmus // seek around in the stream to figure out the size 62fb07ece0SStephan Aßmus off_t size = stream->Seek(0, SEEK_END); 63fb07ece0SStephan Aßmus if (stream->Seek(0, SEEK_SET) != 0) 64fb07ece0SStephan Aßmus return B_ERROR; 65fb07ece0SStephan Aßmus 66fb07ece0SStephan Aßmus // we chicken out on anything larger than 256k 67fb07ece0SStephan Aßmus if (size <= 0 || size > 256 * 1024) 68fb07ece0SStephan Aßmus return B_BAD_VALUE; 69fb07ece0SStephan Aßmus 70fb07ece0SStephan Aßmus // read the entire stream into a buffer 71fb07ece0SStephan Aßmus LittleEndianBuffer buffer(size); 72fb07ece0SStephan Aßmus if (!buffer.Buffer()) 73fb07ece0SStephan Aßmus return B_NO_MEMORY; 74fb07ece0SStephan Aßmus 75fb07ece0SStephan Aßmus if (stream->Read(buffer.Buffer(), size) != size) 76fb07ece0SStephan Aßmus return B_ERROR; 77fb07ece0SStephan Aßmus 78014c7e94SStephan Aßmus ret = _ParseSections(buffer, icon); 79fb07ece0SStephan Aßmus 80fb07ece0SStephan Aßmus return ret; 81fb07ece0SStephan Aßmus } 82fb07ece0SStephan Aßmus 83fb07ece0SStephan Aßmus // Import 84fb07ece0SStephan Aßmus status_t 85fb07ece0SStephan Aßmus FlatIconImporter::Import(Icon* icon, uint8* _buffer, size_t size) 86fb07ece0SStephan Aßmus { 87014c7e94SStephan Aßmus #ifdef ICON_O_MATIC 88014c7e94SStephan Aßmus status_t ret = Init(icon); 89014c7e94SStephan Aßmus if (ret < B_OK) 90014c7e94SStephan Aßmus return ret; 91014c7e94SStephan Aßmus #endif 92014c7e94SStephan Aßmus 93fb07ece0SStephan Aßmus if (!_buffer) 94fb07ece0SStephan Aßmus return B_BAD_VALUE; 95fb07ece0SStephan Aßmus 96fb07ece0SStephan Aßmus // attach LittleEndianBuffer to buffer 97fb07ece0SStephan Aßmus LittleEndianBuffer buffer(_buffer, size); 98fb07ece0SStephan Aßmus 99fb07ece0SStephan Aßmus return _ParseSections(buffer, icon); 100fb07ece0SStephan Aßmus } 101fb07ece0SStephan Aßmus 102fb07ece0SStephan Aßmus // #pragma mark - 103fb07ece0SStephan Aßmus 104fb07ece0SStephan Aßmus // _ParseSections 105fb07ece0SStephan Aßmus status_t 106fb07ece0SStephan Aßmus FlatIconImporter::_ParseSections(LittleEndianBuffer& buffer, Icon* icon) 107fb07ece0SStephan Aßmus { 108fb07ece0SStephan Aßmus // test if this is an icon at all 109fb07ece0SStephan Aßmus uint32 magic; 110fb07ece0SStephan Aßmus if (!buffer.Read(magic) || magic != FLAT_ICON_MAGIC) 111*1a948d74SAxel Dörfler return B_BAD_TYPE; 112fb07ece0SStephan Aßmus 113fb07ece0SStephan Aßmus // styles 114fb07ece0SStephan Aßmus StyleContainer* styles = icon->Styles(); 115fb07ece0SStephan Aßmus status_t ret = _ParseStyles(buffer, styles); 116fb07ece0SStephan Aßmus if (ret < B_OK) { 117fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 118fb07ece0SStephan Aßmus "error parsing styles: %s\n", strerror(ret)); 119fb07ece0SStephan Aßmus return ret; 120fb07ece0SStephan Aßmus } 121fb07ece0SStephan Aßmus 122fb07ece0SStephan Aßmus // paths 123fb07ece0SStephan Aßmus PathContainer* paths = icon->Paths(); 124fb07ece0SStephan Aßmus ret = _ParsePaths(buffer, paths); 125fb07ece0SStephan Aßmus if (ret < B_OK) { 126fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 127fb07ece0SStephan Aßmus "error parsing paths: %s\n", strerror(ret)); 128fb07ece0SStephan Aßmus return ret; 129fb07ece0SStephan Aßmus } 130fb07ece0SStephan Aßmus 131fb07ece0SStephan Aßmus // shapes 132fb07ece0SStephan Aßmus ret = _ParseShapes(buffer, styles, paths, icon->Shapes()); 133fb07ece0SStephan Aßmus if (ret < B_OK) { 134fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 135fb07ece0SStephan Aßmus "error parsing shapes: %s\n", strerror(ret)); 136fb07ece0SStephan Aßmus return ret; 137fb07ece0SStephan Aßmus } 138fb07ece0SStephan Aßmus 139fb07ece0SStephan Aßmus return B_OK; 140fb07ece0SStephan Aßmus } 141fb07ece0SStephan Aßmus 142fb07ece0SStephan Aßmus // _ReadTransformable 143fb07ece0SStephan Aßmus static bool 144fb07ece0SStephan Aßmus _ReadTransformable(LittleEndianBuffer& buffer, Transformable* transformable) 145fb07ece0SStephan Aßmus { 146fb07ece0SStephan Aßmus int32 matrixSize = Transformable::matrix_size; 147fb07ece0SStephan Aßmus double matrix[matrixSize]; 148fb07ece0SStephan Aßmus for (int32 i = 0; i < matrixSize; i++) { 149fb07ece0SStephan Aßmus float value; 150fb07ece0SStephan Aßmus if (!read_float_24(buffer, value)) 151fb07ece0SStephan Aßmus return false; 152fb07ece0SStephan Aßmus matrix[i] = value; 153fb07ece0SStephan Aßmus } 154fb07ece0SStephan Aßmus transformable->LoadFrom(matrix); 155fb07ece0SStephan Aßmus return true; 156fb07ece0SStephan Aßmus } 157fb07ece0SStephan Aßmus 158fb07ece0SStephan Aßmus // _ReadTranslation 159fb07ece0SStephan Aßmus static bool 160fb07ece0SStephan Aßmus _ReadTranslation(LittleEndianBuffer& buffer, Transformable* transformable) 161fb07ece0SStephan Aßmus { 162fb07ece0SStephan Aßmus BPoint t; 163fb07ece0SStephan Aßmus if (read_coord(buffer, t.x) && read_coord(buffer, t.y)) { 164fb07ece0SStephan Aßmus transformable->TranslateBy(t); 165fb07ece0SStephan Aßmus return true; 166fb07ece0SStephan Aßmus } 167fb07ece0SStephan Aßmus 168fb07ece0SStephan Aßmus return false; 169fb07ece0SStephan Aßmus } 170fb07ece0SStephan Aßmus 171fb07ece0SStephan Aßmus // _ReadColorStyle 172fb07ece0SStephan Aßmus static Style* 1732f953b71SStephan Aßmus _ReadColorStyle(LittleEndianBuffer& buffer, bool alpha, bool gray) 174fb07ece0SStephan Aßmus { 175fb07ece0SStephan Aßmus rgb_color color; 176fb07ece0SStephan Aßmus if (alpha) { 1772f953b71SStephan Aßmus if (gray) { 1782f953b71SStephan Aßmus if (!buffer.Read(color.red) 1792f953b71SStephan Aßmus || !buffer.Read(color.alpha)) 1802f953b71SStephan Aßmus return NULL; 1812f953b71SStephan Aßmus color.green = color.blue = color.red; 1822f953b71SStephan Aßmus } else { 183fb07ece0SStephan Aßmus if (!buffer.Read((uint32&)color)) 184fb07ece0SStephan Aßmus return NULL; 1852f953b71SStephan Aßmus } 186fb07ece0SStephan Aßmus } else { 187fb07ece0SStephan Aßmus color.alpha = 255; 1882f953b71SStephan Aßmus if (gray) { 1892f953b71SStephan Aßmus if (!buffer.Read(color.red)) 1902f953b71SStephan Aßmus return NULL; 1912f953b71SStephan Aßmus color.green = color.blue = color.red; 1922f953b71SStephan Aßmus } else { 193fb07ece0SStephan Aßmus if (!buffer.Read(color.red) 194fb07ece0SStephan Aßmus || !buffer.Read(color.green) 195fb07ece0SStephan Aßmus || !buffer.Read(color.blue)) 196fb07ece0SStephan Aßmus return NULL; 197fb07ece0SStephan Aßmus } 1982f953b71SStephan Aßmus } 199fb07ece0SStephan Aßmus return new (nothrow) Style(color); 200fb07ece0SStephan Aßmus } 201fb07ece0SStephan Aßmus 202fb07ece0SStephan Aßmus // _ReadGradientStyle 203fb07ece0SStephan Aßmus static Style* 204fb07ece0SStephan Aßmus _ReadGradientStyle(LittleEndianBuffer& buffer) 205fb07ece0SStephan Aßmus { 206fb07ece0SStephan Aßmus Style* style = new (nothrow) Style(); 207fb07ece0SStephan Aßmus if (!style) 208fb07ece0SStephan Aßmus return NULL; 209fb07ece0SStephan Aßmus 210fb07ece0SStephan Aßmus ObjectDeleter<Style> styleDeleter(style); 211fb07ece0SStephan Aßmus 212fb07ece0SStephan Aßmus uint8 gradientType; 213fb07ece0SStephan Aßmus uint8 gradientFlags; 214fb07ece0SStephan Aßmus uint8 gradientStopCount; 215fb07ece0SStephan Aßmus if (!buffer.Read(gradientType) 216fb07ece0SStephan Aßmus || !buffer.Read(gradientFlags) 217fb07ece0SStephan Aßmus || !buffer.Read(gradientStopCount)) { 218fb07ece0SStephan Aßmus return NULL; 219fb07ece0SStephan Aßmus } 220fb07ece0SStephan Aßmus 221fb07ece0SStephan Aßmus Gradient gradient(true); 222fb07ece0SStephan Aßmus // empty gradient 223fb07ece0SStephan Aßmus 224fb07ece0SStephan Aßmus gradient.SetType((gradient_type)gradientType); 225fb07ece0SStephan Aßmus // TODO: support more stuff with flags 226fb07ece0SStephan Aßmus // ("inherits transformation" and so on) 227fb07ece0SStephan Aßmus if (gradientFlags & GRADIENT_FLAG_TRANSFORM) { 228fb07ece0SStephan Aßmus if (!_ReadTransformable(buffer, &gradient)) 229fb07ece0SStephan Aßmus return NULL; 230fb07ece0SStephan Aßmus } 231fb07ece0SStephan Aßmus 232fb07ece0SStephan Aßmus bool alpha = !(gradientFlags & GRADIENT_FLAG_NO_ALPHA); 2332f953b71SStephan Aßmus bool gray = gradientFlags & GRADIENT_FLAG_GRAYS; 234fb07ece0SStephan Aßmus 235fb07ece0SStephan Aßmus for (int32 i = 0; i < gradientStopCount; i++) { 236fb07ece0SStephan Aßmus uint8 stopOffset; 237fb07ece0SStephan Aßmus rgb_color color; 238fb07ece0SStephan Aßmus 239fb07ece0SStephan Aßmus if (!buffer.Read(stopOffset)) 240fb07ece0SStephan Aßmus return NULL; 241fb07ece0SStephan Aßmus 242fb07ece0SStephan Aßmus if (alpha) { 2432f953b71SStephan Aßmus if (gray) { 2442f953b71SStephan Aßmus if (!buffer.Read(color.red) 2452f953b71SStephan Aßmus || !buffer.Read(color.alpha)) 2462f953b71SStephan Aßmus return NULL; 2472f953b71SStephan Aßmus color.green = color.blue = color.red; 2482f953b71SStephan Aßmus } else { 249fb07ece0SStephan Aßmus if (!buffer.Read((uint32&)color)) 250fb07ece0SStephan Aßmus return NULL; 2512f953b71SStephan Aßmus } 252fb07ece0SStephan Aßmus } else { 253fb07ece0SStephan Aßmus color.alpha = 255; 2542f953b71SStephan Aßmus if (gray) { 2552f953b71SStephan Aßmus if (!buffer.Read(color.red)) 2562f953b71SStephan Aßmus return NULL; 2572f953b71SStephan Aßmus color.green = color.blue = color.red; 2582f953b71SStephan Aßmus } else { 259fb07ece0SStephan Aßmus if (!buffer.Read(color.red) 260fb07ece0SStephan Aßmus || !buffer.Read(color.green) 261fb07ece0SStephan Aßmus || !buffer.Read(color.blue)) { 262fb07ece0SStephan Aßmus return NULL; 263fb07ece0SStephan Aßmus } 264fb07ece0SStephan Aßmus } 2652f953b71SStephan Aßmus } 266fb07ece0SStephan Aßmus 267fb07ece0SStephan Aßmus gradient.AddColor(color, stopOffset / 255.0); 268fb07ece0SStephan Aßmus } 269fb07ece0SStephan Aßmus 270fb07ece0SStephan Aßmus style->SetGradient(&gradient); 271fb07ece0SStephan Aßmus 272fb07ece0SStephan Aßmus styleDeleter.Detach(); 273fb07ece0SStephan Aßmus return style; 274fb07ece0SStephan Aßmus } 275fb07ece0SStephan Aßmus 276fb07ece0SStephan Aßmus // _ParseStyles 277fb07ece0SStephan Aßmus status_t 278fb07ece0SStephan Aßmus FlatIconImporter::_ParseStyles(LittleEndianBuffer& buffer, 279fb07ece0SStephan Aßmus StyleContainer* styles) 280fb07ece0SStephan Aßmus { 281fb07ece0SStephan Aßmus uint8 styleCount; 282fb07ece0SStephan Aßmus if (!buffer.Read(styleCount)) 283fb07ece0SStephan Aßmus return B_ERROR; 284fb07ece0SStephan Aßmus 285fb07ece0SStephan Aßmus for (int32 i = 0; i < styleCount; i++) { 286fb07ece0SStephan Aßmus uint8 styleType; 287fb07ece0SStephan Aßmus if (!buffer.Read(styleType)) 288fb07ece0SStephan Aßmus return B_ERROR; 289fb07ece0SStephan Aßmus Style* style = NULL; 29070f4b8c0SStephan Aßmus if (styleType == STYLE_TYPE_SOLID_COLOR) { 291fb07ece0SStephan Aßmus // solid color 2922f953b71SStephan Aßmus style = _ReadColorStyle(buffer, true, false); 293fb07ece0SStephan Aßmus if (!style) 294fb07ece0SStephan Aßmus return B_NO_MEMORY; 29570f4b8c0SStephan Aßmus } else if (styleType == STYLE_TYPE_SOLID_COLOR_NO_ALPHA) { 296fb07ece0SStephan Aßmus // solid color without alpha 2972f953b71SStephan Aßmus style = _ReadColorStyle(buffer, false, false); 2982f953b71SStephan Aßmus if (!style) 2992f953b71SStephan Aßmus return B_NO_MEMORY; 3002f953b71SStephan Aßmus } else if (styleType == STYLE_TYPE_SOLID_GRAY) { 3012f953b71SStephan Aßmus // solid gray plus alpha 3022f953b71SStephan Aßmus style = _ReadColorStyle(buffer, true, true); 3032f953b71SStephan Aßmus if (!style) 3042f953b71SStephan Aßmus return B_NO_MEMORY; 3052f953b71SStephan Aßmus } else if (styleType == STYLE_TYPE_SOLID_GRAY_NO_ALPHA) { 3062f953b71SStephan Aßmus // solid gray without alpha 3072f953b71SStephan Aßmus style = _ReadColorStyle(buffer, false, true); 308fb07ece0SStephan Aßmus if (!style) 309fb07ece0SStephan Aßmus return B_NO_MEMORY; 31070f4b8c0SStephan Aßmus } else if (styleType == STYLE_TYPE_GRADIENT) { 311fb07ece0SStephan Aßmus // gradient 312fb07ece0SStephan Aßmus style = _ReadGradientStyle(buffer); 313fb07ece0SStephan Aßmus if (!style) 314fb07ece0SStephan Aßmus return B_NO_MEMORY; 315fb07ece0SStephan Aßmus } else { 316fb07ece0SStephan Aßmus // unkown style type, skip tag 317fb07ece0SStephan Aßmus uint16 tagLength; 318fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 319fb07ece0SStephan Aßmus return B_ERROR; 320fb07ece0SStephan Aßmus buffer.Skip(tagLength); 321fb07ece0SStephan Aßmus continue; 322fb07ece0SStephan Aßmus } 323fb07ece0SStephan Aßmus // add style if we were able to read one 324fb07ece0SStephan Aßmus if (style && !styles->AddStyle(style)) { 325fb07ece0SStephan Aßmus delete style; 326fb07ece0SStephan Aßmus return B_NO_MEMORY; 327fb07ece0SStephan Aßmus } 328fb07ece0SStephan Aßmus } 329fb07ece0SStephan Aßmus 330fb07ece0SStephan Aßmus return B_OK; 331fb07ece0SStephan Aßmus } 332fb07ece0SStephan Aßmus 333fb07ece0SStephan Aßmus // read_path_no_curves 334fb07ece0SStephan Aßmus static bool 335fb07ece0SStephan Aßmus read_path_no_curves(LittleEndianBuffer& buffer, VectorPath* path, 336fb07ece0SStephan Aßmus uint8 pointCount) 337fb07ece0SStephan Aßmus { 338fb07ece0SStephan Aßmus for (uint32 p = 0; p < pointCount; p++) { 339fb07ece0SStephan Aßmus BPoint point; 340fb07ece0SStephan Aßmus if (!read_coord(buffer, point.x) 341fb07ece0SStephan Aßmus || !read_coord(buffer, point.y)) 342fb07ece0SStephan Aßmus return false; 343fb07ece0SStephan Aßmus 344fb07ece0SStephan Aßmus if (!path->AddPoint(point)) 345fb07ece0SStephan Aßmus return false; 346fb07ece0SStephan Aßmus } 347fb07ece0SStephan Aßmus return true; 348fb07ece0SStephan Aßmus } 349fb07ece0SStephan Aßmus 350fb07ece0SStephan Aßmus // read_path_curves 351fb07ece0SStephan Aßmus static bool 352fb07ece0SStephan Aßmus read_path_curves(LittleEndianBuffer& buffer, VectorPath* path, 353fb07ece0SStephan Aßmus uint8 pointCount) 354fb07ece0SStephan Aßmus { 355fb07ece0SStephan Aßmus for (uint32 p = 0; p < pointCount; p++) { 356fb07ece0SStephan Aßmus BPoint point; 357fb07ece0SStephan Aßmus if (!read_coord(buffer, point.x) 358fb07ece0SStephan Aßmus || !read_coord(buffer, point.y)) 359fb07ece0SStephan Aßmus return false; 360fb07ece0SStephan Aßmus 361fb07ece0SStephan Aßmus BPoint pointIn; 362fb07ece0SStephan Aßmus if (!read_coord(buffer, pointIn.x) 363fb07ece0SStephan Aßmus || !read_coord(buffer, pointIn.y)) 364fb07ece0SStephan Aßmus return false; 365fb07ece0SStephan Aßmus 366fb07ece0SStephan Aßmus BPoint pointOut; 367fb07ece0SStephan Aßmus if (!read_coord(buffer, pointOut.x) 368fb07ece0SStephan Aßmus || !read_coord(buffer, pointOut.y)) 369fb07ece0SStephan Aßmus return false; 370fb07ece0SStephan Aßmus 371fb07ece0SStephan Aßmus if (!path->AddPoint(point, pointIn, pointOut, false)) 372fb07ece0SStephan Aßmus return false; 373fb07ece0SStephan Aßmus } 374fb07ece0SStephan Aßmus return true; 375fb07ece0SStephan Aßmus } 376fb07ece0SStephan Aßmus 377fb07ece0SStephan Aßmus // read_path_with_commands 378fb07ece0SStephan Aßmus static bool 379fb07ece0SStephan Aßmus read_path_with_commands(LittleEndianBuffer& buffer, VectorPath* path, 380fb07ece0SStephan Aßmus uint8 pointCount) 381fb07ece0SStephan Aßmus { 382fb07ece0SStephan Aßmus PathCommandQueue queue; 383fb07ece0SStephan Aßmus return queue.Read(buffer, path, pointCount); 384fb07ece0SStephan Aßmus } 385fb07ece0SStephan Aßmus 386fb07ece0SStephan Aßmus 387fb07ece0SStephan Aßmus // _ParsePaths 388fb07ece0SStephan Aßmus status_t 389fb07ece0SStephan Aßmus FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer, 390fb07ece0SStephan Aßmus PathContainer* paths) 391fb07ece0SStephan Aßmus { 392fb07ece0SStephan Aßmus uint8 pathCount; 393fb07ece0SStephan Aßmus if (!buffer.Read(pathCount)) 394fb07ece0SStephan Aßmus return B_ERROR; 395fb07ece0SStephan Aßmus 396fb07ece0SStephan Aßmus for (int32 i = 0; i < pathCount; i++) { 397fb07ece0SStephan Aßmus uint8 pathFlags; 398fb07ece0SStephan Aßmus uint8 pointCount; 399fb07ece0SStephan Aßmus if (!buffer.Read(pathFlags) || !buffer.Read(pointCount)) 400fb07ece0SStephan Aßmus return B_ERROR; 401fb07ece0SStephan Aßmus 402fb07ece0SStephan Aßmus VectorPath* path = new (nothrow) VectorPath(); 403fb07ece0SStephan Aßmus if (!path) 404fb07ece0SStephan Aßmus return B_NO_MEMORY; 405fb07ece0SStephan Aßmus 406fb07ece0SStephan Aßmus // chose path reading strategy depending on path flags 407fb07ece0SStephan Aßmus bool error = false; 40870f4b8c0SStephan Aßmus if (pathFlags & PATH_FLAG_NO_CURVES) { 409fb07ece0SStephan Aßmus if (!read_path_no_curves(buffer, path, pointCount)) 410fb07ece0SStephan Aßmus error = true; 41170f4b8c0SStephan Aßmus } else if (pathFlags & PATH_FLAG_USES_COMMANDS) { 412fb07ece0SStephan Aßmus if (!read_path_with_commands(buffer, path, pointCount)) 413fb07ece0SStephan Aßmus error = true; 414fb07ece0SStephan Aßmus } else { 415fb07ece0SStephan Aßmus if (!read_path_curves(buffer, path, pointCount)) 416fb07ece0SStephan Aßmus error = true; 417fb07ece0SStephan Aßmus } 418fb07ece0SStephan Aßmus 419fb07ece0SStephan Aßmus if (error) { 420fb07ece0SStephan Aßmus delete path; 421fb07ece0SStephan Aßmus return B_ERROR; 422fb07ece0SStephan Aßmus } 423fb07ece0SStephan Aßmus // post process path to clean it up 424fb07ece0SStephan Aßmus path->CleanUp(); 42570f4b8c0SStephan Aßmus if (pathFlags & PATH_FLAG_CLOSED) 426fb07ece0SStephan Aßmus path->SetClosed(true); 427fb07ece0SStephan Aßmus // add path to container 428fb07ece0SStephan Aßmus if (!paths->AddPath(path)) { 429fb07ece0SStephan Aßmus delete path; 430fb07ece0SStephan Aßmus return B_NO_MEMORY; 431fb07ece0SStephan Aßmus } 432fb07ece0SStephan Aßmus } 433fb07ece0SStephan Aßmus 434fb07ece0SStephan Aßmus return B_OK; 435fb07ece0SStephan Aßmus } 436fb07ece0SStephan Aßmus 437fb07ece0SStephan Aßmus // _ReadTransformer 438fb07ece0SStephan Aßmus static Transformer* 439fb07ece0SStephan Aßmus _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source) 440fb07ece0SStephan Aßmus { 441fb07ece0SStephan Aßmus uint8 transformerType; 442fb07ece0SStephan Aßmus if (!buffer.Read(transformerType)) 443fb07ece0SStephan Aßmus return NULL; 444fb07ece0SStephan Aßmus 445fb07ece0SStephan Aßmus switch (transformerType) { 44670f4b8c0SStephan Aßmus case TRANSFORMER_TYPE_AFFINE: { 447fb07ece0SStephan Aßmus AffineTransformer* affine 448fb07ece0SStephan Aßmus = new (nothrow) AffineTransformer(source); 449fb07ece0SStephan Aßmus if (!affine) 450fb07ece0SStephan Aßmus return NULL; 451fb07ece0SStephan Aßmus double matrix[6]; 452fb07ece0SStephan Aßmus for (int32 i = 0; i < 6; i++) { 453fb07ece0SStephan Aßmus float value; 454fb07ece0SStephan Aßmus if (!buffer.Read(value)) { 455fb07ece0SStephan Aßmus delete affine; 456fb07ece0SStephan Aßmus return NULL; 457fb07ece0SStephan Aßmus } 458fb07ece0SStephan Aßmus matrix[i] = value; 459fb07ece0SStephan Aßmus } 460fb07ece0SStephan Aßmus affine->load_from(matrix); 461fb07ece0SStephan Aßmus return affine; 462fb07ece0SStephan Aßmus } 46370f4b8c0SStephan Aßmus case TRANSFORMER_TYPE_CONTOUR: { 464fb07ece0SStephan Aßmus ContourTransformer* contour 465fb07ece0SStephan Aßmus = new (nothrow) ContourTransformer(source); 466fb07ece0SStephan Aßmus uint8 width; 467fb07ece0SStephan Aßmus uint8 lineJoin; 468fb07ece0SStephan Aßmus uint8 miterLimit; 469fb07ece0SStephan Aßmus if (!contour 470fb07ece0SStephan Aßmus || !buffer.Read(width) 471fb07ece0SStephan Aßmus || !buffer.Read(lineJoin) 472fb07ece0SStephan Aßmus || !buffer.Read(miterLimit)) { 473fb07ece0SStephan Aßmus delete contour; 474fb07ece0SStephan Aßmus return NULL; 475fb07ece0SStephan Aßmus } 476fb07ece0SStephan Aßmus contour->width(width - 128.0); 477fb07ece0SStephan Aßmus contour->line_join((agg::line_join_e)lineJoin); 478fb07ece0SStephan Aßmus contour->miter_limit(miterLimit); 479fb07ece0SStephan Aßmus return contour; 480fb07ece0SStephan Aßmus } 48170f4b8c0SStephan Aßmus case TRANSFORMER_TYPE_PERSPECTIVE: { 482fb07ece0SStephan Aßmus PerspectiveTransformer* perspective 483fb07ece0SStephan Aßmus = new (nothrow) PerspectiveTransformer(source); 484fb07ece0SStephan Aßmus // TODO: upgrade AGG to be able to support storage of 485fb07ece0SStephan Aßmus // trans_perspective 486fb07ece0SStephan Aßmus return perspective; 487fb07ece0SStephan Aßmus } 48870f4b8c0SStephan Aßmus case TRANSFORMER_TYPE_STROKE: { 489fb07ece0SStephan Aßmus StrokeTransformer* stroke 490fb07ece0SStephan Aßmus = new (nothrow) StrokeTransformer(source); 491fb07ece0SStephan Aßmus uint8 width; 4922f953b71SStephan Aßmus uint8 lineOptions; 493fb07ece0SStephan Aßmus uint8 miterLimit; 494fb07ece0SStephan Aßmus // uint8 shorten; 495fb07ece0SStephan Aßmus if (!stroke 496fb07ece0SStephan Aßmus || !buffer.Read(width) 4972f953b71SStephan Aßmus || !buffer.Read(lineOptions) 498fb07ece0SStephan Aßmus || !buffer.Read(miterLimit)) { 499fb07ece0SStephan Aßmus delete stroke; 500fb07ece0SStephan Aßmus return NULL; 501fb07ece0SStephan Aßmus } 502fb07ece0SStephan Aßmus stroke->width(width - 128.0); 5032f953b71SStephan Aßmus uint8 lineJoin = lineOptions & 15; 504fb07ece0SStephan Aßmus stroke->line_join((agg::line_join_e)lineJoin); 5052f953b71SStephan Aßmus uint8 lineCap = lineOptions >> 4; 506fb07ece0SStephan Aßmus stroke->line_cap((agg::line_cap_e)lineCap); 507fb07ece0SStephan Aßmus stroke->miter_limit(miterLimit); 508fb07ece0SStephan Aßmus return stroke; 509fb07ece0SStephan Aßmus } 510fb07ece0SStephan Aßmus default: { 511fb07ece0SStephan Aßmus // unkown transformer, skip tag 512fb07ece0SStephan Aßmus uint16 tagLength; 513fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 514fb07ece0SStephan Aßmus return NULL; 515fb07ece0SStephan Aßmus buffer.Skip(tagLength); 516fb07ece0SStephan Aßmus return NULL; 517fb07ece0SStephan Aßmus } 518fb07ece0SStephan Aßmus } 519fb07ece0SStephan Aßmus } 520fb07ece0SStephan Aßmus 521fb07ece0SStephan Aßmus // _ReadPathSourceShape 522014c7e94SStephan Aßmus Shape* 523014c7e94SStephan Aßmus FlatIconImporter::_ReadPathSourceShape(LittleEndianBuffer& buffer, 524014c7e94SStephan Aßmus StyleContainer* styles, 525014c7e94SStephan Aßmus PathContainer* paths) 526fb07ece0SStephan Aßmus { 527fb07ece0SStephan Aßmus // find out which style this shape uses 528fb07ece0SStephan Aßmus uint8 styleIndex; 529fb07ece0SStephan Aßmus uint8 pathCount; 530fb07ece0SStephan Aßmus if (!buffer.Read(styleIndex) || !buffer.Read(pathCount)) 531fb07ece0SStephan Aßmus return NULL; 532fb07ece0SStephan Aßmus 533014c7e94SStephan Aßmus #ifdef ICON_O_MATIC 534014c7e94SStephan Aßmus Style* style = styles->StyleAt(StyleIndexFor(styleIndex)); 535014c7e94SStephan Aßmus #else 536fb07ece0SStephan Aßmus Style* style = styles->StyleAt(styleIndex); 537014c7e94SStephan Aßmus #endif 538014c7e94SStephan Aßmus 539fb07ece0SStephan Aßmus if (!style) { 540fb07ece0SStephan Aßmus printf("_ReadPathSourceShape() - " 541fb07ece0SStephan Aßmus "shape references non-existing style %d\n", styleIndex); 542fb07ece0SStephan Aßmus return NULL; 543fb07ece0SStephan Aßmus } 544fb07ece0SStephan Aßmus 545fb07ece0SStephan Aßmus // create the shape 546fb07ece0SStephan Aßmus Shape* shape = new (nothrow) Shape(style); 547fb07ece0SStephan Aßmus ObjectDeleter<Shape> shapeDeleter(shape); 548fb07ece0SStephan Aßmus 549fb07ece0SStephan Aßmus if (!shape || shape->InitCheck() < B_OK) 550fb07ece0SStephan Aßmus return NULL; 551fb07ece0SStephan Aßmus 552fb07ece0SStephan Aßmus // find out which paths this shape uses 553fb07ece0SStephan Aßmus for (uint32 i = 0; i < pathCount; i++) { 554fb07ece0SStephan Aßmus uint8 pathIndex; 555fb07ece0SStephan Aßmus if (!buffer.Read(pathIndex)) 556fb07ece0SStephan Aßmus return NULL; 557fb07ece0SStephan Aßmus 558014c7e94SStephan Aßmus #ifdef ICON_O_MATIC 559014c7e94SStephan Aßmus VectorPath* path = paths->PathAt(PathIndexFor(pathIndex)); 560014c7e94SStephan Aßmus #else 561fb07ece0SStephan Aßmus VectorPath* path = paths->PathAt(pathIndex); 562014c7e94SStephan Aßmus #endif 563fb07ece0SStephan Aßmus if (!path) { 564fb07ece0SStephan Aßmus printf("_ReadPathSourceShape() - " 565fb07ece0SStephan Aßmus "shape references non-existing path %d\n", pathIndex); 566fb07ece0SStephan Aßmus continue; 567fb07ece0SStephan Aßmus } 568fb07ece0SStephan Aßmus shape->Paths()->AddPath(path); 569fb07ece0SStephan Aßmus } 570fb07ece0SStephan Aßmus 571fb07ece0SStephan Aßmus // shape flags 572fb07ece0SStephan Aßmus uint8 shapeFlags; 573fb07ece0SStephan Aßmus if (!buffer.Read(shapeFlags)) 574fb07ece0SStephan Aßmus return NULL; 575fb07ece0SStephan Aßmus 576fb07ece0SStephan Aßmus shape->SetHinting(shapeFlags & SHAPE_FLAG_HINTING); 577fb07ece0SStephan Aßmus 578fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_TRANSFORM) { 579fb07ece0SStephan Aßmus // transformation 580fb07ece0SStephan Aßmus if (!_ReadTransformable(buffer, shape)) 581fb07ece0SStephan Aßmus return NULL; 582fb07ece0SStephan Aßmus } else if (shapeFlags & SHAPE_FLAG_TRANSLATION) { 583fb07ece0SStephan Aßmus // translation 584fb07ece0SStephan Aßmus if (!_ReadTranslation(buffer, shape)) 585fb07ece0SStephan Aßmus return NULL; 586fb07ece0SStephan Aßmus } 587fb07ece0SStephan Aßmus 588fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_LOD_SCALE) { 589fb07ece0SStephan Aßmus // min max visibility scale 590fb07ece0SStephan Aßmus uint8 minScale; 591fb07ece0SStephan Aßmus uint8 maxScale; 592fb07ece0SStephan Aßmus if (!buffer.Read(minScale) || !buffer.Read(maxScale)) 593fb07ece0SStephan Aßmus return NULL; 5942f953b71SStephan Aßmus shape->SetMinVisibilityScale(minScale / 63.75); 5952f953b71SStephan Aßmus shape->SetMaxVisibilityScale(maxScale / 63.75); 596fb07ece0SStephan Aßmus } 597fb07ece0SStephan Aßmus 598fb07ece0SStephan Aßmus // transformers 599fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_HAS_TRANSFORMERS) { 600fb07ece0SStephan Aßmus uint8 transformerCount; 601fb07ece0SStephan Aßmus if (!buffer.Read(transformerCount)) 602fb07ece0SStephan Aßmus return NULL; 603fb07ece0SStephan Aßmus for (uint32 i = 0; i < transformerCount; i++) { 604fb07ece0SStephan Aßmus Transformer* transformer 605fb07ece0SStephan Aßmus = _ReadTransformer(buffer, shape->VertexSource()); 606fb07ece0SStephan Aßmus if (transformer && !shape->AddTransformer(transformer)) { 607fb07ece0SStephan Aßmus delete transformer; 608fb07ece0SStephan Aßmus return NULL; 609fb07ece0SStephan Aßmus } 610fb07ece0SStephan Aßmus } 611fb07ece0SStephan Aßmus } 612fb07ece0SStephan Aßmus 613fb07ece0SStephan Aßmus shapeDeleter.Detach(); 614fb07ece0SStephan Aßmus return shape; 615fb07ece0SStephan Aßmus } 616fb07ece0SStephan Aßmus 617fb07ece0SStephan Aßmus // _ParseShapes 618fb07ece0SStephan Aßmus status_t 619fb07ece0SStephan Aßmus FlatIconImporter::_ParseShapes(LittleEndianBuffer& buffer, 620fb07ece0SStephan Aßmus StyleContainer* styles, 621fb07ece0SStephan Aßmus PathContainer* paths, 622fb07ece0SStephan Aßmus ShapeContainer* shapes) 623fb07ece0SStephan Aßmus { 624fb07ece0SStephan Aßmus uint8 shapeCount; 625fb07ece0SStephan Aßmus if (!buffer.Read(shapeCount)) 626fb07ece0SStephan Aßmus return B_ERROR; 627fb07ece0SStephan Aßmus 628fb07ece0SStephan Aßmus for (uint32 i = 0; i < shapeCount; i++) { 629fb07ece0SStephan Aßmus uint8 shapeType; 630fb07ece0SStephan Aßmus if (!buffer.Read(shapeType)) 631fb07ece0SStephan Aßmus return B_ERROR; 632fb07ece0SStephan Aßmus Shape* shape = NULL; 63370f4b8c0SStephan Aßmus if (shapeType == SHAPE_TYPE_PATH_SOURCE) { 634fb07ece0SStephan Aßmus // path source shape 635fb07ece0SStephan Aßmus shape = _ReadPathSourceShape(buffer, styles, paths); 636fb07ece0SStephan Aßmus if (!shape) 637fb07ece0SStephan Aßmus return B_NO_MEMORY; 638fb07ece0SStephan Aßmus } else { 639fb07ece0SStephan Aßmus // unkown shape type, skip tag 640fb07ece0SStephan Aßmus uint16 tagLength; 641fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 642fb07ece0SStephan Aßmus return B_ERROR; 643fb07ece0SStephan Aßmus buffer.Skip(tagLength); 644fb07ece0SStephan Aßmus continue; 645fb07ece0SStephan Aßmus } 646fb07ece0SStephan Aßmus // add shape if we were able to read one 647fb07ece0SStephan Aßmus if (shape && !shapes->AddShape(shape)) { 648fb07ece0SStephan Aßmus delete shape; 649fb07ece0SStephan Aßmus return B_NO_MEMORY; 650fb07ece0SStephan Aßmus } 651fb07ece0SStephan Aßmus } 652fb07ece0SStephan Aßmus 653fb07ece0SStephan Aßmus return B_OK; 654fb07ece0SStephan Aßmus } 655fb07ece0SStephan Aßmus 656fb07ece0SStephan Aßmus 657fb07ece0SStephan Aßmus 658fb07ece0SStephan Aßmus 659