tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / translation / BitmapStream.cpp
blob9bc9634d17ae2118b4ed1b609650f74ac88734fe
1 /*
2 * Copyright 2002-2011, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Travis Smith
7 * Michael Wilber
8 */
11 #include <BitmapStream.h>
13 #include <new>
15 #include <string.h>
17 #include <Bitmap.h>
18 #include <Debug.h>
21 // Initializes this object to either use the BBitmap passed to
22 // it as the object to read/write to or to create a BBitmap
23 // when data is written to this object.
24 BBitmapStream::BBitmapStream(BBitmap* bitmap)
26 fBitmap = bitmap;
27 fDetached = false;
28 fPosition = 0;
29 fSize = 0;
30 fBigEndianHeader = new (std::nothrow) TranslatorBitmap;
31 if (fBigEndianHeader == NULL) {
32 fBitmap = NULL;
33 return;
36 // Extract header information if bitmap is available
37 if (fBitmap != NULL && fBitmap->InitCheck() == B_OK) {
38 fHeader.magic = B_TRANSLATOR_BITMAP;
39 fHeader.bounds = fBitmap->Bounds();
40 fHeader.rowBytes = fBitmap->BytesPerRow();
41 fHeader.colors = fBitmap->ColorSpace();
42 fHeader.dataSize = static_cast<uint32>
43 ((fHeader.bounds.Height() + 1) * fHeader.rowBytes);
44 fSize = sizeof(TranslatorBitmap) + fHeader.dataSize;
46 if (B_HOST_IS_BENDIAN)
47 memcpy(fBigEndianHeader, &fHeader, sizeof(TranslatorBitmap));
48 else
49 SwapHeader(&fHeader, fBigEndianHeader);
50 } else
51 fBitmap = NULL;
55 BBitmapStream::~BBitmapStream()
57 if (!fDetached)
58 delete fBitmap;
60 delete fBigEndianHeader;
64 // Reads data from the stream at a specific position and size.
65 ssize_t
66 BBitmapStream::ReadAt(off_t pos, void* buffer, size_t size)
68 if (fBitmap == NULL)
69 return B_NO_INIT;
70 if (size == 0)
71 return B_OK;
72 if (pos >= (off_t)fSize || pos < 0 || buffer == NULL)
73 return B_BAD_VALUE;
75 ssize_t toRead;
76 void *source;
78 if (pos < (off_t)sizeof(TranslatorBitmap)) {
79 toRead = sizeof(TranslatorBitmap) - pos;
80 source = (reinterpret_cast<uint8 *>(fBigEndianHeader)) + pos;
81 } else {
82 toRead = fSize - pos;
83 source = (reinterpret_cast<uint8 *>(fBitmap->Bits())) + pos -
84 sizeof(TranslatorBitmap);
86 if (toRead > (ssize_t)size)
87 toRead = (ssize_t)size;
89 memcpy(buffer, source, toRead);
90 return toRead;
94 // Writes data to the bitmap starting at a specific position and size.
95 ssize_t
96 BBitmapStream::WriteAt(off_t pos, const void* data, size_t size)
98 if (size == 0)
99 return B_OK;
100 if (!data || pos < 0 || pos > (off_t)fSize)
101 return B_BAD_VALUE;
103 ssize_t written = 0;
104 while (size > 0) {
105 size_t toWrite;
106 void *dest;
107 // We depend on writing the header separately in detecting
108 // changes to it
109 if (pos < (off_t)sizeof(TranslatorBitmap)) {
110 toWrite = sizeof(TranslatorBitmap) - pos;
111 dest = (reinterpret_cast<uint8 *> (&fHeader)) + pos;
112 } else {
113 if (fBitmap == NULL || !fBitmap->IsValid())
114 return B_ERROR;
116 toWrite = fHeader.dataSize - pos + sizeof(TranslatorBitmap);
117 dest = (reinterpret_cast<uint8 *> (fBitmap->Bits())) +
118 pos - sizeof(TranslatorBitmap);
120 if (toWrite > size)
121 toWrite = size;
122 if (!toWrite && size)
123 // i.e. we've been told to write too much
124 return B_BAD_VALUE;
126 memcpy(dest, data, toWrite);
127 pos += toWrite;
128 written += toWrite;
129 data = (reinterpret_cast<const uint8 *> (data)) + toWrite;
130 size -= toWrite;
131 if (pos > (off_t)fSize)
132 fSize = pos;
133 // If we change the header, the rest needs to be reset
134 if (pos == sizeof(TranslatorBitmap)) {
135 // Setup both host and Big Endian byte order bitmap headers
136 memcpy(fBigEndianHeader, &fHeader, sizeof(TranslatorBitmap));
137 if (B_HOST_IS_LENDIAN)
138 SwapHeader(fBigEndianHeader, &fHeader);
140 if (fBitmap != NULL
141 && (fBitmap->Bounds() != fHeader.bounds
142 || fBitmap->ColorSpace() != fHeader.colors
143 || (uint32)fBitmap->BytesPerRow() != fHeader.rowBytes)) {
144 if (!fDetached)
145 // if someone detached, we don't delete
146 delete fBitmap;
147 fBitmap = NULL;
149 if (fBitmap == NULL) {
150 if (fHeader.bounds.left > 0.0 || fHeader.bounds.top > 0.0)
151 DEBUGGER("non-origin bounds!");
152 fBitmap = new (std::nothrow )BBitmap(fHeader.bounds,
153 fHeader.colors);
154 if (fBitmap == NULL)
155 return B_ERROR;
156 if (!fBitmap->IsValid()) {
157 status_t error = fBitmap->InitCheck();
158 delete fBitmap;
159 fBitmap = NULL;
160 return error;
162 if ((uint32)fBitmap->BytesPerRow() != fHeader.rowBytes) {
163 fprintf(stderr, "BitmapStream %" B_PRId32 " %" B_PRId32 "\n",
164 fBitmap->BytesPerRow(), fHeader.rowBytes);
165 return B_MISMATCHED_VALUES;
168 if (fBitmap != NULL)
169 fSize = sizeof(TranslatorBitmap) + fBitmap->BitsLength();
172 return written;
176 // Changes the current stream position.
177 off_t
178 BBitmapStream::Seek(off_t position, uint32 seekMode)
180 // When whence == SEEK_SET, it just falls through to
181 // fPosition = position
182 if (seekMode == SEEK_CUR)
183 position += fPosition;
184 else if (seekMode == SEEK_END)
185 position += fSize;
187 if (position < 0 || position > (off_t)fSize)
188 return B_BAD_VALUE;
190 fPosition = position;
191 return fPosition;
195 // Returns the current stream position
196 off_t
197 BBitmapStream::Position() const
199 return fPosition;
204 // Returns the current stream size
205 off_t
206 BBitmapStream::Size() const
208 return fSize;
212 // Sets the size of the data.
213 // I'm not sure if this method has any real purpose.
214 status_t
215 BBitmapStream::SetSize(off_t size)
217 if (size < 0)
218 return B_BAD_VALUE;
219 if (fBitmap && (size > (off_t)(fHeader.dataSize + sizeof(TranslatorBitmap))))
220 return B_BAD_VALUE;
221 // Problem:
222 // What if someone calls SetSize() before writing the header,
223 // so we don't know what bitmap to create?
224 // Solution:
225 // We assume people will write the header before any data,
226 // so SetSize() is really not going to do anything.
227 if (fBitmap != NULL)
228 fSize = size;
230 return B_NO_ERROR;
234 // Sets _bitmap to point to the internal bitmap object.
235 status_t
236 BBitmapStream::DetachBitmap(BBitmap** _bitmap)
238 if (_bitmap == NULL)
239 return B_BAD_VALUE;
240 if (!fBitmap || fDetached)
241 return B_ERROR;
243 fDetached = true;
244 *_bitmap = fBitmap;
246 return B_OK;
250 // Swaps the byte order of source, no matter the byte order, and
251 // copies the result to destination.
252 void
253 BBitmapStream::SwapHeader(const TranslatorBitmap* source,
254 TranslatorBitmap* destination)
256 if (source == NULL || destination == NULL)
257 return;
259 memcpy(destination, source, sizeof(TranslatorBitmap));
260 swap_data(B_UINT32_TYPE, destination, sizeof(TranslatorBitmap),
261 B_SWAP_ALWAYS);
265 void BBitmapStream::_ReservedBitmapStream1() {}
266 void BBitmapStream::_ReservedBitmapStream2() {}