X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fui%2Fdialog%2Ffiledialogimpl-win32.cpp;h=d6624828cf3f9ed6da91acd41261ce097f7ecca4;hb=0c01694a499e247c324a0618c2caad7fa7db449d;hp=4dfa36b488620648294f880433aeca0bb27c8ebd;hpb=8f6fed342c4f5d1f54a8dee80e1e79dc1a452797;p=inkscape.git diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 4dfa36b48..d6624828c 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -40,7 +40,7 @@ #include #include #include "sp-item.h" -#include "canvas-arena.h" +#include "display/canvas-arena.h" #include "filedialog.h" #include "filedialogimpl-win32.h" @@ -104,10 +104,13 @@ FileDialogBaseWin32::FileDialogBaseWin32(Gtk::Window &parent, parent(parent), _current_directory(dir) { - //_mutex = NULL; _main_loop = NULL; + _filter_index = 1; + _filter_count = 0; + _title = (wchar_t*)g_utf8_to_utf16(title, -1, NULL, NULL, NULL); + g_assert(_title != NULL); Glib::RefPtr parentWindow = parent.get_window(); g_assert(parentWindow->gobj() != NULL); @@ -162,6 +165,9 @@ FileOpenDialogImplWin32::FileOpenDialogImplWin32(Gtk::Window &parent, _preview_document_height = 0; _preview_image_width = 0; _preview_image_height = 0; + _preview_emf_image = false; + + _mutex = NULL; createFilterMenu(); } @@ -206,7 +212,7 @@ void FileOpenDialogImplWin32::createFilterMenu() if (imod->deactivated()) continue; // Type - filter.name = g_utf8_to_utf16(imod->get_filetypename(), + filter.name = g_utf8_to_utf16(_(imod->get_filetypename()), -1, NULL, &filter.name_length, NULL); // Extension @@ -243,24 +249,24 @@ void FileOpenDialogImplWin32::createFilterMenu() -1, NULL, &all_image_files.name_length, NULL); all_image_files.filter = g_utf8_to_utf16(all_image_files_filter.data(), -1, NULL, &all_image_files.filter_length, NULL); + all_image_files.mod = NULL; filter_list.push_front(all_image_files); - _extension_map[extension_index++] = NULL; // Filter Inkscape Files all_inkscape_files.name = g_utf8_to_utf16(all_inkscape_files_filter_name, -1, NULL, &all_inkscape_files.name_length, NULL); all_inkscape_files.filter = g_utf8_to_utf16(all_inkscape_files_filter.data(), -1, NULL, &all_inkscape_files.filter_length, NULL); + all_inkscape_files.mod = NULL; filter_list.push_front(all_inkscape_files); - _extension_map[extension_index++] = NULL; // Filter All Files all_files.name = g_utf8_to_utf16(all_files_filter_name, -1, NULL, &all_files.name_length, NULL); all_files.filter = NULL; all_files.filter_length = 0; + all_files.mod = NULL; filter_list.push_front(all_files); - _extension_map[extension_index++] = NULL; filter_length += all_files.name_length + 3 + all_inkscape_files.filter_length + @@ -268,17 +274,16 @@ void FileOpenDialogImplWin32::createFilterMenu() all_image_files.filter_length + all_image_files.name_length + 3 + 1; // Add 3 for 2*2 \0s and a *, and 1 for a trailing \0 - - - _filter = new wchar_t[filter_length]; + + _filter = new wchar_t[filter_length]; wchar_t *filterptr = _filter; - + for(list::iterator filter_iterator = filter_list.begin(); filter_iterator != filter_list.end(); filter_iterator++) { const Filter &filter = *filter_iterator; - memcpy(filterptr, filter.name, filter.name_length * 2); + wcsncpy(filterptr, (wchar_t*)filter.name, filter.name_length); filterptr += filter.name_length; g_free(filter.name); @@ -287,7 +292,7 @@ void FileOpenDialogImplWin32::createFilterMenu() if(filter.filter != NULL) { - memcpy(filterptr, filter.filter, filter.filter_length * 2); + wcsncpy(filterptr, (wchar_t*)filter.filter, filter.filter_length); filterptr += filter.filter_length; g_free(filter.filter); } @@ -298,8 +303,9 @@ void FileOpenDialogImplWin32::createFilterMenu() _extension_map[extension_index++] = filter.mod; } *(filterptr++) = L'\0'; - - _filterIndex = 2; + + _filter_count = extension_index; + _filter_index = 2; // Select the 2nd filter in the list - 2 is NOT the 3rd } void FileOpenDialogImplWin32::GetOpenFileName_thread() @@ -307,11 +313,11 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() OPENFILENAMEEXW ofn; g_assert(this != NULL); - //g_assert(_mutex != NULL); - g_assert(_main_loop != NULL); - + g_assert(_mutex != NULL); + WCHAR* current_directory_string = (WCHAR*)g_utf8_to_utf16( - _current_directory.data(), -1, NULL, NULL, NULL); + _current_directory.data(), _current_directory.length(), + NULL, NULL, NULL); memset(&ofn, 0, sizeof(ofn)); @@ -332,16 +338,15 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() ofn.lpstrTitle = _title; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_HIDEREADONLY | OFN_ENABLESIZING; ofn.lpstrFilter = _filter; - ofn.nFilterIndex = _filterIndex; + ofn.nFilterIndex = _filter_index; ofn.lpfnHook = GetOpenFileName_hookproc; ofn.lCustData = (LPARAM)this; _result = GetOpenFileNameW(&ofn) != 0; - _filterIndex = ofn.nFilterIndex; - _extension = _extension_map[ofn.nFilterIndex]; - - myFilename = utf16_to_ustring(_path_string, _MAX_PATH); + g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); + _filter_index = ofn.nFilterIndex; + _extension = _extension_map[ofn.nFilterIndex - 1]; // Copy the selected file name, converting from UTF-16 to UTF-8 myFilename = utf16_to_ustring(_path_string, _MAX_PATH); @@ -352,9 +357,6 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() _mutex->lock(); _finished = true; _mutex->unlock(); - //g_main_loop_quit(_main_loop); - - } void FileOpenDialogImplWin32::register_preview_wnd_class() @@ -435,7 +437,7 @@ UINT_PTR CALLBACK FileOpenDialogImplWin32::GetOpenFileName_hookproc( pImpl->_file_dialog_wnd = hParentWnd; pImpl->_preview_wnd = - CreateWindow(PreviewWindowClassName, "", + CreateWindowA(PreviewWindowClassName, "", WS_CHILD | WS_VISIBLE, 0, 0, 100, 100, hParentWnd, NULL, hInstance, NULL); SetWindowLongPtr(pImpl->_preview_wnd, GWLP_USERDATA, ofn->lCustData); @@ -466,8 +468,6 @@ UINT_PTR CALLBACK FileOpenDialogImplWin32::GetOpenFileName_hookproc( pImpl->_file_selected = true; pImpl->_mutex->unlock(); - - //pImpl->file_selected(); } } break; @@ -559,7 +559,6 @@ LRESULT CALLBACK FileOpenDialogImplWin32::preview_wnd_proc(HWND hwnd, UINT uMsg, pImpl->_mutex->lock(); - //FillRect(dc, &client_rect, (HBRUSH)(COLOR_HOTLIGHT+1)); if(pImpl->_path_string[0] == 0) { FillRect(dc, &rcClient, (HBRUSH)(COLOR_3DFACE + 1)); @@ -792,6 +791,8 @@ void FileOpenDialogImplWin32::load_preview() // Prepare to render a preview const Glib::ustring svg = ".svg"; const Glib::ustring svgz = ".svgz"; + const Glib::ustring emf = ".emf"; + const Glib::ustring wmf = ".wmf"; const Glib::ustring path = utf16_to_ustring(_path_string); bool success = false; @@ -801,6 +802,8 @@ void FileOpenDialogImplWin32::load_preview() if ((dialogType == SVG_TYPES || dialogType == IMPORT_TYPES) && (hasSuffix(path, svg) || hasSuffix(path, svgz))) success = set_svg_preview(); + else if (hasSuffix(path, emf) || hasSuffix(path, wmf)) + success = set_emf_preview(); else if (isValidImageFile(path)) success = set_image_preview(); else { @@ -824,6 +827,7 @@ void FileOpenDialogImplWin32::free_preview() _preview_file_icon = NULL; _preview_bitmap_image.clear(); + _preview_emf_image = false; _mutex->unlock(); } @@ -865,7 +869,7 @@ bool FileOpenDialogImplWin32::set_svg_preview() NR::Maybe maybeArea(area); sp_document_ensure_up_to_date (svgDoc); sp_item_invoke_bbox((SPItem *) svgDoc->root, &maybeArea, - sp_item_i2r_affine((SPItem *)(svgDoc->root)), TRUE); + from_2geom(sp_item_i2r_affine((SPItem *)(svgDoc->root))), TRUE); NRArena *const arena = NRArena::create(); @@ -875,7 +879,7 @@ bool FileOpenDialogImplWin32::set_svg_preview() arena, key, SP_ITEM_SHOW_DISPLAY); NRGC gc(NULL); - nr_matrix_set_scale(&gc.transform, scaleFactor, scaleFactor); + gc.transform = NR::Matrix(NR::scale(scaleFactor, scaleFactor)); nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE); @@ -940,18 +944,192 @@ bool FileOpenDialogImplWin32::set_image_preview() { const Glib::ustring path = utf16_to_ustring(_path_string, _MAX_PATH); + bool successful = false; + _mutex->lock(); - _preview_bitmap_image = Gdk::Pixbuf::create_from_file(path); - if(!_preview_bitmap_image) return false; - _preview_image_width = _preview_bitmap_image->get_width(); - _preview_document_width = _preview_image_width; - _preview_image_height = _preview_bitmap_image->get_height(); - _preview_document_height = _preview_image_height; + try { + _preview_bitmap_image = Gdk::Pixbuf::create_from_file(path); + if (_preview_bitmap_image) { + _preview_image_width = _preview_bitmap_image->get_width(); + _preview_document_width = _preview_image_width; + _preview_image_height = _preview_bitmap_image->get_height(); + _preview_document_height = _preview_image_height; + successful = true; + } + } + catch (const Gdk::PixbufError&) {} + catch (const Glib::FileError&) {} _mutex->unlock(); - return true; + return successful; +} + +// Aldus Placeable Header =================================================== +// Since we are a 32bit app, we have to be sure this structure compiles to +// be identical to a 16 bit app's version. To do this, we use the #pragma +// to adjust packing, we use a WORD for the hmf handle, and a SMALL_RECT +// for the bbox rectangle. +#pragma pack( push ) +#pragma pack( 2 ) +typedef struct +{ + DWORD dwKey; + WORD hmf; + SMALL_RECT bbox; + WORD wInch; + DWORD dwReserved; + WORD wCheckSum; +} APMHEADER, *PAPMHEADER; +#pragma pack( pop ) + + +static HENHMETAFILE +MyGetEnhMetaFileW( const WCHAR *filename ) +{ + // Try open as Enhanced Metafile + HENHMETAFILE hemf = GetEnhMetaFileW(filename); + + if (!hemf) { + // Try open as Windows Metafile + HMETAFILE hmf = GetMetaFileW(filename); + + METAFILEPICT mp; + HDC hDC; + + if (!hmf) { + WCHAR szTemp[MAX_PATH]; + + DWORD dw = GetShortPathNameW( filename, szTemp, MAX_PATH ); + if (dw) { + hmf = GetMetaFileW( szTemp ); + } + } + + if (hmf) { + // Convert Windows Metafile to Enhanced Metafile + DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL ); + + if (nSize) { + BYTE *lpvData = new BYTE[nSize]; + if (lpvData) { + DWORD dw = GetMetaFileBitsEx( hmf, nSize, lpvData ); + if (dw) { + // Fill out a METAFILEPICT structure + mp.mm = MM_ANISOTROPIC; + mp.xExt = 1000; + mp.yExt = 1000; + mp.hMF = NULL; + // Get a reference DC + hDC = GetDC( NULL ); + // Make an enhanced metafile from the windows metafile + hemf = SetWinMetaFileBits( nSize, lpvData, hDC, &mp ); + // Clean up + ReleaseDC( NULL, hDC ); + DeleteMetaFile( hmf ); + } + delete[] lpvData; + } + else { + DeleteMetaFile( hmf ); + } + } + else { + DeleteMetaFile( hmf ); + } + } + else { + // Try open as Aldus Placeable Metafile + HANDLE hFile; + hFile = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + if (hFile != INVALID_HANDLE_VALUE) { + DWORD nSize = GetFileSize( hFile, NULL ); + if (nSize) { + BYTE *lpvData = new BYTE[nSize]; + if (lpvData) { + DWORD dw = ReadFile( hFile, lpvData, nSize, &nSize, NULL ); + if (dw) { + if ( ((PAPMHEADER)lpvData)->dwKey == 0x9ac6cdd7l ) { + // Fill out a METAFILEPICT structure + mp.mm = MM_ANISOTROPIC; + mp.xExt = ((PAPMHEADER)lpvData)->bbox.Right - ((PAPMHEADER)lpvData)->bbox.Left; + mp.xExt = ( mp.xExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch); + mp.yExt = ((PAPMHEADER)lpvData)->bbox.Bottom - ((PAPMHEADER)lpvData)->bbox.Top; + mp.yExt = ( mp.yExt * 2540l ) / (DWORD)(((PAPMHEADER)lpvData)->wInch); + mp.hMF = NULL; + // Get a reference DC + hDC = GetDC( NULL ); + // Create an enhanced metafile from the bits + hemf = SetWinMetaFileBits( nSize, lpvData+sizeof(APMHEADER), hDC, &mp ); + // Clean up + ReleaseDC( NULL, hDC ); + } + } + delete[] lpvData; + } + } + CloseHandle( hFile ); + } + } + } + + return hemf; +} + + +bool FileOpenDialogImplWin32::set_emf_preview() +{ + _mutex->lock(); + + BOOL ok = FALSE; + + DWORD w = 0; + DWORD h = 0; + + HENHMETAFILE hemf = MyGetEnhMetaFileW( _path_string ); + + if (hemf) + { + ENHMETAHEADER emh; + ZeroMemory(&emh, sizeof(emh)); + ok = GetEnhMetaFileHeader(hemf, sizeof(emh), &emh) != 0; + + w = (emh.rclFrame.right - emh.rclFrame.left); + h = (emh.rclFrame.bottom - emh.rclFrame.top); + + DeleteEnhMetaFile(hemf); + } + + if (ok) + { + const int PreviewSize = 512; + + // Get the size of the document + const double emfWidth = w; + const double emfHeight = h; + + // Find the minimum scale to fit the image inside the preview area + const double scaleFactorX = PreviewSize / emfWidth; + const double scaleFactorY = PreviewSize / emfHeight; + const double scaleFactor = (scaleFactorX > scaleFactorY) ? scaleFactorY : scaleFactorX; + + // Now get the resized values + const double scaledEmfWidth = scaleFactor * emfWidth; + const double scaledEmfHeight = scaleFactor * emfHeight; + + _preview_document_width = scaledEmfWidth; + _preview_document_height = scaledEmfHeight; + _preview_image_width = emfWidth; + _preview_image_height = emfHeight; + + _preview_emf_image = true; + } + + _mutex->unlock(); + + return ok; } void FileOpenDialogImplWin32::render_preview() @@ -971,7 +1149,7 @@ void FileOpenDialogImplWin32::render_preview() // Do we have anything to render? _mutex->lock(); - if(!_preview_bitmap_image) + if(!_preview_bitmap_image && !_preview_emf_image) { _mutex->unlock(); return; @@ -1143,7 +1321,6 @@ void FileOpenDialogImplWin32::render_preview() context->stroke_preserve(); // Draw the image - if(_preview_bitmap_image) // Is the image a pixbuf? { // Set the transformation @@ -1170,6 +1347,20 @@ void FileOpenDialogImplWin32::render_preview() // Finish drawing surface->finish(); + + if (_preview_emf_image) { + HENHMETAFILE hemf = MyGetEnhMetaFileW(_path_string); + if (hemf) { + RECT rc; + rc.top = svgY+2; + rc.left = svgX+2; + rc.bottom = scaledSvgHeight-2; + rc.right = scaledSvgWidth-2; + PlayEnhMetaFile(hMemDC, hemf, &rc); + DeleteEnhMetaFile(hemf); + } + } + SelectObject(hMemDC, hOldBitmap) ; DeleteDC(hMemDC); @@ -1194,7 +1385,7 @@ bool FileOpenDialogImplWin32::show() { // We can only run one worker thread at a time - //if(_mutex != NULL) return false; + if(_mutex != NULL) return false; if(!Glib::thread_supported()) Glib::thread_init(); @@ -1225,7 +1416,6 @@ FileOpenDialogImplWin32::show() Sleep(10); } - //g_main_loop_run(_main_loop); } // Tidy up @@ -1260,8 +1450,6 @@ FileSaveDialogImplWin32::FileSaveDialogImplWin32(Gtk::Window &parent, const Glib::ustring &/*default_key*/) : FileDialogBaseWin32(parent, dir, title, fileTypes, "dialogs.save_as") { - _main_loop = NULL; - createFilterMenu(); } @@ -1281,7 +1469,7 @@ void FileSaveDialogImplWin32::createFilterMenu() Inkscape::Extension::db.get_output_list(extension_list); int filter_count = 0; - int filter_length = 0; + int filter_length = 1; for (Inkscape::Extension::DB::OutputList::iterator current_item = extension_list.begin(); current_item != extension_list.end(); current_item++) @@ -1301,7 +1489,7 @@ void FileSaveDialogImplWin32::createFilterMenu() // Type filter.name = g_utf8_to_utf16( - omod->get_filetypename(), -1, NULL, &filter.name_length, NULL); + _(omod->get_filetypename()), -1, NULL, &filter.name_length, NULL); filter.mod = omod; @@ -1322,14 +1510,14 @@ void FileSaveDialogImplWin32::createFilterMenu() { const Filter &filter = *filter_iterator; - memcpy(filterptr, filter.name, filter.name_length * 2); + wcsncpy(filterptr, (wchar_t*)filter.name, filter.name_length); filterptr += filter.name_length; g_free(filter.name); *(filterptr++) = L'\0'; *(filterptr++) = L'*'; - memcpy(filterptr, filter.filter, filter.filter_length * 2); + wcsncpy(filterptr, (wchar_t*)filter.filter, filter.filter_length); filterptr += filter.filter_length; g_free(filter.filter); @@ -1340,7 +1528,8 @@ void FileSaveDialogImplWin32::createFilterMenu() } *(filterptr++) = 0; - _filterIndex = 0; + _filter_count = extension_index; + _filter_index = 1; // A value of 1 selects the 1st filter - NOT the 2nd } void FileSaveDialogImplWin32::GetSaveFileName_thread() @@ -1348,11 +1537,11 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() OPENFILENAMEEXW ofn; g_assert(this != NULL); - //g_assert(_mutex != NULL); g_assert(_main_loop != NULL); - gunichar2* current_directory_string = g_utf8_to_utf16( - _current_directory.data(), -1, NULL, NULL, NULL); + WCHAR* current_directory_string = (WCHAR*)g_utf8_to_utf16( + _current_directory.data(), _current_directory.length(), + NULL, NULL, NULL); // Copy the selected file name, converting from UTF-8 to UTF-16 memset(_path_string, 0, sizeof(_path_string)); @@ -1366,28 +1555,24 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() ofn.hwndOwner = _ownerHwnd; ofn.lpstrFile = _path_string; ofn.nMaxFile = _MAX_PATH; - ofn.nFilterIndex = _filterIndex; + ofn.nFilterIndex = _filter_index; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = (wchar_t*)current_directory_string; + ofn.lpstrInitialDir = current_directory_string; ofn.lpstrTitle = _title; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrFilter = _filter; - ofn.nFilterIndex = _filterIndex; + ofn.nFilterIndex = _filter_index; _result = GetSaveFileNameW(&ofn) != 0; - _filterIndex = ofn.nFilterIndex; - _extension = _extension_map[ofn.nFilterIndex]; + g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); + _filter_index = ofn.nFilterIndex; + _extension = _extension_map[ofn.nFilterIndex - 1]; // Copy the selected file name, converting from UTF-16 to UTF-8 myFilename = utf16_to_ustring(_path_string, _MAX_PATH); - //_mutex->lock(); - //_finished = true; - //_mutex->unlock(); - - // Tidy up g_free(current_directory_string); @@ -1400,40 +1585,21 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() bool FileSaveDialogImplWin32::show() { - // We can only run one worker thread at a time - //if(_mutex != NULL) return false; - if(!Glib::thread_supported()) Glib::thread_init(); _result = false; - //_finished = false; - //_mutex = new Glib::Mutex(); _main_loop = g_main_loop_new(g_main_context_default(), FALSE); - - if(Glib::Thread::create(sigc::mem_fun(*this, &FileSaveDialogImplWin32::GetSaveFileName_thread), true)) - { - /*while(1) - { - // While the dialog runs - keep the main UI alive - g_main_context_iteration(g_main_context_default(), FALSE); - - if(_mutex->trylock()) - { - if(_finished) break; - _mutex->unlock(); - } - - Sleep(10); - }*/ - g_main_loop_run(_main_loop); - } - //delete _mutex; - //_mutex = NULL; - - if(_result) - appendExtension(myFilename, (Inkscape::Extension::Output*)_extension); - + + if(_main_loop != NULL) + { + if(Glib::Thread::create(sigc::mem_fun(*this, &FileSaveDialogImplWin32::GetSaveFileName_thread), true)) + g_main_loop_run(_main_loop); + + if(_result) + appendExtension(myFilename, (Inkscape::Extension::Output*)_extension); + } + return _result; }