Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright 2011 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkTypes.h"
      9 #if defined(SK_BUILD_FOR_WIN)
     10 
     11 #include "SkIStream.h"
     12 #include "SkStream.h"
     13 
     14 /**
     15  * SkBaseIStream
     16  */
     17 SkBaseIStream::SkBaseIStream() : _refcount(1) { }
     18 SkBaseIStream::~SkBaseIStream() { }
     19 
     20 HRESULT STDMETHODCALLTYPE SkBaseIStream::QueryInterface(REFIID iid
     21                                                       , void ** ppvObject)
     22 {
     23     if (nullptr == ppvObject) {
     24         return E_INVALIDARG;
     25     }
     26     if (iid == __uuidof(IUnknown)
     27         || iid == __uuidof(IStream)
     28         || iid == __uuidof(ISequentialStream))
     29     {
     30         *ppvObject = static_cast<IStream*>(this);
     31         AddRef();
     32         return S_OK;
     33     } else {
     34         *ppvObject = nullptr;
     35         return E_NOINTERFACE;
     36     }
     37 }
     38 
     39 ULONG STDMETHODCALLTYPE SkBaseIStream::AddRef(void) {
     40     return (ULONG)InterlockedIncrement(&_refcount);
     41 }
     42 
     43 ULONG STDMETHODCALLTYPE SkBaseIStream::Release(void) {
     44     ULONG res = (ULONG) InterlockedDecrement(&_refcount);
     45     if (0 == res) {
     46         delete this;
     47     }
     48     return res;
     49 }
     50 
     51 // ISequentialStream Interface
     52 HRESULT STDMETHODCALLTYPE SkBaseIStream::Read(void* pv
     53                                             , ULONG cb
     54                                             , ULONG* pcbRead)
     55 { return E_NOTIMPL; }
     56 
     57 HRESULT STDMETHODCALLTYPE SkBaseIStream::Write(void const* pv
     58                                              , ULONG cb
     59                                              , ULONG* pcbWritten)
     60 { return E_NOTIMPL; }
     61 
     62 // IStream Interface
     63 HRESULT STDMETHODCALLTYPE SkBaseIStream::SetSize(ULARGE_INTEGER)
     64 { return E_NOTIMPL; }
     65 
     66 HRESULT STDMETHODCALLTYPE SkBaseIStream::CopyTo(IStream*
     67                                               , ULARGE_INTEGER
     68                                               , ULARGE_INTEGER*
     69                                               , ULARGE_INTEGER*)
     70 { return E_NOTIMPL; }
     71 
     72 HRESULT STDMETHODCALLTYPE SkBaseIStream::Commit(DWORD)
     73 { return E_NOTIMPL; }
     74 
     75 HRESULT STDMETHODCALLTYPE SkBaseIStream::Revert(void)
     76 { return E_NOTIMPL; }
     77 
     78 HRESULT STDMETHODCALLTYPE SkBaseIStream::LockRegion(ULARGE_INTEGER
     79                                                   , ULARGE_INTEGER
     80                                                   , DWORD)
     81 { return E_NOTIMPL; }
     82 
     83 HRESULT STDMETHODCALLTYPE SkBaseIStream::UnlockRegion(ULARGE_INTEGER
     84                                                     , ULARGE_INTEGER
     85                                                     , DWORD)
     86 { return E_NOTIMPL; }
     87 
     88 HRESULT STDMETHODCALLTYPE SkBaseIStream::Clone(IStream **)
     89 { return E_NOTIMPL; }
     90 
     91 HRESULT STDMETHODCALLTYPE SkBaseIStream::Seek(LARGE_INTEGER liDistanceToMove
     92                                             , DWORD dwOrigin
     93                                             , ULARGE_INTEGER* lpNewFilePointer)
     94 { return E_NOTIMPL; }
     95 
     96 HRESULT STDMETHODCALLTYPE SkBaseIStream::Stat(STATSTG* pStatstg
     97                                             , DWORD grfStatFlag)
     98 { return E_NOTIMPL; }
     99 
    100 
    101 /**
    102  * SkIStream
    103  */
    104 SkIStream::SkIStream(SkStream* stream, bool deleteOnRelease)
    105     : SkBaseIStream()
    106     , fSkStream(stream)
    107     , fDeleteOnRelease(deleteOnRelease)
    108     , fLocation()
    109 {
    110     this->fSkStream->rewind();
    111 }
    112 
    113 SkIStream::~SkIStream() {
    114     if (fDeleteOnRelease) {
    115         delete this->fSkStream;
    116     }
    117 }
    118 
    119 HRESULT SkIStream::CreateFromSkStream(SkStream* stream
    120                                     , bool deleteOnRelease
    121                                     , IStream ** ppStream)
    122 {
    123     if (nullptr == stream) {
    124         return E_INVALIDARG;
    125     }
    126     *ppStream = new SkIStream(stream, deleteOnRelease);
    127     return S_OK;
    128 }
    129 
    130 // ISequentialStream Interface
    131 HRESULT STDMETHODCALLTYPE SkIStream::Read(void* pv, ULONG cb, ULONG* pcbRead) {
    132     *pcbRead = static_cast<ULONG>(this->fSkStream->read(pv, cb));
    133     this->fLocation.QuadPart += *pcbRead;
    134     return (*pcbRead == cb) ? S_OK : S_FALSE;
    135 }
    136 
    137 HRESULT STDMETHODCALLTYPE SkIStream::Write(void const* pv
    138                                          , ULONG cb
    139                                          , ULONG* pcbWritten)
    140 {
    141     return STG_E_CANTSAVE;
    142 }
    143 
    144 // IStream Interface
    145 HRESULT STDMETHODCALLTYPE SkIStream::Seek(LARGE_INTEGER liDistanceToMove
    146                                         , DWORD dwOrigin
    147                                         , ULARGE_INTEGER* lpNewFilePointer)
    148 {
    149     HRESULT hr = S_OK;
    150 
    151     switch(dwOrigin) {
    152     case STREAM_SEEK_SET: {
    153         if (!this->fSkStream->rewind()) {
    154             hr = E_FAIL;
    155         } else {
    156             size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
    157             size_t skipped = this->fSkStream->skip(skip);
    158             this->fLocation.QuadPart = skipped;
    159             if (skipped != skip) {
    160                 hr = E_FAIL;
    161             }
    162         }
    163         break;
    164     }
    165     case STREAM_SEEK_CUR: {
    166         size_t skip = static_cast<size_t>(liDistanceToMove.QuadPart);
    167         size_t skipped = this->fSkStream->skip(skip);
    168         this->fLocation.QuadPart += skipped;
    169         if (skipped != skip) {
    170             hr = E_FAIL;
    171         }
    172         break;
    173     }
    174     case STREAM_SEEK_END: {
    175         if (!this->fSkStream->rewind()) {
    176             hr = E_FAIL;
    177         } else {
    178             // FIXME: Should not depend on getLength.
    179             // See https://code.google.com/p/skia/issues/detail?id=1570
    180             size_t skip = static_cast<size_t>(this->fSkStream->getLength() +
    181                                               liDistanceToMove.QuadPart);
    182             size_t skipped = this->fSkStream->skip(skip);
    183             this->fLocation.QuadPart = skipped;
    184             if (skipped != skip) {
    185                 hr = E_FAIL;
    186             }
    187         }
    188         break;
    189     }
    190     default:
    191         hr = STG_E_INVALIDFUNCTION;
    192         break;
    193     }
    194 
    195     if (lpNewFilePointer) {
    196         lpNewFilePointer->QuadPart = this->fLocation.QuadPart;
    197     }
    198     return hr;
    199 }
    200 
    201 HRESULT STDMETHODCALLTYPE SkIStream::Stat(STATSTG* pStatstg
    202                                         , DWORD grfStatFlag)
    203 {
    204     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
    205         return STG_E_INVALIDFLAG;
    206     }
    207     pStatstg->pwcsName = nullptr;
    208     // FIXME: Should not depend on getLength
    209     // See https://code.google.com/p/skia/issues/detail?id=1570
    210     pStatstg->cbSize.QuadPart = this->fSkStream->getLength();
    211     pStatstg->clsid = CLSID_NULL;
    212     pStatstg->type = STGTY_STREAM;
    213     pStatstg->grfMode = STGM_READ;
    214     return S_OK;
    215 }
    216 
    217 
    218 /**
    219  * SkIWStream
    220  */
    221 SkWIStream::SkWIStream(SkWStream* stream)
    222     : SkBaseIStream()
    223     , fSkWStream(stream)
    224 { }
    225 
    226 SkWIStream::~SkWIStream() {
    227     if (this->fSkWStream) {
    228         this->fSkWStream->flush();
    229     }
    230 }
    231 
    232 HRESULT SkWIStream::CreateFromSkWStream(SkWStream* stream
    233                                       , IStream ** ppStream)
    234 {
    235     *ppStream = new SkWIStream(stream);
    236     return S_OK;
    237 }
    238 
    239 // ISequentialStream Interface
    240 HRESULT STDMETHODCALLTYPE SkWIStream::Write(void const* pv
    241                                           , ULONG cb
    242                                           , ULONG* pcbWritten)
    243 {
    244     HRESULT hr = S_OK;
    245     bool wrote = this->fSkWStream->write(pv, cb);
    246     if (wrote) {
    247         *pcbWritten = cb;
    248     } else {
    249         *pcbWritten = 0;
    250         hr = S_FALSE;
    251     }
    252     return hr;
    253 }
    254 
    255 // IStream Interface
    256 HRESULT STDMETHODCALLTYPE SkWIStream::Commit(DWORD) {
    257     this->fSkWStream->flush();
    258     return S_OK;
    259 }
    260 
    261 HRESULT STDMETHODCALLTYPE SkWIStream::Stat(STATSTG* pStatstg
    262                                          , DWORD grfStatFlag)
    263 {
    264     if (0 == (grfStatFlag & STATFLAG_NONAME)) {
    265         return STG_E_INVALIDFLAG;
    266     }
    267     pStatstg->pwcsName = nullptr;
    268     pStatstg->cbSize.QuadPart = 0;
    269     pStatstg->clsid = CLSID_NULL;
    270     pStatstg->type = STGTY_STREAM;
    271     pStatstg->grfMode = STGM_WRITE;
    272     return S_OK;
    273 }
    274 #endif//defined(SK_BUILD_FOR_WIN)
    275