20#ifndef DONT_HAVE_GDIPLUS
27#include <registry.hxx>
50 HRSRC hrc = FindResourceW(
g_hModule, L
"#2000",
reinterpret_cast<LPWSTR
>(RT_RCDATA));
52 HGLOBAL hglob = LoadResource(
g_hModule, hrc);
53 char* data =
static_cast<char*
>(LockResource(hglob));
54 buffer = ZipFile::ZipContentBuffer_t(data, data +
size);
59 return zipfile->HasContent(
"META-INF/documentsignatures.xml");
63 const Gdiplus::Rect&
canvas,
const Gdiplus::Rect& thumbnail_border,
const Gdiplus::Rect& signet)
67 int hoffset =
canvas.GetRight() - thumbnail_border.GetRight();
68 int voffset =
canvas.GetBottom() - thumbnail_border.GetBottom();
70 if (hoffset > voffset)
72 x = thumbnail_border.GetRight() - signet.GetRight() +
min(signet.GetRight() / 2, hoffset);
73 y = thumbnail_border.GetBottom() - signet.GetBottom();
77 x = thumbnail_border.GetRight() - signet.GetRight();
78 y = thumbnail_border.GetBottom() - signet.GetBottom() +
min(signet.GetBottom() / 2, voffset);
81 return Gdiplus::Point(
x,
y);
87Gdiplus::Rect CalcScaledAspectRatio(
const Gdiplus::Rect& src,
const Gdiplus::Rect& dest)
90 if (src.Width >= src.Height)
91 result = Gdiplus::Rect(0, 0, dest.Width, src.Height * dest.Width / src.Width);
93 result = Gdiplus::Rect(0, 0, src.Width * dest.Height / src.Height, dest.Height);
98class StreamOnZipBuffer final :
public IStream
101 explicit StreamOnZipBuffer(
const ZipFile::ZipContentBuffer_t& zip_buffer);
104 virtual ULONG STDMETHODCALLTYPE AddRef()
override;
105 virtual ULONG STDMETHODCALLTYPE Release()
override;
106 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
void __RPC_FAR *__RPC_FAR *ppvObject)
override;
109 virtual HRESULT STDMETHODCALLTYPE
Read(
void *pv, ULONG cb, ULONG *pcbRead)
override;
110 virtual HRESULT STDMETHODCALLTYPE
Write(
void const *pv, ULONG cb, ULONG *pcbWritten)
override;
111 virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
override;
112 virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize)
override;
113 virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
override;
114 virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags)
override;
115 virtual HRESULT STDMETHODCALLTYPE Revert()
override;
116 virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
override;
117 virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
override;
118 virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag)
override;
119 virtual HRESULT STDMETHODCALLTYPE
Clone(IStream **ppstm)
override;
123 const ZipFile::ZipContentBuffer_t& ref_zip_buffer_;
129StreamOnZipBuffer::StreamOnZipBuffer(
const ZipFile::ZipContentBuffer_t& zip_buffer) :
131 ref_zip_buffer_(zip_buffer),
138ULONG STDMETHODCALLTYPE StreamOnZipBuffer::AddRef()
140 return InterlockedIncrement(&ref_count_);
143ULONG STDMETHODCALLTYPE StreamOnZipBuffer::Release()
145 LONG refcnt = InterlockedDecrement(&ref_count_);
153HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::QueryInterface(REFIID riid,
void __RPC_FAR *__RPC_FAR *ppvObject)
155 *ppvObject =
nullptr;
156 IUnknown* pUnk =
nullptr;
158 if ((IID_IUnknown == riid) || (IID_IStream == riid))
165 return E_NOINTERFACE;
168HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Read(
void *pv, ULONG cb, ULONG *pcbRead)
171 return STG_E_INVALIDPOINTER;
173 size_t size = ref_zip_buffer_.size();
178 char*
p =
static_cast<char*
>(pv);
181 for ( ;(pos_ <
size) && (cb > 0); pos_++, cb--, read++)
182 *p++ = ref_zip_buffer_[pos_];
190HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *)
192 __int64
size =
static_cast<__int64
>(ref_zip_buffer_.size());
197 case STREAM_SEEK_SET:
199 case STREAM_SEEK_CUR:
200 p =
static_cast<__int64
>(pos_);
202 case STREAM_SEEK_END:
207 HRESULT
hr = STG_E_INVALIDFUNCTION;
209 p += dlibMove.QuadPart;
211 if ( ( p >= 0 ) && (
p <
size) )
213 pos_ =
static_cast<size_t>(
p);
219HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
221 if (pstatstg ==
nullptr)
222 return STG_E_INVALIDPOINTER;
224 ZeroMemory(pstatstg,
sizeof(STATSTG));
226 if (grfStatFlag == STATFLAG_DEFAULT)
228 size_t sz = 4 *
sizeof(wchar_t);
229 wchar_t*
name =
static_cast<wchar_t*
>(CoTaskMemAlloc(sz));
230 ZeroMemory(name, sz);
231 memcpy(name, L
"png", 3 *
sizeof(
wchar_t));
232 pstatstg->pwcsName =
name;
235 pstatstg->type = STGTY_LOCKBYTES;
238 uli.LowPart =
static_cast<DWORD
>(ref_zip_buffer_.size());
241 pstatstg->cbSize = uli;
246HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Write(
void const *, ULONG, ULONG *)
249HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::SetSize(ULARGE_INTEGER)
252HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::CopyTo(IStream *, ULARGE_INTEGER, ULARGE_INTEGER *, ULARGE_INTEGER *)
255HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Commit(DWORD)
258HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Revert()
261HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
264HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD)
267HRESULT STDMETHODCALLTYPE StreamOnZipBuffer::Clone(IStream **)
279 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
280 Gdiplus::GdiplusStartup(&
gdiplus_token_, &gdiplusStartupInput,
nullptr);
282 ZipFile::ZipContentBuffer_t img_data;
284 IStream*
stream =
new StreamOnZipBuffer(img_data);
300 *ppvObject =
nullptr;
301 IUnknown* pUnk =
nullptr;
303 if ((IID_IUnknown == riid) || (IID_IPersistFile == riid))
305 pUnk =
static_cast<IPersistFile*
>(
this);
310 else if (IID_IExtractImage == riid)
312 pUnk =
static_cast<IExtractImage*
>(
this);
317 return E_NOINTERFACE;
346 std::unique_ptr<ZipFile> zipfile(
new ZipFile( fname ) );
350 ZipFile::ZipContentBuffer_t thumbnail;
352 IStream*
stream =
new StreamOnZipBuffer(thumbnail);
356 if ((thumbnail_png.GetHeight() == 0) || (thumbnail_png.GetWidth() == 0))
362 HWND hwnd = GetDesktopWindow();
363 HDC hdc =
GetDC(hwnd);
364 HDC memDC = CreateCompatibleDC(hdc);
373 Gdiplus::Rect scaledRect = CalcScaledAspectRatio(
374 Gdiplus::Rect(0, 0, thumbnail_png.GetWidth(), thumbnail_png.GetHeight()), canvas_thumbnail);
381 ZeroMemory(&dib,
sizeof(dib));
383 dib.bi.biSize =
sizeof(BITMAPINFOHEADER);
388 dib.bi.biCompression = BI_RGB;
391 HBITMAP hMemBmp = CreateDIBSection(memDC,
reinterpret_cast<LPBITMAPINFO
>(&dib), DIB_RGB_COLORS, &lpBits,
nullptr, 0);
392 HGDIOBJ hOldObj = SelectObject(memDC, hMemBmp);
394 Gdiplus::Graphics graphics(memDC);
395 Gdiplus::Pen blackPen(Gdiplus::Color(255, 0, 0, 0), 1);
397 Gdiplus::SolidBrush whiteBrush(Gdiplus::Color(255, 255, 255, 255));
398 graphics.FillRectangle(&whiteBrush,
canvas);
400 scaledRect.X = (
canvas.Width - scaledRect.Width) / 2;
401 scaledRect.Y = (
canvas.Height - scaledRect.Height) / 2;
403 Gdiplus::Rect border_rect(scaledRect.X, scaledRect.Y, scaledRect.Width, scaledRect.Height);
404 graphics.DrawRectangle(&blackPen, border_rect);
408 scaledRect.Width -= 1;
409 scaledRect.Height -= 1;
411 graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
412 Gdiplus::Status stat = graphics.DrawImage(
413 &thumbnail_png, scaledRect, 0 , 0,
414 thumbnail_png.GetWidth(), thumbnail_png.GetHeight(), Gdiplus::UnitPixel);
419 double SCALING_FACTOR = 0.6;
420 Gdiplus::Rect signet_scaled(
421 0, 0,
static_cast<INT
>(
signet_->GetWidth() * SCALING_FACTOR),
static_cast<INT
>(
signet_->GetHeight() * SCALING_FACTOR));
423 Gdiplus::Rect dest(pos_signet.X, pos_signet.Y, signet_scaled.GetRight(), signet_scaled.GetBottom());
425 stat = graphics.DrawImage(
431 if (stat == Gdiplus::Ok)
433 *phBmpImage = hMemBmp;
437 SelectObject(memDC, hOldObj);
441 ReleaseDC(hwnd, hdc);
445 catch(std::exception&)
454 LPWSTR pszPathBuffer, DWORD cchMax, DWORD *pdwPriority,
const SIZE *prgSize, DWORD dwRecClrDepth, DWORD *pdwFlags)
456 if ((prgSize ==
nullptr) || (pdwFlags ==
nullptr) || ((*pdwFlags & IEIFLAG_ASYNC) && (pdwPriority ==
nullptr)))
462 *pdwFlags = IEIFLAG_CACHE;
464 wcsncpy(pszPathBuffer,
filename_.c_str(), cchMax);
virtual HRESULT STDMETHODCALLTYPE GetCurFile(LPOLESTR __RPC_FAR *ppszFileName) override
virtual HRESULT STDMETHODCALLTYPE Extract(HBITMAP *phBmpImage) override
virtual HRESULT STDMETHODCALLTYPE Load(LPCOLESTR pszFileName, DWORD dwMode) override
CThumbviewer(LONG RefCnt=1)
virtual ULONG STDMETHODCALLTYPE AddRef() override
virtual HRESULT STDMETHODCALLTYPE Save(LPCOLESTR pszFileName, BOOL fRemember) override
virtual ULONG STDMETHODCALLTYPE Release() override
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override
virtual HRESULT STDMETHODCALLTYPE GetLocation(LPWSTR pszPathBuffer, DWORD cchMax, DWORD *pdwPriority, const SIZE *prgSize, DWORD dwRecClrDepth, DWORD *pdwFlags) override
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID) override
virtual HRESULT STDMETHODCALLTYPE IsDirty() override
virtual HRESULT STDMETHODCALLTYPE SaveCompleted(LPCOLESTR pszFileName) override
Gdiplus::Bitmap * signet_
Reference< XOutputStream > stream
static void LoadSignetImageFromResource(ZipFile::ZipContentBuffer_t &buffer)
static Gdiplus::Point CalcSignetPosition(const Gdiplus::Rect &canvas, const Gdiplus::Rect &thumbnail_border, const Gdiplus::Rect &signet)
static bool IsSignedDocument(const ZipFile *zipfile)
css::uno::Reference< css::animations::XAnimationNode > Clone(const css::uno::Reference< css::animations::XAnimationNode > &xSourceNode, const SdPage *pSource=nullptr, const SdPage *pTarget=nullptr)
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
static HINSTANCE g_hModule
const wchar_t *typedef BOOL
const CLSID CLSID_THUMBVIEWER_HANDLER
const std::string THUMBNAIL_CONTENT
std::wstring getShortPathName(const std::wstring &aLongName)
helper function to convert windows paths to short form.
void OutputDebugStringFormatW(LPCWSTR pFormat,...)