| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | // Copyright (c) 2020 GitHub, Inc.
 | 
					
						
							|  |  |  | // Use of this source code is governed by the MIT license that can be
 | 
					
						
							|  |  |  | // found in the LICENSE file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "shell/common/api/electron_api_native_image.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <windows.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <thumbcache.h>
 | 
					
						
							|  |  |  | #include <wrl/client.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 21:21:36 +00:00
										 |  |  | #include "base/win/scoped_com_initializer.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | #include "shell/common/gin_converters/image_converter.h"
 | 
					
						
							|  |  |  | #include "shell/common/gin_helper/promise.h"
 | 
					
						
							|  |  |  | #include "shell/common/skia_util.h"
 | 
					
						
							| 
									
										
										
										
											2021-07-01 17:51:37 -07:00
										 |  |  | #include "third_party/skia/include/core/SkBitmap.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | #include "ui/gfx/icon_util.h"
 | 
					
						
							| 
									
										
										
										
											2021-07-01 17:51:37 -07:00
										 |  |  | #include "ui/gfx/image/image_skia.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 12:55:47 -07:00
										 |  |  | namespace electron::api { | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // static
 | 
					
						
							|  |  |  | v8::Local<v8::Promise> NativeImage::CreateThumbnailFromPath( | 
					
						
							|  |  |  |     v8::Isolate* isolate, | 
					
						
							|  |  |  |     const base::FilePath& path, | 
					
						
							|  |  |  |     const gfx::Size& size) { | 
					
						
							| 
									
										
										
										
											2021-08-27 21:21:36 +00:00
										 |  |  |   base::win::ScopedCOMInitializer scoped_com_initializer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |   gin_helper::Promise<gfx::Image> promise(isolate); | 
					
						
							|  |  |  |   v8::Local<v8::Promise> handle = promise.GetHandle(); | 
					
						
							|  |  |  |   HRESULT hr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (size.IsEmpty()) { | 
					
						
							|  |  |  |     promise.RejectWithErrorMessage("size must not be empty"); | 
					
						
							|  |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // create an IShellItem
 | 
					
						
							|  |  |  |   Microsoft::WRL::ComPtr<IShellItem> pItem; | 
					
						
							| 
									
										
										
										
											2021-03-18 15:55:51 -04:00
										 |  |  |   std::wstring image_path = path.value(); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |   hr = SHCreateItemFromParsingName(image_path.c_str(), nullptr, | 
					
						
							|  |  |  |                                    IID_PPV_ARGS(&pItem)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							|  |  |  |     promise.RejectWithErrorMessage( | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |         "Failed to create IShellItem from the given path"); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Init thumbnail cache
 | 
					
						
							|  |  |  |   Microsoft::WRL::ComPtr<IThumbnailCache> pThumbnailCache; | 
					
						
							|  |  |  |   hr = CoCreateInstance(CLSID_LocalThumbnailCache, nullptr, CLSCTX_INPROC, | 
					
						
							|  |  |  |                         IID_PPV_ARGS(&pThumbnailCache)); | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							|  |  |  |     promise.RejectWithErrorMessage( | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |         "Failed to acquire local thumbnail cache reference"); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Populate the IShellBitmap
 | 
					
						
							|  |  |  |   Microsoft::WRL::ComPtr<ISharedBitmap> pThumbnail; | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |   hr = pThumbnailCache->GetThumbnail( | 
					
						
							|  |  |  |       pItem.Get(), size.width(), | 
					
						
							|  |  |  |       WTS_FLAGS::WTS_SCALETOREQUESTEDSIZE | WTS_FLAGS::WTS_SCALEUP, &pThumbnail, | 
					
						
							| 
									
										
										
										
											2023-10-03 21:26:35 +02:00
										 |  |  |       nullptr, nullptr); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							|  |  |  |     promise.RejectWithErrorMessage( | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |         "Failed to get thumbnail from local thumbnail cache reference"); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Init HBITMAP
 | 
					
						
							| 
									
										
										
										
											2023-10-03 21:26:35 +02:00
										 |  |  |   HBITMAP hBitmap = nullptr; | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |   hr = pThumbnail->GetSharedBitmap(&hBitmap); | 
					
						
							|  |  |  |   if (FAILED(hr)) { | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |     promise.RejectWithErrorMessage("Failed to extract bitmap from thumbnail"); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // convert HBITMAP to gfx::Image
 | 
					
						
							|  |  |  |   BITMAP bitmap; | 
					
						
							|  |  |  |   if (!GetObject(hBitmap, sizeof(bitmap), &bitmap)) { | 
					
						
							| 
									
										
										
										
											2023-03-09 03:48:29 +01:00
										 |  |  |     promise.RejectWithErrorMessage("Could not convert HBITMAP to BITMAP"); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |     return handle; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ICONINFO icon_info; | 
					
						
							|  |  |  |   icon_info.fIcon = TRUE; | 
					
						
							|  |  |  |   icon_info.hbmMask = hBitmap; | 
					
						
							|  |  |  |   icon_info.hbmColor = hBitmap; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-19 12:09:35 +01:00
										 |  |  |   base::win::ScopedGDIObject<HICON> icon(CreateIconIndirect(&icon_info)); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |   SkBitmap skbitmap = IconUtil::CreateSkBitmapFromHICON(icon.get()); | 
					
						
							| 
									
										
										
										
											2021-01-12 15:31:23 -08:00
										 |  |  |   gfx::ImageSkia image_skia = | 
					
						
							|  |  |  |       gfx::ImageSkia::CreateFromBitmap(skbitmap, 1.0 /*scale factor*/); | 
					
						
							| 
									
										
										
										
											2020-08-24 09:36:13 -07:00
										 |  |  |   gfx::Image gfx_image = gfx::Image(image_skia); | 
					
						
							|  |  |  |   promise.Resolve(gfx_image); | 
					
						
							|  |  |  |   return handle; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 12:55:47 -07:00
										 |  |  | }  // namespace electron::api
 |