diff options
author | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-29 13:43:31 +0000 |
---|---|---|
committer | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-05-29 13:43:31 +0000 |
commit | 6cab1a4b6a68aa81237731308ff37a646d48f51c (patch) | |
tree | 9fbab394aea93cd4a8a828e48ed325366d8f79e0 /src | |
parent | 6320e8f393539b7a536b32b5a072a474709da5ff (diff) |
Change SkStream.
https://codereview.chromium.org/15298009/
git-svn-id: http://skia.googlecode.com/svn/trunk@9312 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkData.cpp | 99 | ||||
-rw-r--r-- | src/core/SkFDStream.cpp | 104 | ||||
-rw-r--r-- | src/core/SkStream.cpp | 285 | ||||
-rw-r--r-- | src/ports/SkFontHost_fontconfig.cpp | 30 | ||||
-rw-r--r-- | src/ports/SkOSFile_none.cpp | 18 | ||||
-rw-r--r-- | src/ports/SkOSFile_posix.cpp | 63 | ||||
-rw-r--r-- | src/ports/SkOSFile_stdio.cpp | 79 | ||||
-rw-r--r-- | src/ports/SkOSFile_win.cpp | 99 | ||||
-rw-r--r-- | src/utils/win/SkDWriteFontFileStream.cpp | 135 | ||||
-rw-r--r-- | src/utils/win/SkDWriteFontFileStream.h | 11 |
10 files changed, 430 insertions, 493 deletions
diff --git a/src/core/SkData.cpp b/src/core/SkData.cpp index e47bbce28e..32e029740a 100644 --- a/src/core/SkData.cpp +++ b/src/core/SkData.cpp @@ -9,16 +9,6 @@ #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) SkData::SkData(const void* ptr, size_t size, ReleaseProc proc, void* context) { @@ -92,96 +82,27 @@ SkData* SkData::NewWithProc(const void* data, size_t length, return new SkData(data, length, proc, context); } -// assumes context is a SkData -static void sk_dataref_releaseproc(const void*, size_t, void* context) { - SkData* src = reinterpret_cast<SkData*>(context); - 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 defined(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); +// assumes fPtr was allocated with sk_fmmap +static void sk_mmap_releaseproc(const void* addr, size_t length, void*) { + sk_fmunmap(addr, length); } 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); + size_t size; + void* addr = sk_fmmap(f, &size); 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); + return SkData::NewWithProc(addr, size, sk_mmap_releaseproc, NULL); } -#else - -SkData* SkData::NewFromFILE(SkFILE* f) { - return NULL; +// assumes context is a SkData +static void sk_dataref_releaseproc(const void*, size_t, void* context) { + SkData* src = reinterpret_cast<SkData*>(context); + src->unref(); } -#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, diff --git a/src/core/SkFDStream.cpp b/src/core/SkFDStream.cpp deleted file mode 100644 index ed94229ed1..0000000000 --- a/src/core/SkFDStream.cpp +++ /dev/null @@ -1,104 +0,0 @@ - -/* - * Copyright 2011 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#include "SkStream.h" - -#ifdef SK_BUILD_FOR_WIN - -// -1 means isValid() will return false -SkFDStream::SkFDStream(int, bool) : fFD(-1), fCloseWhenDone(false) {} -SkFDStream::~SkFDStream() {} -bool SkFDStream::rewind() { return false; } -size_t SkFDStream::read(void*, size_t) { return 0; } - -#else - -#include <unistd.h> - -//#define TRACE_FDSTREAM - -SkFDStream::SkFDStream(int fileDesc, bool closeWhenDone) - : fFD(fileDesc), fCloseWhenDone(closeWhenDone) { -} - -SkFDStream::~SkFDStream() { - if (fFD >= 0 && fCloseWhenDone) { - ::close(fFD); - } -} - -bool SkFDStream::rewind() { - if (fFD >= 0) { - off_t value = ::lseek(fFD, 0, SEEK_SET); -#ifdef TRACE_FDSTREAM - if (value) { - SkDebugf("xxxxxxxxxxxxxx rewind failed %d\n", value); - } -#endif - return value == 0; - } - return false; -} - -size_t SkFDStream::read(void* buffer, size_t size) { - if (fFD >= 0) { - if (buffer == NULL && size == 0) { // request total size - off_t curr = ::lseek(fFD, 0, SEEK_CUR); - if (curr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed 0 CURR\n"); -#endif - return 0; // error - } - off_t size = ::lseek(fFD, 0, SEEK_END); - if (size < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed 0 END\n"); -#endif - size = 0; // error - } - if (::lseek(fFD, curr, SEEK_SET) != curr) { - // can't restore, error -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek failed %d SET\n", curr); -#endif - return 0; - } - return (size_t) size; - } else if (NULL == buffer) { // skip - off_t oldCurr = ::lseek(fFD, 0, SEEK_CUR); - if (oldCurr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek1 failed %d CUR\n", oldCurr); -#endif - return 0; // error; - } - off_t newCurr = ::lseek(fFD, size, SEEK_CUR); - if (newCurr < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx lseek2 failed %d CUR\n", newCurr); -#endif - return 0; // error; - } - // return the actual amount we skipped - return (size_t) (newCurr - oldCurr); - } else { // read - ssize_t actual = ::read(fFD, buffer, size); - // our API can't return an error, so we return 0 - if (actual < 0) { -#ifdef TRACE_FDSTREAM - SkDebugf("xxxxxxxxxxxxx read failed %d actual %d\n", size, actual); -#endif - actual = 0; - } - return actual; - } - } - return 0; -} - -#endif diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index 74734e6d98..91de88adac 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -16,9 +16,7 @@ SK_DEFINE_INST_COUNT(SkStream) SK_DEFINE_INST_COUNT(SkWStream) SK_DEFINE_INST_COUNT(SkFILEStream) -SK_DEFINE_INST_COUNT(SkFDStream) SK_DEFINE_INST_COUNT(SkMemoryStream) -SK_DEFINE_INST_COUNT(SkBufferStream) SK_DEFINE_INST_COUNT(SkFILEWStream) SK_DEFINE_INST_COUNT(SkMemoryWStream) SK_DEFINE_INST_COUNT(SkDynamicMemoryWStream) @@ -26,26 +24,6 @@ SK_DEFINE_INST_COUNT(SkDebugWStream) /////////////////////////////////////////////////////////////////////////////// -const char* SkStream::getFileName() -{ - // override in subclass if you represent a file - return NULL; -} - -const void* SkStream::getMemoryBase() -{ - // override in subclass if you represent a memory block - return NULL; -} - -size_t SkStream::skip(size_t size) -{ - /* Check for size == 0, and just return 0. If we passed that - to read(), it would interpret it as a request for the entire - size of the stream. - */ - return size ? this->read(NULL, size) : 0; -} int8_t SkStream::readS8() { int8_t value; @@ -221,12 +199,17 @@ bool SkWStream::writeData(const SkData* data) { /////////////////////////////////////////////////////////////////////////////// -SkFILEStream::SkFILEStream(const char file[]) : fName(file) { +SkFILEStream::SkFILEStream(const char file[]) : fName(file), fOwnership(kCallerPasses_Ownership) { fFILE = file ? sk_fopen(fName.c_str(), kRead_SkFILE_Flag) : NULL; } +SkFILEStream::SkFILEStream(FILE* file, Ownership ownership) + : fFILE((SkFILE*)file) + , fOwnership(ownership) { +} + SkFILEStream::~SkFILEStream() { - if (fFILE) { + if (fFILE && fOwnership != kCallerRetains_Ownership) { sk_fclose(fFILE); } } @@ -242,8 +225,15 @@ void SkFILEStream::setPath(const char path[]) { } } -const char* SkFILEStream::getFileName() { - return fName.c_str(); +size_t SkFILEStream::read(void* buffer, size_t size) { + if (fFILE) { + return sk_fread(buffer, size, fFILE); + } + return 0; +} + +bool SkFILEStream::isAtEnd() const { + return sk_feof(fFILE); } bool SkFILEStream::rewind() { @@ -258,15 +248,56 @@ bool SkFILEStream::rewind() { return false; } -size_t SkFILEStream::read(void* buffer, size_t size) { - if (fFILE) { - if (buffer == NULL && size == 0) { // special signature, they want the total size - return sk_fgetsize(fFILE); - } else { - return sk_fread(buffer, size, fFILE); +SkStreamAsset* SkFILEStream::duplicate() const { + if (NULL == fFILE) { + return new SkMemoryStream(); + } + + if (NULL != fData.get()) { + return new SkMemoryStream(fData); + } + + if (!fName.isEmpty()) { + SkAutoTUnref<SkFILEStream> that(new SkFILEStream(fName.c_str())); + if (sk_fidentical(that->fFILE, this->fFILE)) { + return that.detach(); } } - return 0; + + fData.reset(SkData::NewFromFILE(fFILE)); + if (NULL == fData.get()) { + return NULL; + } + return new SkMemoryStream(fData); +} + +size_t SkFILEStream::getPosition() const { + return sk_ftell(fFILE); +} + +bool SkFILEStream::seek(size_t position) { + return sk_fseek(fFILE, position); +} + +bool SkFILEStream::move(long offset) { + return sk_fmove(fFILE, offset); +} + +SkStreamAsset* SkFILEStream::fork() const { + SkAutoTUnref<SkStreamAsset> that(this->duplicate()); + that->seek(this->getPosition()); + return that.detach(); +} + +size_t SkFILEStream::getLength() const { + return sk_fgetsize(fFILE); +} + +const void* SkFILEStream::getMemoryBase() { + if (NULL == fData.get()) { + return NULL; + } + return fData->data(); } /////////////////////////////////////////////////////////////////////////////// @@ -341,22 +372,9 @@ void SkMemoryStream::skipToAlign4() { fOffset += -(int)fOffset & 0x03; } -bool SkMemoryStream::rewind() { - fOffset = 0; - return true; -} - size_t SkMemoryStream::read(void* buffer, size_t size) { size_t dataSize = fData->size(); - if (buffer == NULL && size == 0) // special signature, they want the total size - return dataSize; - - // if buffer is NULL, seek ahead by size - - if (size == 0) { - return 0; - } if (size > dataSize - fOffset) { size = dataSize - fOffset; } @@ -367,171 +385,50 @@ size_t SkMemoryStream::read(void* buffer, size_t size) { return size; } -const void* SkMemoryStream::getMemoryBase() { - return fData->data(); -} - -const void* SkMemoryStream::getAtPos() { - return fData->bytes() + fOffset; +bool SkMemoryStream::isAtEnd() const { + return fOffset == fData->size(); } -size_t SkMemoryStream::seek(size_t offset) { - if (offset > fData->size()) { - offset = fData->size(); - } - fOffset = offset; - return offset; +bool SkMemoryStream::rewind() { + fOffset = 0; + return true; } -/////////////////////////////////////////////////////////////////////////////// - -SkBufferStream::SkBufferStream(SkStream* proxy, size_t bufferSize) - : fProxy(proxy) -{ - SkASSERT(proxy != NULL); - proxy->ref(); - this->init(NULL, bufferSize); +SkMemoryStream* SkMemoryStream::duplicate() const { + return SkNEW_ARGS(SkMemoryStream, (fData)); } -SkBufferStream::SkBufferStream(SkStream* proxy, void* buffer, size_t bufferSize) - : fProxy(proxy) -{ - SkASSERT(proxy != NULL); - SkASSERT(buffer == NULL || bufferSize != 0); // init(addr, 0) makes no sense, we must know how big their buffer is - proxy->ref(); - this->init(buffer, bufferSize); +size_t SkMemoryStream::getPosition() const { + return fOffset; } -void SkBufferStream::init(void* buffer, size_t bufferSize) -{ - if (bufferSize == 0) - bufferSize = kDefaultBufferSize; - - fOrigBufferSize = bufferSize; - fBufferSize = bufferSize; - fBufferOffset = bufferSize; // to trigger a reload on the first read() - - if (buffer == NULL) - { - fBuffer = (char*)sk_malloc_throw(fBufferSize); - fWeOwnTheBuffer = true; - } - else - { - fBuffer = (char*)buffer; - fWeOwnTheBuffer = false; - } +bool SkMemoryStream::seek(size_t position) { + fOffset = position > fData->size() + ? fData->size() + : position; + return true; } -SkBufferStream::~SkBufferStream() -{ - fProxy->unref(); - if (fWeOwnTheBuffer) - sk_free(fBuffer); +bool SkMemoryStream::move(long offset) { + return this->seek(fOffset + offset); } -bool SkBufferStream::rewind() -{ - fBufferOffset = fBufferSize = fOrigBufferSize; - return fProxy->rewind(); +SkMemoryStream* SkMemoryStream::fork() const { + SkAutoTUnref<SkMemoryStream> that(this->duplicate()); + that->seek(fOffset); + return that.detach(); } -const char* SkBufferStream::getFileName() -{ - return fProxy->getFileName(); +size_t SkMemoryStream::getLength() const { + return fData->size(); } -#ifdef SK_DEBUG -// #define SK_TRACE_BUFFERSTREAM -#endif - -size_t SkBufferStream::read(void* buffer, size_t size) { -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf("Request %d", size); -#endif - - if (buffer == NULL && size == 0) { - return fProxy->read(buffer, size); // requesting total size - } - - if (0 == size) { - return 0; - } - - // skip size bytes - if (NULL == buffer) { - size_t remaining = fBufferSize - fBufferOffset; - if (remaining >= size) { - fBufferOffset += size; - return size; - } - // if we get here, we are being asked to skip beyond our current buffer - // so reset our offset to force a read next time, and skip the diff - // in our proxy - fBufferOffset = fOrigBufferSize; - return remaining + fProxy->read(NULL, size - remaining); - } - - size_t s = size; - size_t actuallyRead = 0; - - // flush what we can from our fBuffer - if (fBufferOffset < fBufferSize) - { - if (s > fBufferSize - fBufferOffset) - s = fBufferSize - fBufferOffset; - memcpy(buffer, fBuffer + fBufferOffset, s); -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf(" flush %d", s); -#endif - size -= s; - fBufferOffset += s; - buffer = (char*)buffer + s; - actuallyRead = s; - } - - // check if there is more to read - if (size) - { - SkASSERT(fBufferOffset >= fBufferSize); // need to refill our fBuffer - - if (size < fBufferSize) // lets try to read more than the request - { - s = fProxy->read(fBuffer, fBufferSize); -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf(" read %d into fBuffer", s); -#endif - if (size > s) // they asked for too much - size = s; - if (size) - { - memcpy(buffer, fBuffer, size); - actuallyRead += size; -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf(" memcpy %d into dst", size); -#endif - } - - fBufferOffset = size; - fBufferSize = s; // record the (possibly smaller) size for the buffer - } - else // just do a direct read - { - actuallyRead += fProxy->read(buffer, size); -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf(" direct read %d", size); -#endif - } - } -#ifdef SK_TRACE_BUFFERSTREAM - SkDebugf("\n"); -#endif - return actuallyRead; +const void* SkMemoryStream::getMemoryBase() { + return fData->data(); } -const void* SkBufferStream::getMemoryBase() -{ - return fProxy->getMemoryBase(); +const void* SkMemoryStream::getAtPos() { + return fData->bytes() + fOffset; } ///////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -800,7 +697,7 @@ static SkData* mmap_filename(const char path[]) { return data; } -SkStream* SkStream::NewFromFile(const char path[]) { +SkStreamAsset* SkStream::NewFromFile(const char path[]) { SkAutoTUnref<SkData> data(mmap_filename(path)); if (data.get()) { return SkNEW_ARGS(SkMemoryStream, (data.get())); diff --git a/src/ports/SkFontHost_fontconfig.cpp b/src/ports/SkFontHost_fontconfig.cpp index f42ab3fc99..a5aef56f1c 100644 --- a/src/ports/SkFontHost_fontconfig.cpp +++ b/src/ports/SkFontHost_fontconfig.cpp @@ -136,16 +136,30 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { SkStream* FontConfigTypeface::onOpenStream(int* ttcIndex) const { SkStream* stream = this->getLocalStream(); if (stream) { - // TODO: fix issue 1176. - // As of now open_stream will return a stream and unwind it, but the - // SkStream is not thread safe, and if two threads use the stream they - // may collide and print preview for example could still fail, - // or there could be some failures in rendering if this stream is used - // there. - stream->rewind(); - stream->ref(); // should have been provided by CreateFromStream() *ttcIndex = 0; + + SkAutoTUnref<SkStream> dupStream(stream->duplicate()); + if (dupStream) { + return dupStream.detach(); + } + + // TODO: update interface use, remove the following code in this block. + size_t length = stream->getLength(); + + const void* memory = stream->getMemoryBase(); + if (NULL != memory) { + return new SkMemoryStream(memory, length, true); + } + + SkAutoTMalloc<uint8_t> allocMemory(length); + stream->rewind(); + if (length == stream->read(allocMemory.get(), length)) { + return new SkMemoryStream(allocMemory.detach(), length); + } + + stream->rewind(); + stream->ref(); } else { SkAutoTUnref<SkFontConfigInterface> fci(RefFCI()); if (NULL == fci.get()) { diff --git a/src/ports/SkOSFile_none.cpp b/src/ports/SkOSFile_none.cpp new file mode 100644 index 0000000000..e22d22ed4d --- /dev/null +++ b/src/ports/SkOSFile_none.cpp @@ -0,0 +1,18 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkOSFile.h" + +bool sk_fidentical(SkFILE* a, SkFILE* b) { + return false; +} + +void sk_fmunmap(const void* addr, size_t length) { } + +void* sk_fmmap(SkFILE* f, size_t* size) { + return NULL; +} diff --git a/src/ports/SkOSFile_posix.cpp b/src/ports/SkOSFile_posix.cpp new file mode 100644 index 0000000000..c9da4db6b8 --- /dev/null +++ b/src/ports/SkOSFile_posix.cpp @@ -0,0 +1,63 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkOSFile.h" + +#include <stdio.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + +typedef struct { + dev_t dev; + ino_t ino; +} SkFILEID; + +static bool sk_ino(SkFILE* a, SkFILEID* id) { + int fd = fileno((FILE*)a); + if (fd < 0) { + return 0; + } + struct stat status; + if (0 != fstat(fd, &status)) { + return 0; + } + id->dev = status.st_dev; + id->ino = status.st_ino; + return true; +} + +bool sk_fidentical(SkFILE* a, SkFILE* b) { + SkFILEID aID, bID; + return sk_ino(a, &aID) && sk_ino(b, &bID) + && aID.ino == bID.ino + && aID.dev == bID.dev; +} + +void sk_fmunmap(const void* addr, size_t length) { + munmap(const_cast<void*>(addr), length); +} + +void* sk_fmmap(SkFILE* f, size_t* size) { + size_t fileSize = sk_fgetsize(f); + if (0 == fileSize) { + return NULL; + } + + int fd = fileno((FILE*)f); + if (fd < 0) { + return NULL; + } + + void* addr = mmap(NULL, fileSize, PROT_READ, MAP_PRIVATE, fd, 0); + if (MAP_FAILED == addr) { + return NULL; + } + + *size = fileSize; + return addr; +} diff --git a/src/ports/SkOSFile_stdio.cpp b/src/ports/SkOSFile_stdio.cpp index 40c8745552..ad26c807c7 100644 --- a/src/ports/SkOSFile_stdio.cpp +++ b/src/ports/SkOSFile_stdio.cpp @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -6,7 +5,6 @@ * found in the LICENSE file. */ - #include "SkOSFile.h" #include <errno.h> @@ -21,74 +19,65 @@ #include <unistd.h> #endif -SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) -{ +SkFILE* sk_fopen(const char path[], SkFILE_Flags flags) { char perm[4]; char* p = perm; - if (flags & kRead_SkFILE_Flag) + if (flags & kRead_SkFILE_Flag) { *p++ = 'r'; - if (flags & kWrite_SkFILE_Flag) + } + if (flags & kWrite_SkFILE_Flag) { *p++ = 'w'; + } *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) - SkDebugf("sk_fopen failed for %s (%s), errno=%s\n", path, perm, strerror(errno)); -#endif - return f; + return (SkFILE*)::fopen(path, perm); } char* sk_fgets(char* str, int size, SkFILE* f) { return ::fgets(str, size, (FILE *)f); } - int sk_feof(SkFILE *f) { // no :: namespace qualifier because it breaks android return feof((FILE *)f); } -size_t sk_fgetsize(SkFILE* f) -{ +size_t sk_fgetsize(SkFILE* f) { SkASSERT(f); - long curr = ::ftell((FILE*)f); // remember where we are + long curr = ::ftell((FILE*)f); // remember where we are if (curr < 0) { return 0; } - ::fseek((FILE*)f, 0, SEEK_END); // go to the end - long size = ::ftell((FILE*)f); // record the size + + ::fseek((FILE*)f, 0, SEEK_END); // go to the end + long size = ::ftell((FILE*)f); // record the size if (size < 0) { size = 0; } - ::fseek((FILE*)f, curr, SEEK_SET); // go back to our prev loc + + ::fseek((FILE*)f, curr, SEEK_SET); // go back to our prev location return size; } -bool sk_frewind(SkFILE* f) -{ +bool sk_frewind(SkFILE* f) { SkASSERT(f); ::rewind((FILE*)f); -// ::fseek((FILE*)f, 0, SEEK_SET); return true; } -size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f) -{ +size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f) { SkASSERT(f); - if (buffer == NULL) - { + if (buffer == NULL) { size_t curr = ::ftell((FILE*)f); if ((long)curr == -1) { SkDEBUGF(("sk_fread: ftell(%p) returned -1 feof:%d ferror:%d\n", f, feof((FILE*)f), ferror((FILE*)f))); return 0; } - // ::fseek((FILE*)f, (long)(curr + byteCount), SEEK_SET); int err = ::fseek((FILE*)f, (long)byteCount, SEEK_CUR); if (err != 0) { SkDEBUGF(("sk_fread: fseek(%d) tell:%d failed with feof:%d ferror:%d returned:%d\n", @@ -101,26 +90,40 @@ size_t sk_fread(void* buffer, size_t byteCount, SkFILE* f) return ::fread(buffer, 1, byteCount, (FILE*)f); } -size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f) -{ +size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f) { SkASSERT(f); return ::fwrite(buffer, 1, byteCount, (FILE*)f); } -void sk_fflush(SkFILE* f) -{ +void sk_fflush(SkFILE* f) { SkASSERT(f); ::fflush((FILE*)f); } -void sk_fclose(SkFILE* f) -{ +bool sk_fseek(SkFILE* f, size_t byteCount) { + int err = ::fseek((FILE*)f, (long)byteCount, SEEK_SET); + return err == 0; +} + +bool sk_fmove(SkFILE* f, long byteCount) { + int err = ::fseek((FILE*)f, byteCount, SEEK_CUR); + return err == 0; +} + +size_t sk_ftell(SkFILE* f) { + long curr = ::ftell((FILE*)f); + if (curr < 0) { + return 0; + } + return curr; +} + +void sk_fclose(SkFILE* f) { SkASSERT(f); ::fclose((FILE*)f); } -bool sk_exists(const char *path) -{ +bool sk_exists(const char *path) { #ifdef _WIN32 return (0 == _access(path, 0)); #else @@ -128,8 +131,7 @@ bool sk_exists(const char *path) #endif } -bool sk_isdir(const char *path) -{ +bool sk_isdir(const char *path) { struct stat status; if (0 != stat(path, &status)) { return false; @@ -137,8 +139,7 @@ bool sk_isdir(const char *path) return SkToBool(status.st_mode & S_IFDIR); } -bool sk_mkdir(const char* path) -{ +bool sk_mkdir(const char* path) { if (sk_isdir(path)) { return true; } diff --git a/src/ports/SkOSFile_win.cpp b/src/ports/SkOSFile_win.cpp new file mode 100644 index 0000000000..fdf9ca5013 --- /dev/null +++ b/src/ports/SkOSFile_win.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkOSFile.h" + +#include <io.h> +#include <stdio.h> +#include <sys/stat.h> + +typedef struct { + ULONGLONG fVolume; + ULONGLONG fLsbSize; + ULONGLONG fMsbSize; +} SkFILEID; + +static bool sk_ino(SkFILE* f, SkFILEID* id) { + int fileno = _fileno((FILE*)f); + if (fileno < 0) { + return false; + } + + HANDLE file = (HANDLE)_get_osfhandle(fileno); + if (INVALID_HANDLE_VALUE == file) { + return false; + } + + //TODO: call GetFileInformationByHandleEx on Vista and later with FileIdInfo. + BY_HANDLE_FILE_INFORMATION info; + if (0 == GetFileInformationByHandle(file, &info)) { + return false; + } + id->fVolume = info.dwVolumeSerialNumber; + id->fLsbSize = info.nFileIndexLow + (((ULONGLONG)info.nFileIndexHigh) << 32); + id->fMsbSize = 0; + + return true; +} + +bool sk_fidentical(SkFILE* a, SkFILE* b) { + SkFILEID aID, bID; + return sk_ino(a, &aID) && sk_ino(b, &bID) + && aID.fLsbSize == bID.fLsbSize + && aID.fMsbSize == bID.fMsbSize + && aID.fVolume == bID.fVolume; +} + +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; + +void sk_fmunmap(const void* addr, size_t) { + UnmapViewOfFile(addr); +} + +void* sk_fmmap(SkFILE* f, size_t* length) { + size_t fileSize = sk_fgetsize(f); + if (0 == fileSize) { + 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; + } + + *length = fileSize; + return addr; +} diff --git a/src/utils/win/SkDWriteFontFileStream.cpp b/src/utils/win/SkDWriteFontFileStream.cpp index 1569158ee2..971fdb98b4 100644 --- a/src/utils/win/SkDWriteFontFileStream.cpp +++ b/src/utils/win/SkDWriteFontFileStream.cpp @@ -8,6 +8,7 @@ #include "SkTypes.h" #include "SkDWriteFontFileStream.h" #include "SkHRESULT.h" +#include "SkTScopedComPtr.h" #include <dwrite.h> #include <limits> @@ -16,11 +17,10 @@ // SkIDWriteFontFileStream SkDWriteFontFileStream::SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream) - : fFontFileStream(fontFileStream) + : fFontFileStream(SkRefComPtr(fontFileStream)) , fPos(0) , fLockedMemory(NULL) , fFragmentLock(NULL) { - fontFileStream->AddRef(); } SkDWriteFontFileStream::~SkDWriteFontFileStream() { @@ -29,44 +29,19 @@ SkDWriteFontFileStream::~SkDWriteFontFileStream() { } } -const void* SkDWriteFontFileStream::getMemoryBase() { - if (fLockedMemory) { - return fLockedMemory; - } - - UINT64 fileSize; - HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size"); - HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock), - "Could not lock file fragment."); - return fLockedMemory; -} - -bool SkDWriteFontFileStream::rewind() { - fPos = 0; - return true; -} - size_t SkDWriteFontFileStream::read(void* buffer, size_t size) { HRESULT hr = S_OK; if (NULL == buffer) { - UINT64 realFileSize = 0; - hr = fFontFileStream->GetFileSize(&realFileSize); - if (realFileSize > (std::numeric_limits<size_t>::max)()) { - return 0; - } - size_t fileSize = static_cast<size_t>(realFileSize); - if (size == 0) { - return fileSize; + size_t fileSize = this->getLength(); + + if (fPos + size > fileSize) { + size_t skipped = fileSize - fPos; + fPos = fileSize; + return skipped; } else { - if (fPos + size > fileSize) { - size_t skipped = fileSize - fPos; - fPos = fileSize; - return skipped; - } else { - fPos += size; - return size; - } + fPos += size; + return size; } } @@ -81,28 +56,78 @@ size_t SkDWriteFontFileStream::read(void* buffer, size_t size) { } //The read may have failed because we asked for too much data. + size_t fileSize = this->getLength(); + if (fPos + size <= fileSize) { + //This means we were within bounds, but failed for some other reason. + return 0; + } + + size_t read = fileSize - fPos; + hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock); + if (SUCCEEDED(hr)) { + memcpy(buffer, start, read); + fFontFileStream->ReleaseFileFragment(fragmentLock); + fPos = fileSize; + return read; + } + + return 0; +} + +bool SkDWriteFontFileStream::isAtEnd() const { + return fPos == this->getLength(); +} + +bool SkDWriteFontFileStream::rewind() { + fPos = 0; + return true; +} + +SkDWriteFontFileStream* SkDWriteFontFileStream::duplicate() const { + return SkNEW_ARGS(SkDWriteFontFileStream, (fFontFileStream.get())); +} + +size_t SkDWriteFontFileStream::getPosition() const { + return fPos; +} + +bool SkDWriteFontFileStream::seek(size_t position) { + size_t length = this->getLength(); + fPos = (position > length) ? length : position; + return true; +} + +bool SkDWriteFontFileStream::move(long offset) { + return seek(fPos + offset); +} + +SkDWriteFontFileStream* SkDWriteFontFileStream::fork() const { + SkAutoTUnref<SkDWriteFontFileStream> that(this->duplicate()); + that->seek(fPos); + return that.detach(); +} + +size_t SkDWriteFontFileStream::getLength() const { + HRESULT hr = S_OK; UINT64 realFileSize = 0; hr = fFontFileStream->GetFileSize(&realFileSize); if (realFileSize > (std::numeric_limits<size_t>::max)()) { return 0; } - size_t fileSize = static_cast<size_t>(realFileSize); - if (fPos + size > fileSize) { - size_t read = fileSize - fPos; - hr = fFontFileStream->ReadFileFragment(&start, fPos, read, &fragmentLock); - if (SUCCEEDED(hr)) { - memcpy(buffer, start, read); - fFontFileStream->ReleaseFileFragment(fragmentLock); - fPos = fileSize; - return read; - } - return 0; - } else { - //This means we were within bounds, but failed for some other reason. - return 0; - } + return static_cast<size_t>(realFileSize); } +const void* SkDWriteFontFileStream::getMemoryBase() { + if (fLockedMemory) { + return fLockedMemory; + } + + UINT64 fileSize; + HRNM(fFontFileStream->GetFileSize(&fileSize), "Could not get file size"); + HRNM(fFontFileStream->ReadFileFragment(&fLockedMemory, 0, fileSize, &fFragmentLock), + "Could not lock file fragment."); + return fLockedMemory; +} /////////////////////////////////////////////////////////////////////////////// // SkIDWriteFontFileStreamWrapper @@ -116,8 +141,7 @@ HRESULT SkDWriteFontFileStreamWrapper::Create(SkStream* stream, SkDWriteFontFile } SkDWriteFontFileStreamWrapper::SkDWriteFontFileStreamWrapper(SkStream* stream) - : fRefCount(1), fStream(stream) { - stream->ref(); + : fRefCount(1), fStream(SkRef(stream)) { } HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::QueryInterface(REFIID iid, void** ppvObject) { @@ -180,7 +204,7 @@ HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment( if (fStream->skip(static_cast<size_t>(fileOffset)) != fileOffset) { return E_FAIL; } - SkAutoTDeleteArray<uint8_t> streamData(new uint8_t[static_cast<size_t>(fragmentSize)]); + SkAutoTMalloc<uint8_t> streamData(static_cast<size_t>(fragmentSize)); if (fStream->read(streamData.get(), static_cast<size_t>(fragmentSize)) != fragmentSize) { return E_FAIL; } @@ -192,10 +216,7 @@ HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReadFileFragment( } void STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::ReleaseFileFragment(void* fragmentContext) { - if (NULL == fragmentContext) { - return; - } - delete [] fragmentContext; + sk_free(fragmentContext); } HRESULT STDMETHODCALLTYPE SkDWriteFontFileStreamWrapper::GetFileSize(UINT64* fileSize) { diff --git a/src/utils/win/SkDWriteFontFileStream.h b/src/utils/win/SkDWriteFontFileStream.h index b214858e57..5a56290c14 100644 --- a/src/utils/win/SkDWriteFontFileStream.h +++ b/src/utils/win/SkDWriteFontFileStream.h @@ -19,13 +19,20 @@ * An SkStream backed by an IDWriteFontFileStream. * This allows Skia code to read an IDWriteFontFileStream. */ -class SkDWriteFontFileStream : public SkStream { +class SkDWriteFontFileStream : public SkStreamMemory { public: explicit SkDWriteFontFileStream(IDWriteFontFileStream* fontFileStream); virtual ~SkDWriteFontFileStream(); - virtual bool rewind() SK_OVERRIDE; virtual size_t read(void* buffer, size_t size) SK_OVERRIDE; + virtual bool isAtEnd() const SK_OVERRIDE; + virtual bool rewind() SK_OVERRIDE; + virtual SkDWriteFontFileStream* duplicate() const SK_OVERRIDE; + virtual size_t getPosition() const SK_OVERRIDE; + virtual bool seek(size_t position) SK_OVERRIDE; + virtual bool move(long offset) SK_OVERRIDE; + virtual SkDWriteFontFileStream* fork() const SK_OVERRIDE; + virtual size_t getLength() const SK_OVERRIDE; virtual const void* getMemoryBase() SK_OVERRIDE; private: |