1*fb07ece0SStephan Aßmus /* 2*fb07ece0SStephan Aßmus * Copyright 2006, Haiku. All rights reserved. 3*fb07ece0SStephan Aßmus * Distributed under the terms of the MIT License. 4*fb07ece0SStephan Aßmus * 5*fb07ece0SStephan Aßmus * Authors: 6*fb07ece0SStephan Aßmus * Stephan Aßmus <superstippi@gmx.de> 7*fb07ece0SStephan Aßmus */ 8*fb07ece0SStephan Aßmus 9*fb07ece0SStephan Aßmus #include "FlatIconImporter.h" 10*fb07ece0SStephan Aßmus 11*fb07ece0SStephan Aßmus #include <new> 12*fb07ece0SStephan Aßmus #include <stdio.h> 13*fb07ece0SStephan Aßmus 14*fb07ece0SStephan Aßmus #include <Archivable.h> 15*fb07ece0SStephan Aßmus #include <DataIO.h> 16*fb07ece0SStephan Aßmus #include <Message.h> 17*fb07ece0SStephan Aßmus 18*fb07ece0SStephan Aßmus #include "AffineTransformer.h" 19*fb07ece0SStephan Aßmus #include "AutoDeleter.h" 20*fb07ece0SStephan Aßmus #include "ContourTransformer.h" 21*fb07ece0SStephan Aßmus #include "FlatIconFormat.h" 22*fb07ece0SStephan Aßmus #include "Gradient.h" 23*fb07ece0SStephan Aßmus #include "Icon.h" 24*fb07ece0SStephan Aßmus #include "LittleEndianBuffer.h" 25*fb07ece0SStephan Aßmus #include "PathCommandQueue.h" 26*fb07ece0SStephan Aßmus #include "PathContainer.h" 27*fb07ece0SStephan Aßmus #include "PerspectiveTransformer.h" 28*fb07ece0SStephan Aßmus #include "Shape.h" 29*fb07ece0SStephan Aßmus #include "StrokeTransformer.h" 30*fb07ece0SStephan Aßmus #include "Style.h" 31*fb07ece0SStephan Aßmus #include "StyleContainer.h" 32*fb07ece0SStephan Aßmus #include "VectorPath.h" 33*fb07ece0SStephan Aßmus 34*fb07ece0SStephan Aßmus using std::nothrow; 35*fb07ece0SStephan Aßmus 36*fb07ece0SStephan Aßmus // constructor 37*fb07ece0SStephan Aßmus FlatIconImporter::FlatIconImporter() 38*fb07ece0SStephan Aßmus { 39*fb07ece0SStephan Aßmus } 40*fb07ece0SStephan Aßmus 41*fb07ece0SStephan Aßmus // destructor 42*fb07ece0SStephan Aßmus FlatIconImporter::~FlatIconImporter() 43*fb07ece0SStephan Aßmus { 44*fb07ece0SStephan Aßmus } 45*fb07ece0SStephan Aßmus 46*fb07ece0SStephan Aßmus // Import 47*fb07ece0SStephan Aßmus status_t 48*fb07ece0SStephan Aßmus FlatIconImporter::Import(Icon* icon, BPositionIO* stream) 49*fb07ece0SStephan Aßmus { 50*fb07ece0SStephan Aßmus // seek around in the stream to figure out the size 51*fb07ece0SStephan Aßmus off_t size = stream->Seek(0, SEEK_END); 52*fb07ece0SStephan Aßmus if (stream->Seek(0, SEEK_SET) != 0) 53*fb07ece0SStephan Aßmus return B_ERROR; 54*fb07ece0SStephan Aßmus 55*fb07ece0SStephan Aßmus // we chicken out on anything larger than 256k 56*fb07ece0SStephan Aßmus if (size <= 0 || size > 256 * 1024) 57*fb07ece0SStephan Aßmus return B_BAD_VALUE; 58*fb07ece0SStephan Aßmus 59*fb07ece0SStephan Aßmus // read the entire stream into a buffer 60*fb07ece0SStephan Aßmus LittleEndianBuffer buffer(size); 61*fb07ece0SStephan Aßmus if (!buffer.Buffer()) 62*fb07ece0SStephan Aßmus return B_NO_MEMORY; 63*fb07ece0SStephan Aßmus 64*fb07ece0SStephan Aßmus if (stream->Read(buffer.Buffer(), size) != size) 65*fb07ece0SStephan Aßmus return B_ERROR; 66*fb07ece0SStephan Aßmus 67*fb07ece0SStephan Aßmus status_t ret = _ParseSections(buffer, icon); 68*fb07ece0SStephan Aßmus 69*fb07ece0SStephan Aßmus return ret; 70*fb07ece0SStephan Aßmus } 71*fb07ece0SStephan Aßmus 72*fb07ece0SStephan Aßmus // Import 73*fb07ece0SStephan Aßmus status_t 74*fb07ece0SStephan Aßmus FlatIconImporter::Import(Icon* icon, uint8* _buffer, size_t size) 75*fb07ece0SStephan Aßmus { 76*fb07ece0SStephan Aßmus if (!_buffer) 77*fb07ece0SStephan Aßmus return B_BAD_VALUE; 78*fb07ece0SStephan Aßmus 79*fb07ece0SStephan Aßmus // attach LittleEndianBuffer to buffer 80*fb07ece0SStephan Aßmus LittleEndianBuffer buffer(_buffer, size); 81*fb07ece0SStephan Aßmus 82*fb07ece0SStephan Aßmus return _ParseSections(buffer, icon); 83*fb07ece0SStephan Aßmus } 84*fb07ece0SStephan Aßmus 85*fb07ece0SStephan Aßmus // #pragma mark - 86*fb07ece0SStephan Aßmus 87*fb07ece0SStephan Aßmus // _ParseSections 88*fb07ece0SStephan Aßmus status_t 89*fb07ece0SStephan Aßmus FlatIconImporter::_ParseSections(LittleEndianBuffer& buffer, Icon* icon) 90*fb07ece0SStephan Aßmus { 91*fb07ece0SStephan Aßmus // test if this is an icon at all 92*fb07ece0SStephan Aßmus uint32 magic; 93*fb07ece0SStephan Aßmus if (!buffer.Read(magic) || magic != FLAT_ICON_MAGIC) 94*fb07ece0SStephan Aßmus return B_ERROR; 95*fb07ece0SStephan Aßmus 96*fb07ece0SStephan Aßmus // styles 97*fb07ece0SStephan Aßmus StyleContainer* styles = icon->Styles(); 98*fb07ece0SStephan Aßmus status_t ret = _ParseStyles(buffer, styles); 99*fb07ece0SStephan Aßmus if (ret < B_OK) { 100*fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 101*fb07ece0SStephan Aßmus "error parsing styles: %s\n", strerror(ret)); 102*fb07ece0SStephan Aßmus return ret; 103*fb07ece0SStephan Aßmus } 104*fb07ece0SStephan Aßmus 105*fb07ece0SStephan Aßmus // paths 106*fb07ece0SStephan Aßmus PathContainer* paths = icon->Paths(); 107*fb07ece0SStephan Aßmus ret = _ParsePaths(buffer, paths); 108*fb07ece0SStephan Aßmus if (ret < B_OK) { 109*fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 110*fb07ece0SStephan Aßmus "error parsing paths: %s\n", strerror(ret)); 111*fb07ece0SStephan Aßmus return ret; 112*fb07ece0SStephan Aßmus } 113*fb07ece0SStephan Aßmus 114*fb07ece0SStephan Aßmus // shapes 115*fb07ece0SStephan Aßmus ret = _ParseShapes(buffer, styles, paths, icon->Shapes()); 116*fb07ece0SStephan Aßmus if (ret < B_OK) { 117*fb07ece0SStephan Aßmus printf("FlatIconImporter::_ParseSections() - " 118*fb07ece0SStephan Aßmus "error parsing shapes: %s\n", strerror(ret)); 119*fb07ece0SStephan Aßmus return ret; 120*fb07ece0SStephan Aßmus } 121*fb07ece0SStephan Aßmus 122*fb07ece0SStephan Aßmus return B_OK; 123*fb07ece0SStephan Aßmus } 124*fb07ece0SStephan Aßmus 125*fb07ece0SStephan Aßmus // _ReadTransformable 126*fb07ece0SStephan Aßmus static bool 127*fb07ece0SStephan Aßmus _ReadTransformable(LittleEndianBuffer& buffer, Transformable* transformable) 128*fb07ece0SStephan Aßmus { 129*fb07ece0SStephan Aßmus int32 matrixSize = Transformable::matrix_size; 130*fb07ece0SStephan Aßmus double matrix[matrixSize]; 131*fb07ece0SStephan Aßmus for (int32 i = 0; i < matrixSize; i++) { 132*fb07ece0SStephan Aßmus float value; 133*fb07ece0SStephan Aßmus if (!read_float_24(buffer, value)) 134*fb07ece0SStephan Aßmus return false; 135*fb07ece0SStephan Aßmus matrix[i] = value; 136*fb07ece0SStephan Aßmus } 137*fb07ece0SStephan Aßmus transformable->LoadFrom(matrix); 138*fb07ece0SStephan Aßmus return true; 139*fb07ece0SStephan Aßmus } 140*fb07ece0SStephan Aßmus 141*fb07ece0SStephan Aßmus // _ReadTranslation 142*fb07ece0SStephan Aßmus static bool 143*fb07ece0SStephan Aßmus _ReadTranslation(LittleEndianBuffer& buffer, Transformable* transformable) 144*fb07ece0SStephan Aßmus { 145*fb07ece0SStephan Aßmus BPoint t; 146*fb07ece0SStephan Aßmus if (read_coord(buffer, t.x) && read_coord(buffer, t.y)) { 147*fb07ece0SStephan Aßmus transformable->TranslateBy(t); 148*fb07ece0SStephan Aßmus return true; 149*fb07ece0SStephan Aßmus } 150*fb07ece0SStephan Aßmus 151*fb07ece0SStephan Aßmus return false; 152*fb07ece0SStephan Aßmus } 153*fb07ece0SStephan Aßmus 154*fb07ece0SStephan Aßmus // _ReadColorStyle 155*fb07ece0SStephan Aßmus static Style* 156*fb07ece0SStephan Aßmus _ReadColorStyle(LittleEndianBuffer& buffer, bool alpha) 157*fb07ece0SStephan Aßmus { 158*fb07ece0SStephan Aßmus rgb_color color; 159*fb07ece0SStephan Aßmus if (alpha) { 160*fb07ece0SStephan Aßmus if (!buffer.Read((uint32&)color)) 161*fb07ece0SStephan Aßmus return NULL; 162*fb07ece0SStephan Aßmus } else { 163*fb07ece0SStephan Aßmus color.alpha = 255; 164*fb07ece0SStephan Aßmus if (!buffer.Read(color.red) 165*fb07ece0SStephan Aßmus || !buffer.Read(color.green) 166*fb07ece0SStephan Aßmus || !buffer.Read(color.blue)) 167*fb07ece0SStephan Aßmus return NULL; 168*fb07ece0SStephan Aßmus } 169*fb07ece0SStephan Aßmus return new (nothrow) Style(color); 170*fb07ece0SStephan Aßmus } 171*fb07ece0SStephan Aßmus 172*fb07ece0SStephan Aßmus // _ReadGradientStyle 173*fb07ece0SStephan Aßmus static Style* 174*fb07ece0SStephan Aßmus _ReadGradientStyle(LittleEndianBuffer& buffer) 175*fb07ece0SStephan Aßmus { 176*fb07ece0SStephan Aßmus Style* style = new (nothrow) Style(); 177*fb07ece0SStephan Aßmus if (!style) 178*fb07ece0SStephan Aßmus return NULL; 179*fb07ece0SStephan Aßmus 180*fb07ece0SStephan Aßmus ObjectDeleter<Style> styleDeleter(style); 181*fb07ece0SStephan Aßmus 182*fb07ece0SStephan Aßmus uint8 gradientType; 183*fb07ece0SStephan Aßmus uint8 gradientFlags; 184*fb07ece0SStephan Aßmus uint8 gradientStopCount; 185*fb07ece0SStephan Aßmus if (!buffer.Read(gradientType) 186*fb07ece0SStephan Aßmus || !buffer.Read(gradientFlags) 187*fb07ece0SStephan Aßmus || !buffer.Read(gradientStopCount)) { 188*fb07ece0SStephan Aßmus return NULL; 189*fb07ece0SStephan Aßmus } 190*fb07ece0SStephan Aßmus 191*fb07ece0SStephan Aßmus Gradient gradient(true); 192*fb07ece0SStephan Aßmus // empty gradient 193*fb07ece0SStephan Aßmus 194*fb07ece0SStephan Aßmus gradient.SetType((gradient_type)gradientType); 195*fb07ece0SStephan Aßmus // TODO: support more stuff with flags 196*fb07ece0SStephan Aßmus // ("inherits transformation" and so on) 197*fb07ece0SStephan Aßmus if (gradientFlags & GRADIENT_FLAG_TRANSFORM) { 198*fb07ece0SStephan Aßmus if (!_ReadTransformable(buffer, &gradient)) 199*fb07ece0SStephan Aßmus return NULL; 200*fb07ece0SStephan Aßmus } 201*fb07ece0SStephan Aßmus 202*fb07ece0SStephan Aßmus bool alpha = !(gradientFlags & GRADIENT_FLAG_NO_ALPHA); 203*fb07ece0SStephan Aßmus 204*fb07ece0SStephan Aßmus for (int32 i = 0; i < gradientStopCount; i++) { 205*fb07ece0SStephan Aßmus uint8 stopOffset; 206*fb07ece0SStephan Aßmus rgb_color color; 207*fb07ece0SStephan Aßmus 208*fb07ece0SStephan Aßmus if (!buffer.Read(stopOffset)) 209*fb07ece0SStephan Aßmus return NULL; 210*fb07ece0SStephan Aßmus 211*fb07ece0SStephan Aßmus if (alpha) { 212*fb07ece0SStephan Aßmus if (!buffer.Read((uint32&)color)) 213*fb07ece0SStephan Aßmus return NULL; 214*fb07ece0SStephan Aßmus } else { 215*fb07ece0SStephan Aßmus color.alpha = 255; 216*fb07ece0SStephan Aßmus if (!buffer.Read(color.red) 217*fb07ece0SStephan Aßmus || !buffer.Read(color.green) 218*fb07ece0SStephan Aßmus || !buffer.Read(color.blue)) { 219*fb07ece0SStephan Aßmus return NULL; 220*fb07ece0SStephan Aßmus } 221*fb07ece0SStephan Aßmus } 222*fb07ece0SStephan Aßmus 223*fb07ece0SStephan Aßmus gradient.AddColor(color, stopOffset / 255.0); 224*fb07ece0SStephan Aßmus } 225*fb07ece0SStephan Aßmus 226*fb07ece0SStephan Aßmus style->SetGradient(&gradient); 227*fb07ece0SStephan Aßmus 228*fb07ece0SStephan Aßmus styleDeleter.Detach(); 229*fb07ece0SStephan Aßmus return style; 230*fb07ece0SStephan Aßmus } 231*fb07ece0SStephan Aßmus 232*fb07ece0SStephan Aßmus // _ParseStyles 233*fb07ece0SStephan Aßmus status_t 234*fb07ece0SStephan Aßmus FlatIconImporter::_ParseStyles(LittleEndianBuffer& buffer, 235*fb07ece0SStephan Aßmus StyleContainer* styles) 236*fb07ece0SStephan Aßmus { 237*fb07ece0SStephan Aßmus uint8 styleCount; 238*fb07ece0SStephan Aßmus if (!buffer.Read(styleCount)) 239*fb07ece0SStephan Aßmus return B_ERROR; 240*fb07ece0SStephan Aßmus 241*fb07ece0SStephan Aßmus for (int32 i = 0; i < styleCount; i++) { 242*fb07ece0SStephan Aßmus uint8 styleType; 243*fb07ece0SStephan Aßmus if (!buffer.Read(styleType)) 244*fb07ece0SStephan Aßmus return B_ERROR; 245*fb07ece0SStephan Aßmus Style* style = NULL; 246*fb07ece0SStephan Aßmus if (styleType == TAG_STYLE_SOLID_COLOR) { 247*fb07ece0SStephan Aßmus // solid color 248*fb07ece0SStephan Aßmus style = _ReadColorStyle(buffer, true); 249*fb07ece0SStephan Aßmus if (!style) 250*fb07ece0SStephan Aßmus return B_NO_MEMORY; 251*fb07ece0SStephan Aßmus } else if (styleType == TAG_STYLE_SOLID_COLOR_NO_ALPHA) { 252*fb07ece0SStephan Aßmus // solid color without alpha 253*fb07ece0SStephan Aßmus style = _ReadColorStyle(buffer, false); 254*fb07ece0SStephan Aßmus if (!style) 255*fb07ece0SStephan Aßmus return B_NO_MEMORY; 256*fb07ece0SStephan Aßmus } else if (styleType == TAG_STYLE_GRADIENT) { 257*fb07ece0SStephan Aßmus // gradient 258*fb07ece0SStephan Aßmus style = _ReadGradientStyle(buffer); 259*fb07ece0SStephan Aßmus if (!style) 260*fb07ece0SStephan Aßmus return B_NO_MEMORY; 261*fb07ece0SStephan Aßmus } else { 262*fb07ece0SStephan Aßmus // unkown style type, skip tag 263*fb07ece0SStephan Aßmus uint16 tagLength; 264*fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 265*fb07ece0SStephan Aßmus return B_ERROR; 266*fb07ece0SStephan Aßmus buffer.Skip(tagLength); 267*fb07ece0SStephan Aßmus continue; 268*fb07ece0SStephan Aßmus } 269*fb07ece0SStephan Aßmus // add style if we were able to read one 270*fb07ece0SStephan Aßmus if (style && !styles->AddStyle(style)) { 271*fb07ece0SStephan Aßmus delete style; 272*fb07ece0SStephan Aßmus return B_NO_MEMORY; 273*fb07ece0SStephan Aßmus } 274*fb07ece0SStephan Aßmus } 275*fb07ece0SStephan Aßmus 276*fb07ece0SStephan Aßmus return B_OK; 277*fb07ece0SStephan Aßmus } 278*fb07ece0SStephan Aßmus 279*fb07ece0SStephan Aßmus // read_path_no_curves 280*fb07ece0SStephan Aßmus static bool 281*fb07ece0SStephan Aßmus read_path_no_curves(LittleEndianBuffer& buffer, VectorPath* path, 282*fb07ece0SStephan Aßmus uint8 pointCount) 283*fb07ece0SStephan Aßmus { 284*fb07ece0SStephan Aßmus for (uint32 p = 0; p < pointCount; p++) { 285*fb07ece0SStephan Aßmus BPoint point; 286*fb07ece0SStephan Aßmus if (!read_coord(buffer, point.x) 287*fb07ece0SStephan Aßmus || !read_coord(buffer, point.y)) 288*fb07ece0SStephan Aßmus return false; 289*fb07ece0SStephan Aßmus 290*fb07ece0SStephan Aßmus if (!path->AddPoint(point)) 291*fb07ece0SStephan Aßmus return false; 292*fb07ece0SStephan Aßmus } 293*fb07ece0SStephan Aßmus return true; 294*fb07ece0SStephan Aßmus } 295*fb07ece0SStephan Aßmus 296*fb07ece0SStephan Aßmus // read_path_curves 297*fb07ece0SStephan Aßmus static bool 298*fb07ece0SStephan Aßmus read_path_curves(LittleEndianBuffer& buffer, VectorPath* path, 299*fb07ece0SStephan Aßmus uint8 pointCount) 300*fb07ece0SStephan Aßmus { 301*fb07ece0SStephan Aßmus for (uint32 p = 0; p < pointCount; p++) { 302*fb07ece0SStephan Aßmus BPoint point; 303*fb07ece0SStephan Aßmus if (!read_coord(buffer, point.x) 304*fb07ece0SStephan Aßmus || !read_coord(buffer, point.y)) 305*fb07ece0SStephan Aßmus return false; 306*fb07ece0SStephan Aßmus 307*fb07ece0SStephan Aßmus BPoint pointIn; 308*fb07ece0SStephan Aßmus if (!read_coord(buffer, pointIn.x) 309*fb07ece0SStephan Aßmus || !read_coord(buffer, pointIn.y)) 310*fb07ece0SStephan Aßmus return false; 311*fb07ece0SStephan Aßmus 312*fb07ece0SStephan Aßmus BPoint pointOut; 313*fb07ece0SStephan Aßmus if (!read_coord(buffer, pointOut.x) 314*fb07ece0SStephan Aßmus || !read_coord(buffer, pointOut.y)) 315*fb07ece0SStephan Aßmus return false; 316*fb07ece0SStephan Aßmus 317*fb07ece0SStephan Aßmus if (!path->AddPoint(point, pointIn, pointOut, false)) 318*fb07ece0SStephan Aßmus return false; 319*fb07ece0SStephan Aßmus } 320*fb07ece0SStephan Aßmus return true; 321*fb07ece0SStephan Aßmus } 322*fb07ece0SStephan Aßmus 323*fb07ece0SStephan Aßmus // read_path_with_commands 324*fb07ece0SStephan Aßmus static bool 325*fb07ece0SStephan Aßmus read_path_with_commands(LittleEndianBuffer& buffer, VectorPath* path, 326*fb07ece0SStephan Aßmus uint8 pointCount) 327*fb07ece0SStephan Aßmus { 328*fb07ece0SStephan Aßmus PathCommandQueue queue; 329*fb07ece0SStephan Aßmus return queue.Read(buffer, path, pointCount); 330*fb07ece0SStephan Aßmus } 331*fb07ece0SStephan Aßmus 332*fb07ece0SStephan Aßmus 333*fb07ece0SStephan Aßmus // _ParsePaths 334*fb07ece0SStephan Aßmus status_t 335*fb07ece0SStephan Aßmus FlatIconImporter::_ParsePaths(LittleEndianBuffer& buffer, 336*fb07ece0SStephan Aßmus PathContainer* paths) 337*fb07ece0SStephan Aßmus { 338*fb07ece0SStephan Aßmus uint8 pathCount; 339*fb07ece0SStephan Aßmus if (!buffer.Read(pathCount)) 340*fb07ece0SStephan Aßmus return B_ERROR; 341*fb07ece0SStephan Aßmus 342*fb07ece0SStephan Aßmus for (int32 i = 0; i < pathCount; i++) { 343*fb07ece0SStephan Aßmus uint8 pathFlags; 344*fb07ece0SStephan Aßmus uint8 pointCount; 345*fb07ece0SStephan Aßmus if (!buffer.Read(pathFlags) || !buffer.Read(pointCount)) 346*fb07ece0SStephan Aßmus return B_ERROR; 347*fb07ece0SStephan Aßmus 348*fb07ece0SStephan Aßmus VectorPath* path = new (nothrow) VectorPath(); 349*fb07ece0SStephan Aßmus if (!path) 350*fb07ece0SStephan Aßmus return B_NO_MEMORY; 351*fb07ece0SStephan Aßmus 352*fb07ece0SStephan Aßmus // chose path reading strategy depending on path flags 353*fb07ece0SStephan Aßmus bool error = false; 354*fb07ece0SStephan Aßmus if (pathFlags & PATH_FLAGS_NO_CURVES) { 355*fb07ece0SStephan Aßmus if (!read_path_no_curves(buffer, path, pointCount)) 356*fb07ece0SStephan Aßmus error = true; 357*fb07ece0SStephan Aßmus } else if (pathFlags & PATH_FLAGS_USES_COMMANDS) { 358*fb07ece0SStephan Aßmus if (!read_path_with_commands(buffer, path, pointCount)) 359*fb07ece0SStephan Aßmus error = true; 360*fb07ece0SStephan Aßmus } else { 361*fb07ece0SStephan Aßmus if (!read_path_curves(buffer, path, pointCount)) 362*fb07ece0SStephan Aßmus error = true; 363*fb07ece0SStephan Aßmus } 364*fb07ece0SStephan Aßmus 365*fb07ece0SStephan Aßmus if (error) { 366*fb07ece0SStephan Aßmus delete path; 367*fb07ece0SStephan Aßmus return B_ERROR; 368*fb07ece0SStephan Aßmus } 369*fb07ece0SStephan Aßmus // post process path to clean it up 370*fb07ece0SStephan Aßmus path->CleanUp(); 371*fb07ece0SStephan Aßmus if (pathFlags & PATH_FLAGS_CLOSED) 372*fb07ece0SStephan Aßmus path->SetClosed(true); 373*fb07ece0SStephan Aßmus // add path to container 374*fb07ece0SStephan Aßmus if (!paths->AddPath(path)) { 375*fb07ece0SStephan Aßmus delete path; 376*fb07ece0SStephan Aßmus return B_NO_MEMORY; 377*fb07ece0SStephan Aßmus } 378*fb07ece0SStephan Aßmus } 379*fb07ece0SStephan Aßmus 380*fb07ece0SStephan Aßmus return B_OK; 381*fb07ece0SStephan Aßmus } 382*fb07ece0SStephan Aßmus 383*fb07ece0SStephan Aßmus // _ReadTransformer 384*fb07ece0SStephan Aßmus static Transformer* 385*fb07ece0SStephan Aßmus _ReadTransformer(LittleEndianBuffer& buffer, VertexSource& source) 386*fb07ece0SStephan Aßmus { 387*fb07ece0SStephan Aßmus uint8 transformerType; 388*fb07ece0SStephan Aßmus if (!buffer.Read(transformerType)) 389*fb07ece0SStephan Aßmus return NULL; 390*fb07ece0SStephan Aßmus 391*fb07ece0SStephan Aßmus switch (transformerType) { 392*fb07ece0SStephan Aßmus case TAG_TRANSFORMER_AFFINE: { 393*fb07ece0SStephan Aßmus AffineTransformer* affine 394*fb07ece0SStephan Aßmus = new (nothrow) AffineTransformer(source); 395*fb07ece0SStephan Aßmus if (!affine) 396*fb07ece0SStephan Aßmus return NULL; 397*fb07ece0SStephan Aßmus double matrix[6]; 398*fb07ece0SStephan Aßmus for (int32 i = 0; i < 6; i++) { 399*fb07ece0SStephan Aßmus float value; 400*fb07ece0SStephan Aßmus if (!buffer.Read(value)) { 401*fb07ece0SStephan Aßmus delete affine; 402*fb07ece0SStephan Aßmus return NULL; 403*fb07ece0SStephan Aßmus } 404*fb07ece0SStephan Aßmus matrix[i] = value; 405*fb07ece0SStephan Aßmus } 406*fb07ece0SStephan Aßmus affine->load_from(matrix); 407*fb07ece0SStephan Aßmus return affine; 408*fb07ece0SStephan Aßmus } 409*fb07ece0SStephan Aßmus case TAG_TRANSFORMER_CONTOUR: { 410*fb07ece0SStephan Aßmus ContourTransformer* contour 411*fb07ece0SStephan Aßmus = new (nothrow) ContourTransformer(source); 412*fb07ece0SStephan Aßmus uint8 width; 413*fb07ece0SStephan Aßmus uint8 lineJoin; 414*fb07ece0SStephan Aßmus uint8 miterLimit; 415*fb07ece0SStephan Aßmus if (!contour 416*fb07ece0SStephan Aßmus || !buffer.Read(width) 417*fb07ece0SStephan Aßmus || !buffer.Read(lineJoin) 418*fb07ece0SStephan Aßmus || !buffer.Read(miterLimit)) { 419*fb07ece0SStephan Aßmus delete contour; 420*fb07ece0SStephan Aßmus return NULL; 421*fb07ece0SStephan Aßmus } 422*fb07ece0SStephan Aßmus contour->width(width - 128.0); 423*fb07ece0SStephan Aßmus contour->line_join((agg::line_join_e)lineJoin); 424*fb07ece0SStephan Aßmus contour->miter_limit(miterLimit); 425*fb07ece0SStephan Aßmus return contour; 426*fb07ece0SStephan Aßmus } 427*fb07ece0SStephan Aßmus case TAG_TRANSFORMER_PERSPECTIVE: { 428*fb07ece0SStephan Aßmus PerspectiveTransformer* perspective 429*fb07ece0SStephan Aßmus = new (nothrow) PerspectiveTransformer(source); 430*fb07ece0SStephan Aßmus // TODO: upgrade AGG to be able to support storage of 431*fb07ece0SStephan Aßmus // trans_perspective 432*fb07ece0SStephan Aßmus return perspective; 433*fb07ece0SStephan Aßmus } 434*fb07ece0SStephan Aßmus case TAG_TRANSFORMER_STROKE: { 435*fb07ece0SStephan Aßmus StrokeTransformer* stroke 436*fb07ece0SStephan Aßmus = new (nothrow) StrokeTransformer(source); 437*fb07ece0SStephan Aßmus uint8 width; 438*fb07ece0SStephan Aßmus uint8 lineJoin; 439*fb07ece0SStephan Aßmus uint8 lineCap; 440*fb07ece0SStephan Aßmus uint8 miterLimit; 441*fb07ece0SStephan Aßmus // uint8 shorten; 442*fb07ece0SStephan Aßmus if (!stroke 443*fb07ece0SStephan Aßmus || !buffer.Read(width) 444*fb07ece0SStephan Aßmus || !buffer.Read(lineJoin) 445*fb07ece0SStephan Aßmus || !buffer.Read(lineCap) 446*fb07ece0SStephan Aßmus || !buffer.Read(miterLimit)) { 447*fb07ece0SStephan Aßmus delete stroke; 448*fb07ece0SStephan Aßmus return NULL; 449*fb07ece0SStephan Aßmus } 450*fb07ece0SStephan Aßmus stroke->width(width - 128.0); 451*fb07ece0SStephan Aßmus stroke->line_join((agg::line_join_e)lineJoin); 452*fb07ece0SStephan Aßmus stroke->line_cap((agg::line_cap_e)lineCap); 453*fb07ece0SStephan Aßmus stroke->miter_limit(miterLimit); 454*fb07ece0SStephan Aßmus return stroke; 455*fb07ece0SStephan Aßmus } 456*fb07ece0SStephan Aßmus default: { 457*fb07ece0SStephan Aßmus // unkown transformer, skip tag 458*fb07ece0SStephan Aßmus uint16 tagLength; 459*fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 460*fb07ece0SStephan Aßmus return NULL; 461*fb07ece0SStephan Aßmus buffer.Skip(tagLength); 462*fb07ece0SStephan Aßmus return NULL; 463*fb07ece0SStephan Aßmus } 464*fb07ece0SStephan Aßmus } 465*fb07ece0SStephan Aßmus } 466*fb07ece0SStephan Aßmus 467*fb07ece0SStephan Aßmus // _ReadPathSourceShape 468*fb07ece0SStephan Aßmus static Shape* 469*fb07ece0SStephan Aßmus _ReadPathSourceShape(LittleEndianBuffer& buffer, 470*fb07ece0SStephan Aßmus StyleContainer* styles, PathContainer* paths) 471*fb07ece0SStephan Aßmus { 472*fb07ece0SStephan Aßmus // find out which style this shape uses 473*fb07ece0SStephan Aßmus uint8 styleIndex; 474*fb07ece0SStephan Aßmus uint8 pathCount; 475*fb07ece0SStephan Aßmus if (!buffer.Read(styleIndex) || !buffer.Read(pathCount)) 476*fb07ece0SStephan Aßmus return NULL; 477*fb07ece0SStephan Aßmus 478*fb07ece0SStephan Aßmus Style* style = styles->StyleAt(styleIndex); 479*fb07ece0SStephan Aßmus if (!style) { 480*fb07ece0SStephan Aßmus printf("_ReadPathSourceShape() - " 481*fb07ece0SStephan Aßmus "shape references non-existing style %d\n", styleIndex); 482*fb07ece0SStephan Aßmus return NULL; 483*fb07ece0SStephan Aßmus } 484*fb07ece0SStephan Aßmus 485*fb07ece0SStephan Aßmus // create the shape 486*fb07ece0SStephan Aßmus Shape* shape = new (nothrow) Shape(style); 487*fb07ece0SStephan Aßmus ObjectDeleter<Shape> shapeDeleter(shape); 488*fb07ece0SStephan Aßmus 489*fb07ece0SStephan Aßmus if (!shape || shape->InitCheck() < B_OK) 490*fb07ece0SStephan Aßmus return NULL; 491*fb07ece0SStephan Aßmus 492*fb07ece0SStephan Aßmus // find out which paths this shape uses 493*fb07ece0SStephan Aßmus for (uint32 i = 0; i < pathCount; i++) { 494*fb07ece0SStephan Aßmus uint8 pathIndex; 495*fb07ece0SStephan Aßmus if (!buffer.Read(pathIndex)) 496*fb07ece0SStephan Aßmus return NULL; 497*fb07ece0SStephan Aßmus 498*fb07ece0SStephan Aßmus VectorPath* path = paths->PathAt(pathIndex); 499*fb07ece0SStephan Aßmus if (!path) { 500*fb07ece0SStephan Aßmus printf("_ReadPathSourceShape() - " 501*fb07ece0SStephan Aßmus "shape references non-existing path %d\n", pathIndex); 502*fb07ece0SStephan Aßmus continue; 503*fb07ece0SStephan Aßmus } 504*fb07ece0SStephan Aßmus shape->Paths()->AddPath(path); 505*fb07ece0SStephan Aßmus } 506*fb07ece0SStephan Aßmus 507*fb07ece0SStephan Aßmus // shape flags 508*fb07ece0SStephan Aßmus uint8 shapeFlags; 509*fb07ece0SStephan Aßmus if (!buffer.Read(shapeFlags)) 510*fb07ece0SStephan Aßmus return NULL; 511*fb07ece0SStephan Aßmus 512*fb07ece0SStephan Aßmus shape->SetHinting(shapeFlags & SHAPE_FLAG_HINTING); 513*fb07ece0SStephan Aßmus 514*fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_TRANSFORM) { 515*fb07ece0SStephan Aßmus // transformation 516*fb07ece0SStephan Aßmus if (!_ReadTransformable(buffer, shape)) 517*fb07ece0SStephan Aßmus return NULL; 518*fb07ece0SStephan Aßmus } else if (shapeFlags & SHAPE_FLAG_TRANSLATION) { 519*fb07ece0SStephan Aßmus // translation 520*fb07ece0SStephan Aßmus if (!_ReadTranslation(buffer, shape)) 521*fb07ece0SStephan Aßmus return NULL; 522*fb07ece0SStephan Aßmus } 523*fb07ece0SStephan Aßmus 524*fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_LOD_SCALE) { 525*fb07ece0SStephan Aßmus // min max visibility scale 526*fb07ece0SStephan Aßmus uint8 minScale; 527*fb07ece0SStephan Aßmus uint8 maxScale; 528*fb07ece0SStephan Aßmus if (!buffer.Read(minScale) || !buffer.Read(maxScale)) 529*fb07ece0SStephan Aßmus return NULL; 530*fb07ece0SStephan Aßmus shape->SetMinVisibilityScale((float)minScale); 531*fb07ece0SStephan Aßmus shape->SetMaxVisibilityScale((float)maxScale); 532*fb07ece0SStephan Aßmus } 533*fb07ece0SStephan Aßmus 534*fb07ece0SStephan Aßmus // transformers 535*fb07ece0SStephan Aßmus if (shapeFlags & SHAPE_FLAG_HAS_TRANSFORMERS) { 536*fb07ece0SStephan Aßmus uint8 transformerCount; 537*fb07ece0SStephan Aßmus if (!buffer.Read(transformerCount)) 538*fb07ece0SStephan Aßmus return NULL; 539*fb07ece0SStephan Aßmus for (uint32 i = 0; i < transformerCount; i++) { 540*fb07ece0SStephan Aßmus Transformer* transformer 541*fb07ece0SStephan Aßmus = _ReadTransformer(buffer, shape->VertexSource()); 542*fb07ece0SStephan Aßmus if (transformer && !shape->AddTransformer(transformer)) { 543*fb07ece0SStephan Aßmus delete transformer; 544*fb07ece0SStephan Aßmus return NULL; 545*fb07ece0SStephan Aßmus } 546*fb07ece0SStephan Aßmus } 547*fb07ece0SStephan Aßmus } 548*fb07ece0SStephan Aßmus 549*fb07ece0SStephan Aßmus shapeDeleter.Detach(); 550*fb07ece0SStephan Aßmus return shape; 551*fb07ece0SStephan Aßmus } 552*fb07ece0SStephan Aßmus 553*fb07ece0SStephan Aßmus // _ParseShapes 554*fb07ece0SStephan Aßmus status_t 555*fb07ece0SStephan Aßmus FlatIconImporter::_ParseShapes(LittleEndianBuffer& buffer, 556*fb07ece0SStephan Aßmus StyleContainer* styles, 557*fb07ece0SStephan Aßmus PathContainer* paths, 558*fb07ece0SStephan Aßmus ShapeContainer* shapes) 559*fb07ece0SStephan Aßmus { 560*fb07ece0SStephan Aßmus uint8 shapeCount; 561*fb07ece0SStephan Aßmus if (!buffer.Read(shapeCount)) 562*fb07ece0SStephan Aßmus return B_ERROR; 563*fb07ece0SStephan Aßmus 564*fb07ece0SStephan Aßmus for (uint32 i = 0; i < shapeCount; i++) { 565*fb07ece0SStephan Aßmus uint8 shapeType; 566*fb07ece0SStephan Aßmus if (!buffer.Read(shapeType)) 567*fb07ece0SStephan Aßmus return B_ERROR; 568*fb07ece0SStephan Aßmus Shape* shape = NULL; 569*fb07ece0SStephan Aßmus if (shapeType == TAG_SHAPE_PATH_SOURCE) { 570*fb07ece0SStephan Aßmus // path source shape 571*fb07ece0SStephan Aßmus shape = _ReadPathSourceShape(buffer, styles, paths); 572*fb07ece0SStephan Aßmus if (!shape) 573*fb07ece0SStephan Aßmus return B_NO_MEMORY; 574*fb07ece0SStephan Aßmus } else { 575*fb07ece0SStephan Aßmus // unkown shape type, skip tag 576*fb07ece0SStephan Aßmus uint16 tagLength; 577*fb07ece0SStephan Aßmus if (!buffer.Read(tagLength)) 578*fb07ece0SStephan Aßmus return B_ERROR; 579*fb07ece0SStephan Aßmus buffer.Skip(tagLength); 580*fb07ece0SStephan Aßmus continue; 581*fb07ece0SStephan Aßmus } 582*fb07ece0SStephan Aßmus // add shape if we were able to read one 583*fb07ece0SStephan Aßmus if (shape && !shapes->AddShape(shape)) { 584*fb07ece0SStephan Aßmus delete shape; 585*fb07ece0SStephan Aßmus return B_NO_MEMORY; 586*fb07ece0SStephan Aßmus } 587*fb07ece0SStephan Aßmus } 588*fb07ece0SStephan Aßmus 589*fb07ece0SStephan Aßmus return B_OK; 590*fb07ece0SStephan Aßmus } 591*fb07ece0SStephan Aßmus 592*fb07ece0SStephan Aßmus 593*fb07ece0SStephan Aßmus 594*fb07ece0SStephan Aßmus 595