xref: /haiku/src/libs/icon/flat_icon/FlatIconFormat.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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