1 /* 2 * Copyright 2006-2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 10 #include "FlatIconFormat.h" 11 12 #include "LittleEndianBuffer.h" 13 14 15 _BEGIN_ICON_NAMESPACE 16 17 18 const uint32 FLAT_ICON_MAGIC = 'ficn'; 19 20 const char* kVectorAttrNodeName = "BEOS:ICON"; 21 const char* kVectorAttrMimeName = "META:ICON"; 22 23 24 // read_coord 25 bool 26 read_coord(LittleEndianBuffer& buffer, float& coord) 27 { 28 uint8 value; 29 if (!buffer.Read(value)) 30 return false; 31 32 if (value & 128) { 33 // high bit set, the next byte is part of the coord 34 uint8 lowValue; 35 if (!buffer.Read(lowValue)) 36 return false; 37 value &= 127; 38 uint16 coordValue = (value << 8) | lowValue; 39 coord = (float)coordValue / 102.0 - 128.0; 40 } else { 41 // simple coord 42 coord = (float)value - 32.0; 43 } 44 return true; 45 } 46 47 // write_coord 48 bool 49 write_coord(LittleEndianBuffer& buffer, float coord) 50 { 51 // clamp coord 52 if (coord < -128.0) 53 coord = -128.0; 54 if (coord > 192.0) 55 coord = 192.0; 56 57 if (int(coord * 100.0) == (int)coord * 100 58 && coord >= - 32.0 && coord <= 95.0) { 59 // saving coord in 7 bit is sufficient 60 uint8 value = (uint8)(coord + 32.0); 61 return buffer.Write(value); 62 } else { 63 // needing to save coord in 15 bits 64 uint16 value = (uint16)((coord + 128.0) * 102.0); 65 // set high bit to indicate there is only one byte 66 value |= 32768; 67 uint8 highValue = value >> 8; 68 uint8 lowValue = value & 255; 69 return buffer.Write(highValue) && buffer.Write(lowValue); 70 } 71 } 72 73 // read_float_24 74 bool 75 read_float_24(LittleEndianBuffer& buffer, float& _value) 76 { 77 uint8 bufferValue[3]; 78 if (!buffer.Read(bufferValue[0]) || !buffer.Read(bufferValue[1]) 79 || !buffer.Read(bufferValue[2])) 80 return false; 81 82 int shortValue = (bufferValue[0] << 16) 83 | (bufferValue[1] << 8) | bufferValue[2]; 84 85 int sign = (shortValue & 0x800000) >> 23; 86 int exponent = ((shortValue & 0x7e0000) >> 17) - 32; 87 int mantissa = (shortValue & 0x01ffff) << 6; 88 89 if (shortValue == 0) 90 _value = 0.0; 91 else { 92 union { 93 uint32 intValue; 94 float floatValue; 95 } i2f; 96 i2f.intValue = (sign << 31) | ((exponent + 127) << 23) | mantissa; 97 _value = i2f.floatValue; 98 } 99 100 return true; 101 } 102 103 // write_float_24 104 bool 105 write_float_24(LittleEndianBuffer& buffer, float _value) 106 { 107 // 1 bit sign 108 // 6 bit exponent 109 // 17 bit mantissa 110 // TODO: fixme for non-IEEE 754 architectures 111 union { 112 float floatValue; 113 uint32 intValue; 114 } f2i; 115 f2i.floatValue = _value; 116 117 int sign = (f2i.intValue & 0x80000000) >> 31; 118 int exponent = ((f2i.intValue & 0x7f800000) >> 23) - 127; 119 int mantissa = f2i.intValue & 0x007fffff; 120 121 if (exponent >= 32 || exponent < -32) { 122 uint8 zero = 0; 123 return buffer.Write(zero) && buffer.Write(zero) 124 && buffer.Write(zero); 125 } 126 127 int shortValue = (sign << 23) 128 | ((exponent + 32) << 17) 129 | (mantissa >> 6); 130 131 return buffer.Write((uint8)(shortValue >> 16)) 132 && buffer.Write((uint8)((shortValue >> 8) & 0xff)) 133 && buffer.Write((uint8)(shortValue & 0xff)); 134 } 135 136 137 _END_ICON_NAMESPACE 138