aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ports
diff options
context:
space:
mode:
Diffstat (limited to 'src/ports')
-rw-r--r--src/ports/SkFontHost_fontconfig.cpp30
-rw-r--r--src/ports/SkOSFile_none.cpp18
-rw-r--r--src/ports/SkOSFile_posix.cpp63
-rw-r--r--src/ports/SkOSFile_stdio.cpp79
-rw-r--r--src/ports/SkOSFile_win.cpp99
5 files changed, 242 insertions, 47 deletions
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;
+}