// Copyright-free file from http://openclipart.org/detail/29213/paper-plane-by-ddoo
filename.append("plane.png");
- SkFILEStream stream(filename.c_str());
- if (stream.isValid()) {
- stream.rewind();
- size_t length = stream.getLength();
+ SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(filename.c_str()));
+ if (NULL != stream.get()) {
+ stream->rewind();
+ size_t length = stream->getLength();
void* buffer = sk_malloc_throw(length);
- stream.read(buffer, length);
+ stream->read(buffer, length);
SkAutoDataUnref data(SkData::NewFromMalloc(buffer, length));
SkBitmapFactory factory(&SkImageDecoder::DecodeMemoryToTarget);
// Create a cache which will boot the pixels out anytime the
#include "SkFlattenable.h"
+struct SkFILE;
+
/**
* SkData holds an immutable data buffer. Not only is the data immutable,
* but the actual ptr that is returned (by data() or bytes()) is guaranteed
static SkData* NewFromMalloc(const void* data, size_t length);
/**
- * Create a new dataref from a pointer allocated by mmap. The Data object
- * will handle calling munmap().
+ * Create a new dataref from a SkFILE.
+ * This does not take ownership of the SkFILE, nor close it.
+ * The SkFILE must be open for reading only.
+ * Returns NULL on failure.
*/
- static SkData* NewFromMMap(const void* data, size_t length);
+ static SkData* NewFromFILE(SkFILE* f);
/**
* Create a new dataref using a subset of the data in the specified
#include "SkData.h"
#include "SkFlattenableBuffers.h"
+#include "SkOSFile.h"
#if SK_MMAP_SUPPORT
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
+ #include <unistd.h>
+#else
+ #include <io.h>
#endif
SK_DEFINE_INST_COUNT(SkData)
src->unref();
}
+#if SK_MMAP_SUPPORT
+
+static void sk_munmap_releaseproc(const void* addr, size_t length, void*) {
+ munmap(const_cast<void*>(addr), length);
+}
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+ size_t size = sk_fgetsize(f);
+ if (0 == size) {
+ return NULL;
+ }
+
+ int fd = fileno((FILE*)f);
+ if (fd < 0) {
+ return NULL;
+ }
+
+ void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (MAP_FAILED == addr) {
+ return NULL;
+ }
+
+ return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL);
+}
+
+#elif SK_BUILD_FOR_WIN32
+
+template <typename HandleType, HandleType InvalidValue, BOOL (WINAPI * Close)(HandleType)>
+class SkAutoTHandle : SkNoncopyable {
+public:
+ SkAutoTHandle(HandleType handle) : fHandle(handle) { }
+ ~SkAutoTHandle() { Close(fHandle); }
+ operator HandleType() { return fHandle; }
+ bool isValid() { return InvalidValue != fHandle; }
+private:
+ HandleType fHandle;
+};
+typedef SkAutoTHandle<HANDLE, INVALID_HANDLE_VALUE, CloseHandle> SkAutoWinFile;
+typedef SkAutoTHandle<HANDLE, NULL, CloseHandle> SkAutoWinMMap;
+
+static void sk_munmap_releaseproc(const void* addr, size_t, void*) {
+ UnmapViewOfFile(addr);
+}
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+ size_t size = sk_fgetsize(f);
+ if (0 == size) {
+ return NULL;
+ }
+
+ int fileno = _fileno((FILE*)f);
+ if (fileno < 0) {
+ return NULL;
+ }
+
+ HANDLE file = (HANDLE)_get_osfhandle(fileno);
+ if (INVALID_HANDLE_VALUE == file) {
+ return NULL;
+ }
+
+ SkAutoWinMMap mmap(CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL));
+ if (!mmap.isValid()) {
+ //TODO: use SK_TRACEHR(GetLastError(), "Could not create file mapping.") to report.
+ return NULL;
+ }
+
+ // Eventually call UnmapViewOfFile
+ void* addr = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0);
+ if (NULL == addr) {
+ //TODO: use SK_TRACEHR(GetLastError(), "Could not map view of file.") to report.
+ return NULL;
+ }
+
+ return SkData::NewWithProc(addr, size, sk_munmap_releaseproc, NULL);
+}
+
+#else
+
+SkData* SkData::NewFromFILE(SkFILE* f) {
+ return NULL;
+}
+
+#endif
+
SkData* SkData::NewSubset(const SkData* src, size_t offset, size_t length) {
/*
We could, if we wanted/need to, just make a deep copy of src's data,
return NewWithCopy(cstr, size);
}
-#if SK_MMAP_SUPPORT
-static void sk_munmap_releaseproc(const void* addr, size_t length, void*) {
- munmap(const_cast<void*>(addr), length);
-}
-
-SkData* SkData::NewFromMMap(const void* addr, size_t length) {
- return SkNEW_ARGS(SkData, (addr, length, sk_munmap_releaseproc, NULL));
-}
-#else
-SkData* SkData::NewFromMMap(const void* addr, size_t length) {
- return NULL;
-}
-#endif
-
///////////////////////////////////////////////////////////////////////////////
void SkData::flatten(SkFlattenableWriteBuffer& buffer) const {
#include "SkString.h"
#include "SkOSFile.h"
-#if SK_MMAP_SUPPORT
- #include <unistd.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <unistd.h>
-#endif
-
SK_DEFINE_INST_COUNT(SkStream)
SK_DEFINE_INST_COUNT(SkWStream)
SK_DEFINE_INST_COUNT(SkFILEStream)
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
-static bool mmap_filename(const char path[], void** addrPtr, size_t* sizePtr) {
-#if SK_MMAP_SUPPORT
- int fd = open(path, O_RDONLY);
- if (fd < 0) {
- return false;
- }
- off_t offset = lseek(fd, 0, SEEK_END); // find the file size
- if (offset == -1) {
- close(fd);
- return false;
+static SkData* mmap_filename(const char path[]) {
+ SkFILE* file = sk_fopen(path, kRead_SkFILE_Flag);
+ if (NULL == file) {
+ return NULL;
}
- (void)lseek(fd, 0, SEEK_SET); // restore file offset to beginning
-
- // to avoid a 64bit->32bit warning, I explicitly create a size_t size
- size_t size = static_cast<size_t>(offset);
- void* addr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
- close(fd);
-
- if (MAP_FAILED == addr) {
- return false;
- }
-
- *addrPtr = addr;
- *sizePtr = size;
- return true;
-#else
- return false;
-#endif
+ SkData* data = SkData::NewFromFILE(file);
+ sk_fclose(file);
+ return data;
}
SkStream* SkStream::NewFromFile(const char path[]) {
- void* addr;
- size_t size;
- if (mmap_filename(path, &addr, &size)) {
- SkAutoTUnref<SkData> data(SkData::NewFromMMap(addr, size));
- if (data.get()) {
- return SkNEW_ARGS(SkMemoryStream, (data.get()));
- }
+ SkAutoTUnref<SkData> data(mmap_filename(path));
+ if (data.get()) {
+ return SkNEW_ARGS(SkMemoryStream, (data.get()));
}
// If we get here, then our attempt at using mmap failed, so try normal
*p++ = 'b';
*p = 0;
+ //TODO: on Windows fopen is just ASCII or the current code page,
+ //convert to utf16 and use _wfopen
SkFILE* f = (SkFILE*)::fopen(path, perm);
#if 0
if (NULL == f)
if (NULL == errorText) {
SkDEBUGF(("<unknown>\n"));
} else {
- SkDEBUGF((errorText));
+ SkDEBUGF(("%s", errorText));
LocalFree(errorText);
errorText = NULL;
}