• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/images/SkStream.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkStream.h"
19 #include "SkFixed.h"
20 #include "SkString.h"
21 #include "SkOSFile.h"
22 
~SkStream()23 SkStream::~SkStream() {}
24 
getFileName()25 const char* SkStream::getFileName()
26 {
27     // override in subclass if you represent a file
28     return NULL;
29 }
30 
getMemoryBase()31 const void* SkStream::getMemoryBase()
32 {
33     // override in subclass if you represent a memory block
34     return NULL;
35 }
36 
skip(size_t size)37 size_t SkStream::skip(size_t size)
38 {
39     /*  Check for size == 0, and just return 0. If we passed that
40         to read(), it would interpret it as a request for the entire
41         size of the stream.
42     */
43     return size ? this->read(NULL, size) : 0;
44 }
45 
readS8()46 int8_t SkStream::readS8() {
47     int8_t value;
48     size_t len = this->read(&value, 1);
49     SkASSERT(1 == len);
50     return value;
51 }
52 
readS16()53 int16_t SkStream::readS16() {
54     int16_t value;
55     size_t len = this->read(&value, 2);
56     SkASSERT(2 == len);
57     return value;
58 }
59 
readS32()60 int32_t SkStream::readS32() {
61     int32_t value;
62     size_t len = this->read(&value, 4);
63     SkASSERT(4 == len);
64     return value;
65 }
66 
readScalar()67 SkScalar SkStream::readScalar() {
68     SkScalar value;
69     size_t len = this->read(&value, sizeof(SkScalar));
70     SkASSERT(sizeof(SkScalar) == len);
71     return value;
72 }
73 
readPackedUInt()74 size_t SkStream::readPackedUInt() {
75     uint8_t byte;
76     if (!this->read(&byte, 1)) {
77         return 0;
78     }
79     if (byte != 0xFF) {
80         return byte;
81     }
82 
83     uint16_t word;
84     if (!this->read(&word, 2)) {
85         return 0;
86     }
87     if (word != 0xFFFF) {
88         return word;
89     }
90 
91     uint32_t quad;
92     if (!this->read(&quad, 4)) {
93         return 0;
94     }
95     return quad;
96 }
97 
98 //////////////////////////////////////////////////////////////////////////////////////
99 
~SkWStream()100 SkWStream::~SkWStream()
101 {
102 }
103 
newline()104 void SkWStream::newline()
105 {
106     this->write("\n", 1);
107 }
108 
flush()109 void SkWStream::flush()
110 {
111 }
112 
writeText(const char text[])113 bool SkWStream::writeText(const char text[])
114 {
115     SkASSERT(text);
116     return this->write(text, strlen(text));
117 }
118 
writeDecAsText(int32_t dec)119 bool SkWStream::writeDecAsText(int32_t dec)
120 {
121     SkString    tmp;
122     tmp.appendS32(dec);
123     return this->write(tmp.c_str(), tmp.size());
124 }
125 
writeHexAsText(uint32_t hex,int digits)126 bool SkWStream::writeHexAsText(uint32_t hex, int digits)
127 {
128     SkString    tmp;
129     tmp.appendHex(hex, digits);
130     return this->write(tmp.c_str(), tmp.size());
131 }
132 
writeScalarAsText(SkScalar value)133 bool SkWStream::writeScalarAsText(SkScalar value)
134 {
135     SkString    tmp;
136     tmp.appendScalar(value);
137     return this->write(tmp.c_str(), tmp.size());
138 }
139 
write8(U8CPU value)140 bool SkWStream::write8(U8CPU value) {
141     uint8_t v = SkToU8(value);
142     return this->write(&v, 1);
143 }
144 
write16(U16CPU value)145 bool SkWStream::write16(U16CPU value) {
146     uint16_t v = SkToU16(value);
147     return this->write(&v, 2);
148 }
149 
write32(uint32_t value)150 bool SkWStream::write32(uint32_t value) {
151     return this->write(&value, 4);
152 }
153 
writeScalar(SkScalar value)154 bool SkWStream::writeScalar(SkScalar value) {
155     return this->write(&value, sizeof(value));
156 }
157 
writePackedUInt(size_t value)158 bool SkWStream::writePackedUInt(size_t value) {
159     if (value < 0xFF) {
160         return this->write8(value);
161     } else if (value < 0xFFFF) {
162         return this->write8(0xFF) && this->write16(value);
163     } else {
164         return this->write16(0xFFFF) && this->write32(value);
165     }
166 }
167 
writeStream(SkStream * stream,size_t length)168 bool SkWStream::writeStream(SkStream* stream, size_t length) {
169     char scratch[1024];
170     const size_t MAX = sizeof(scratch);
171 
172     while (length != 0) {
173         size_t n = length;
174         if (n > MAX) {
175             n = MAX;
176         }
177         stream->read(scratch, n);
178         if (!this->write(scratch, n)) {
179             return false;
180         }
181         length -= n;
182     }
183     return true;
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////
187 
SkFILEStream(const char file[])188 SkFILEStream::SkFILEStream(const char file[]) : fName(file)
189 {
190 #ifdef SK_BUILD_FOR_BREW
191     if (SkStrEndsWith(fName.c_str(), ".xml"))
192         fName.writable_str()[fName.size()-3] = 'b';
193 #endif
194 
195     fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL;
196 }
197 
~SkFILEStream()198 SkFILEStream::~SkFILEStream()
199 {
200     if (fFILE)
201         sk_fclose(fFILE);
202 }
203 
setPath(const char path[])204 void SkFILEStream::setPath(const char path[])
205 {
206     fName.set(path);
207 #ifdef SK_BUILD_FOR_BREW
208     if (SkStrEndsWith(fName.c_str(), ".xml"))
209         fName.writable_str()[fName.size()-3] = 'b';
210 #endif
211 
212     if (fFILE)
213     {
214         sk_fclose(fFILE);
215         fFILE = NULL;
216     }
217     if (path)
218         fFILE = sk_fopen(fName.c_str(), kRead_SkFILE_Flag);
219 }
220 
getFileName()221 const char* SkFILEStream::getFileName()
222 {
223     return fName.c_str();
224 }
225 
rewind()226 bool SkFILEStream::rewind()
227 {
228     if (fFILE)
229     {
230         if (sk_frewind(fFILE))
231             return true;
232         // we hit an error
233         sk_fclose(fFILE);
234         fFILE = NULL;
235     }
236     return false;
237 }
238 
read(void * buffer,size_t size)239 size_t SkFILEStream::read(void* buffer, size_t size)
240 {
241     if (fFILE)
242     {
243         if (buffer == NULL && size == 0)    // special signature, they want the total size
244             return sk_fgetsize(fFILE);
245         else
246             return sk_fread(buffer, size, fFILE);
247     }
248     return 0;
249 }
250 
251 ////////////////////////////////////////////////////////////////////////////
252 
SkMemoryStream()253 SkMemoryStream::SkMemoryStream()
254 {
255     fWeOwnTheData = false;
256     this->setMemory(NULL, 0);
257 }
258 
SkMemoryStream(size_t size)259 SkMemoryStream::SkMemoryStream(size_t size) {
260     fWeOwnTheData = true;
261     fOffset = 0;
262     fSize = size;
263     fSrc = sk_malloc_throw(size);
264 }
265 
SkMemoryStream(const void * src,size_t size,bool copyData)266 SkMemoryStream::SkMemoryStream(const void* src, size_t size, bool copyData)
267 {
268     fWeOwnTheData = false;
269     this->setMemory(src, size, copyData);
270 }
271 
~SkMemoryStream()272 SkMemoryStream::~SkMemoryStream()
273 {
274     if (fWeOwnTheData)
275         sk_free((void*)fSrc);
276 }
277 
setMemory(const void * src,size_t size,bool copyData)278 void SkMemoryStream::setMemory(const void* src, size_t size, bool copyData)
279 {
280     if (fWeOwnTheData)
281         sk_free((void*)fSrc);
282 
283     fSize = size;
284     fOffset = 0;
285     fWeOwnTheData = copyData;
286 
287     if (copyData)
288     {
289         void* copy = sk_malloc_throw(size);
290         memcpy(copy, src, size);
291         src = copy;
292     }
293     fSrc = src;
294 }
295 
skipToAlign4()296 void SkMemoryStream::skipToAlign4()
297 {
298     // cast to remove unary-minus warning
299     fOffset += -(int)fOffset & 0x03;
300 }
301 
rewind()302 bool SkMemoryStream::rewind()
303 {
304     fOffset = 0;
305     return true;
306 }
307 
read(void * buffer,size_t size)308 size_t SkMemoryStream::read(void* buffer, size_t size)
309 {
310     if (buffer == NULL && size == 0)    // special signature, they want the total size
311         return fSize;
312 
313     // if buffer is NULL, seek ahead by size
314 
315     if (size == 0)
316         return 0;
317     if (size > fSize - fOffset)
318         size = fSize - fOffset;
319     if (buffer) {
320         memcpy(buffer, (const char*)fSrc + fOffset, size);
321     }
322     fOffset += size;
323     return size;
324 }
325 
getMemoryBase()326 const void* SkMemoryStream::getMemoryBase()
327 {
328     return fSrc;
329 }
330 
getAtPos()331 const void* SkMemoryStream::getAtPos()
332 {
333     return (const char*)fSrc + fOffset;
334 }
335 
seek(size_t offset)336 size_t SkMemoryStream::seek(size_t offset)
337 {
338     if (offset > fSize)
339         offset = fSize;
340     fOffset = offset;
341     return offset;
342 }
343 
344 /////////////////////////////////////////////////////////////////////////////////////////////////////////
345 
SkBufferStream(SkStream * proxy,size_t bufferSize)346 SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize)
347     : fProxy(proxy)
348 {
349     SkASSERT(proxy != NULL);
350     proxy->ref();
351     this->init(NULL, bufferSize);
352 }
353 
SkBufferStream(SkStream * proxy,void * buffer,size_t bufferSize)354 SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize)
355     : fProxy(proxy)
356 {
357     SkASSERT(proxy != NULL);
358     SkASSERT(buffer == NULL || bufferSize != 0);    // init(addr, 0) makes no sense, we must know how big their buffer is
359     proxy->ref();
360     this->init(buffer, bufferSize);
361 }
362 
init(void * buffer,size_t bufferSize)363 void SkBufferStream::init(void* buffer, size_t bufferSize)
364 {
365     if (bufferSize == 0)
366         bufferSize = kDefaultBufferSize;
367 
368     fOrigBufferSize = bufferSize;
369     fBufferSize = bufferSize;
370     fBufferOffset = bufferSize; // to trigger a reload on the first read()
371 
372     if (buffer == NULL)
373     {
374         fBuffer = (char*)sk_malloc_throw(fBufferSize);
375         fWeOwnTheBuffer = true;
376     }
377     else
378     {
379         fBuffer = (char*)buffer;
380         fWeOwnTheBuffer = false;
381     }
382 }
383 
~SkBufferStream()384 SkBufferStream::~SkBufferStream()
385 {
386     fProxy->unref();
387     if (fWeOwnTheBuffer)
388         sk_free(fBuffer);
389 }
390 
rewind()391 bool SkBufferStream::rewind()
392 {
393     fBufferOffset = fBufferSize = fOrigBufferSize;
394     return fProxy->rewind();
395 }
396 
getFileName()397 const char* SkBufferStream::getFileName()
398 {
399     return fProxy->getFileName();
400 }
401 
402 #ifdef SK_DEBUG
403 //  #define SK_TRACE_BUFFERSTREAM
404 #endif
405 
read(void * buffer,size_t size)406 size_t SkBufferStream::read(void* buffer, size_t size) {
407 #ifdef SK_TRACE_BUFFERSTREAM
408     SkDebugf("Request %d", size);
409 #endif
410 
411     if (buffer == NULL && size == 0) {
412         return fProxy->read(buffer, size);    // requesting total size
413     }
414 
415     if (0 == size) {
416         return 0;
417     }
418 
419     // skip size bytes
420     if (NULL == buffer) {
421         size_t remaining = fBufferSize - fBufferOffset;
422         if (remaining >= size) {
423             fBufferOffset += size;
424             return size;
425         }
426         // if we get here, we are being asked to skip beyond our current buffer
427         // so reset our offset to force a read next time, and skip the diff
428         // in our proxy
429         fBufferOffset = fOrigBufferSize;
430         return remaining + fProxy->read(NULL, size - remaining);
431     }
432 
433     size_t s = size;
434     size_t actuallyRead = 0;
435 
436     // flush what we can from our fBuffer
437     if (fBufferOffset < fBufferSize)
438     {
439         if (s > fBufferSize - fBufferOffset)
440             s = fBufferSize - fBufferOffset;
441         memcpy(buffer, fBuffer + fBufferOffset, s);
442 #ifdef SK_TRACE_BUFFERSTREAM
443         SkDebugf(" flush %d", s);
444 #endif
445         size -= s;
446         fBufferOffset += s;
447         buffer = (char*)buffer + s;
448         actuallyRead = s;
449     }
450 
451     // check if there is more to read
452     if (size)
453     {
454         SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer
455 
456         if (size < fBufferSize) // lets try to read more than the request
457         {
458             s = fProxy->read(fBuffer, fBufferSize);
459 #ifdef SK_TRACE_BUFFERSTREAM
460             SkDebugf(" read %d into fBuffer", s);
461 #endif
462             if (size > s)   // they asked for too much
463                 size = s;
464             if (size)
465             {
466                 memcpy(buffer, fBuffer, size);
467                 actuallyRead += size;
468 #ifdef SK_TRACE_BUFFERSTREAM
469                 SkDebugf(" memcpy %d into dst", size);
470 #endif
471             }
472 
473             fBufferOffset = size;
474             fBufferSize = s;        // record the (possibly smaller) size for the buffer
475         }
476         else    // just do a direct read
477         {
478             actuallyRead += fProxy->read(buffer, size);
479 #ifdef SK_TRACE_BUFFERSTREAM
480             SkDebugf(" direct read %d", size);
481 #endif
482         }
483     }
484 #ifdef SK_TRACE_BUFFERSTREAM
485     SkDebugf("\n");
486 #endif
487     return actuallyRead;
488 }
489 
getMemoryBase()490 const void* SkBufferStream::getMemoryBase()
491 {
492     return fProxy->getMemoryBase();
493 }
494 
495 /////////////////////////////////////////////////////////////////////////////////////////////////////////
496 /////////////////////////////////////////////////////////////////////////////////////////////////////////
497 
SkFILEWStream(const char path[])498 SkFILEWStream::SkFILEWStream(const char path[])
499 {
500     fFILE = sk_fopen(path, kWrite_SkFILE_Flag);
501 }
502 
~SkFILEWStream()503 SkFILEWStream::~SkFILEWStream()
504 {
505     if (fFILE)
506         sk_fclose(fFILE);
507 }
508 
write(const void * buffer,size_t size)509 bool SkFILEWStream::write(const void* buffer, size_t size)
510 {
511     if (fFILE == NULL)
512         return false;
513 
514     if (sk_fwrite(buffer, size, fFILE) != size)
515     {
516         SkDEBUGCODE(SkDebugf("SkFILEWStream failed writing %d bytes\n", size);)
517         sk_fclose(fFILE);
518         fFILE = NULL;
519         return false;
520     }
521     return true;
522 }
523 
flush()524 void SkFILEWStream::flush()
525 {
526     if (fFILE)
527         sk_fflush(fFILE);
528 }
529 
530 ////////////////////////////////////////////////////////////////////////
531 
SkMemoryWStream(void * buffer,size_t size)532 SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
533     : fBuffer((char*)buffer), fMaxLength(size), fBytesWritten(0)
534 {
535 }
536 
write(const void * buffer,size_t size)537 bool SkMemoryWStream::write(const void* buffer, size_t size)
538 {
539     size = SkMin32(size, fMaxLength - fBytesWritten);
540     if (size > 0)
541     {
542         memcpy(fBuffer + fBytesWritten, buffer, size);
543         fBytesWritten += size;
544         return true;
545     }
546     return false;
547 }
548 
549 ////////////////////////////////////////////////////////////////////////
550 
551 #define SkDynamicMemoryWStream_MinBlockSize   256
552 
553 struct SkDynamicMemoryWStream::Block {
554     Block*  fNext;
555     char*   fCurr;
556     char*   fStop;
557 
startSkDynamicMemoryWStream::Block558     const char* start() const { return (const char*)(this + 1); }
startSkDynamicMemoryWStream::Block559     char*   start() { return (char*)(this + 1); }
availSkDynamicMemoryWStream::Block560     size_t  avail() const { return fStop - fCurr; }
writtenSkDynamicMemoryWStream::Block561     size_t  written() const { return fCurr - this->start(); }
562 
initSkDynamicMemoryWStream::Block563     void init(size_t size)
564     {
565         fNext = NULL;
566         fCurr = this->start();
567         fStop = this->start() + size;
568     }
569 
appendSkDynamicMemoryWStream::Block570     const void* append(const void* data, size_t size)
571     {
572         SkASSERT((size_t)(fStop - fCurr) >= size);
573         memcpy(fCurr, data, size);
574         fCurr += size;
575         return (const void*)((const char*)data + size);
576     }
577 };
578 
SkDynamicMemoryWStream()579 SkDynamicMemoryWStream::SkDynamicMemoryWStream() : fHead(NULL), fTail(NULL), fBytesWritten(0), fCopyToCache(NULL)
580 {
581 }
582 
~SkDynamicMemoryWStream()583 SkDynamicMemoryWStream::~SkDynamicMemoryWStream()
584 {
585     reset();
586 }
587 
detach()588 const char* SkDynamicMemoryWStream::detach()
589 {
590     const char* result = getStream();
591     fCopyToCache = NULL;
592     return result;
593 }
594 
reset()595 void SkDynamicMemoryWStream::reset()
596 {
597     sk_free(fCopyToCache);
598     Block*  block = fHead;
599 
600     while (block != NULL) {
601         Block*  next = block->fNext;
602         sk_free(block);
603         block = next;
604     }
605     fHead = fTail = NULL;
606     fBytesWritten = 0;
607     fCopyToCache = NULL;
608 }
609 
write(const void * buffer,size_t count)610 bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
611 {
612     if (count > 0) {
613 
614         if (fCopyToCache) {
615             sk_free(fCopyToCache);
616             fCopyToCache = NULL;
617         }
618         fBytesWritten += count;
619 
620         size_t  size;
621 
622         if (fTail != NULL && fTail->avail() > 0) {
623             size = SkMin32(fTail->avail(), count);
624             buffer = fTail->append(buffer, size);
625             SkASSERT(count >= size);
626             count -= size;
627             if (count == 0)
628                 return true;
629         }
630 
631         size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
632         Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
633         block->init(size);
634         block->append(buffer, count);
635 
636         if (fTail != NULL)
637             fTail->fNext = block;
638         else
639             fHead = fTail = block;
640         fTail = block;
641     }
642     return true;
643 }
644 
write(const void * buffer,size_t offset,size_t count)645 bool SkDynamicMemoryWStream::write(const void* buffer, size_t offset, size_t count)
646 {
647     if (offset + count > fBytesWritten)
648         return false; // test does not partially modify
649     Block* block = fHead;
650     while (block != NULL) {
651         size_t size = block->written();
652         if (offset < size) {
653             size_t part = offset + count > size ? size - offset : count;
654             memcpy(block->start() + offset, buffer, part);
655             if (count <= part)
656                 return true;
657             count -= part;
658             buffer = (const void*) ((char* ) buffer + part);
659         }
660         offset = offset > size ? offset - size : 0;
661         block = block->fNext;
662     }
663     return false;
664 }
665 
read(void * buffer,size_t offset,size_t count)666 bool SkDynamicMemoryWStream::read(void* buffer, size_t offset, size_t count)
667 {
668     if (offset + count > fBytesWritten)
669         return false; // test does not partially modify
670     Block* block = fHead;
671     while (block != NULL) {
672         size_t size = block->written();
673         if (offset < size) {
674             size_t part = offset + count > size ? size - offset : count;
675             memcpy(buffer, block->start() + offset, part);
676             if (count <= part)
677                 return true;
678             count -= part;
679             buffer = (void*) ((char* ) buffer + part);
680         }
681         offset = offset > size ? offset - size : 0;
682         block = block->fNext;
683     }
684     return false;
685 }
686 
copyTo(void * dst) const687 void SkDynamicMemoryWStream::copyTo(void* dst) const
688 {
689     Block* block = fHead;
690 
691     while (block != NULL) {
692         size_t size = block->written();
693         memcpy(dst, block->start(), size);
694         dst = (void*)((char*)dst + size);
695         block = block->fNext;
696     }
697 }
698 
getStream() const699 const char* SkDynamicMemoryWStream::getStream() const
700 {
701     if (fCopyToCache == NULL) {
702         fCopyToCache = (char*)sk_malloc_throw(fBytesWritten);
703         this->copyTo(fCopyToCache);
704     }
705     return fCopyToCache;
706 }
707 
padToAlign4()708 void SkDynamicMemoryWStream::padToAlign4()
709 {
710     // cast to remove unary-minus warning
711     int padBytes = -(int)fBytesWritten & 0x03;
712     if (padBytes == 0)
713         return;
714     int zero = 0;
715     write(&zero, padBytes);
716 }
717 
718 /////////////////////////////////////////////////////////////////////////////////////////////////////////
719 
newline()720 void SkDebugWStream::newline()
721 {
722 #ifdef SK_DEBUG
723     SkDebugf("\n");
724 #endif
725 }
726 
write(const void * buffer,size_t size)727 bool SkDebugWStream::write(const void* buffer, size_t size)
728 {
729 #ifdef SK_DEBUG
730     char* s = new char[size+1];
731     memcpy(s, buffer, size);
732     s[size] = 0;
733     SkDebugf("%s", s);
734     delete[] s;
735 #endif
736     return true;
737 }
738 
739