33constexpr std::array<uint8_t, 8> CFB_MAGIC = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
60std::vector<uint8_t> readStream(
const CFB::CompoundFileReader& aReader,
const CFB::COMPOUND_FILE_ENTRY* aEntry )
70 aReader.ReadFile( aEntry, 0,
reinterpret_cast<char*
>( data.data() ), data.size() );
80 auto cfb = std::search( aPayload.begin(), aPayload.end(), CFB_MAGIC.begin(), CFB_MAGIC.end() );
82 if( cfb == aPayload.end() )
87 const uint8_t* base = &*cfb;
88 size_t size =
static_cast<size_t>( aPayload.end() - cfb );
89 CFB::CompoundFileReader reader( base, size );
90 const CFB::COMPOUND_FILE_ENTRY* presentation =
nullptr;
91 const CFB::COMPOUND_FILE_ENTRY* native =
nullptr;
93 reader.EnumFiles( reader.GetRootEntry(), -1,
94 [&](
const CFB::COMPOUND_FILE_ENTRY* aEntry,
const CFB::utf16string&,
int )
96 if( !reader.IsStream( aEntry ) )
99 if( entryNameIs( aEntry, 2,
"OlePres000" ) )
100 presentation = aEntry;
101 else if( entryNameIs( aEntry, 1,
"Ole10Native" ) )
109 std::vector<uint8_t> data = readStream( reader, presentation );
111 if( data.size() >= 40 )
113 uint32_t clipboardFormat = readU32( data.data() + 4 );
115 if( clipboardFormat == 3 )
118 if( clipboardFormat == 8 )
121 if( clipboardFormat == 14 )
128 std::vector<uint8_t> data = readStream( reader, native );
129 size_t limit = std::min<size_t>( data.size(), 64 );
131 for(
size_t offset = 0; offset + 14 <= limit; ++offset )
133 if( data[offset] ==
'B' && data[offset + 1] ==
'M' )
138 catch(
const std::exception& )
146bool OrcadRenderWmf(
const std::vector<uint8_t>& aWmf,
int aMaxWidth,
int aMaxHeight, wxImage& aImage )
148 if( aWmf.empty() || aWmf.size() >
static_cast<size_t>( std::numeric_limits<long>::max() ) )
151 wmfAPI* api =
nullptr;
152 wmfAPI_Options options{};
154 char* fontDirs[] = { fontDir.data(),
nullptr };
155 options.function = wmf_gd_function;
156 options.fontdirs = fontDirs;
158 constexpr unsigned long flags =
159 WMF_OPT_FUNCTION | WMF_OPT_FONTDIRS | WMF_OPT_IGNORE_NONFATAL | WMF_OPT_NO_DEBUG | WMF_OPT_NO_ERROR;
161 if( wmf_api_create( &api, flags, &options ) != wmf_E_None )
164 auto destroyApi = [&]
166 wmf_api_destroy( api );
170 wmf_gd_t* gd = WMF_GD_GetData( api );
171 gd->type = wmf_gd_image;
173 if( wmf_mem_open( api,
const_cast<uint8_t*
>( aWmf.data() ),
static_cast<long>( aWmf.size() ) ) != wmf_E_None )
181 if( wmf_scan( api, 0, &bbox ) != wmf_E_None )
187 unsigned int naturalWidth = 0;
188 unsigned int naturalHeight = 0;
190 if( wmf_display_size( api, &naturalWidth, &naturalHeight, 144.0, 144.0 ) != wmf_E_None || naturalWidth == 0
191 || naturalHeight == 0 )
197 double scale = std::min(
static_cast<double>( std::max( 1, aMaxWidth ) ) / naturalWidth,
198 static_cast<double>( std::max( 1, aMaxHeight ) ) / naturalHeight );
200 unsigned int width =
static_cast<unsigned int>( std::max<long>( 1, std::lround( naturalWidth *
scale ) ) );
201 unsigned int height =
static_cast<unsigned int>( std::max<long>( 1, std::lround( naturalHeight *
scale ) ) );
207 if( wmf_play( api, 0, &bbox ) != wmf_E_None )
213 int* pixels = wmf_gd_get_image_pixels( api );
215 if( !pixels || !aImage.Create( width, height,
false ) )
221 unsigned char* rgb = aImage.GetData();
223 for(
size_t i = 0; i < static_cast<size_t>( width ) * height; ++i )
225 rgb[3 * i] =
static_cast<unsigned char>( ( pixels[i] >> 16 ) & 0xFF );
226 rgb[3 * i + 1] =
static_cast<unsigned char>( ( pixels[i] >> 8 ) & 0xFF );
227 rgb[3 * i + 2] =
static_cast<unsigned char>( pixels[i] & 0xFF );
static wxString GetStockDataPath(bool aRespectRunFromBuildDir=true)
Gets the stock (install) data path, which is the base path for things like scripting,...