[Bf-blender-cvs] [3c533be] master: Fix T49112: Alembic unicode path issues on Windows.

Kévin Dietrich noreply at git.blender.org
Thu Aug 25 05:19:51 CEST 2016


Commit: 3c533be77ea8f6c88b188eb870bb46ba972d1372
Author: Kévin Dietrich
Date:   Thu Aug 25 05:19:41 2016 +0200
Branches: master
https://developer.blender.org/rB3c533be77ea8f6c88b188eb870bb46ba972d1372

Fix T49112: Alembic unicode path issues on Windows.

Now we pass streams to Alembic instead of passing the filename string.
That way we can open the stream ourselves with the proper unicode
encoding.

Note that this only applies to Ogawa archive, as HDF5 does not support
streams.

Differential Revision: https://developer.blender.org/D2160

===================================================================

M	source/blender/alembic/CMakeLists.txt
M	source/blender/alembic/intern/abc_exporter.cc
M	source/blender/alembic/intern/abc_exporter.h
M	source/blender/alembic/intern/alembic_capi.cc

===================================================================

diff --git a/source/blender/alembic/CMakeLists.txt b/source/blender/alembic/CMakeLists.txt
index 42bd6a9..0b6b243 100644
--- a/source/blender/alembic/CMakeLists.txt
+++ b/source/blender/alembic/CMakeLists.txt
@@ -33,6 +33,7 @@ set(INC
 	../makesrna
 	../windowmanager
 	../../../intern/guardedalloc
+	../../../intern/utfconv
 )
 
 set(INC_SYS
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 2e9f429..764b153 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -30,6 +30,10 @@
 
 #include <Alembic/AbcCoreOgawa/All.h>
 
+#ifdef WIN32
+#  include "utfconv.h"
+#endif
+
 #include "abc_camera.h"
 #include "abc_curves.h"
 #include "abc_hair.h"
@@ -67,6 +71,54 @@ extern "C" {
 using Alembic::Abc::TimeSamplingPtr;
 using Alembic::Abc::OBox3dProperty;
 
+
+/* ************************************************************************** */
+
+/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to
+ * have a version supporting streams. */
+static Alembic::Abc::OArchive create_archive(std::ostream *ostream,
+                                             const std::string &filename,
+                                             const std::string &scene_name,
+                                             const Alembic::Abc::Argument &arg0,
+                                             const Alembic::Abc::Argument &arg1,
+                                             bool ogawa)
+{
+    Alembic::Abc::MetaData md = GetMetaData(arg0, arg1);
+    md.set(Alembic::Abc::kApplicationNameKey, "Blender");
+	md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
+
+    time_t raw_time;
+    time(&raw_time);
+    char buffer[128];
+
+#if defined _WIN32 || defined _WIN64
+    ctime_s(buffer, 128, &raw_time);
+#else
+    ctime_r(&raw_time, buffer);
+#endif
+
+    const std::size_t buffer_len = strlen(buffer);
+    if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
+        buffer[buffer_len - 1] = '\0';
+    }
+
+    md.set(Alembic::Abc::kDateWrittenKey, buffer);
+
+	Alembic::Abc::ErrorHandler::Policy policy = GetErrorHandlerPolicyFromArgs(arg0, arg1);
+
+#ifdef WITH_ALEMBIC_HDF5
+	if (!ogawa) {
+		return Alembic::Abc::OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy);
+	}
+#else
+	static_cast<void>(filename);
+	static_cast<void>(ogawa);
+#endif
+
+	Alembic::AbcCoreOgawa::WriteArchive archive_writer;
+	return Alembic::Abc::OArchive(archive_writer(ostream, md), Alembic::Abc::kWrapExisting, policy);
+}
+
 /* ************************************************************************** */
 
 ExportSettings::ExportSettings()
@@ -247,26 +299,25 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
 
 	Alembic::Abc::Argument arg(md);
 
-#ifdef WITH_ALEMBIC_HDF5
-	if (!m_settings.export_ogawa) {
-		m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreHDF5::WriteArchive(),
-		                                                m_filename,
-		                                                "Blender",
-		                                                scene_name,
-		                                                Alembic::Abc::ErrorHandler::kThrowPolicy,
-		                                                arg);
-	}
-	else
+	/* Use stream to support unicode character paths on Windows. */
+	if (m_settings.export_ogawa) {
+#ifdef WIN32
+		UTF16_ENCODE(m_filename);
+		std::wstring wstr(m_filename_16);
+		m_out_file.open(wstr.c_str(), std::ios::out | std::ios::binary);
+		UTF16_UN_ENCODE(m_filename);
+#else
+		m_out_file.open(m_filename, std::ios::out | std::ios::binary);
 #endif
-	{
-		m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreOgawa::WriteArchive(),
-		                                                m_filename,
-		                                                "Blender",
-		                                                scene_name,
-		                                                Alembic::Abc::ErrorHandler::kThrowPolicy,
-		                                                arg);
 	}
 
+	m_archive = create_archive(&m_out_file,
+	                           m_filename,
+	                           scene_name,
+	                           Alembic::Abc::ErrorHandler::kThrowPolicy,
+	                           arg,
+	                           m_settings.export_ogawa);
+
 	/* Create time samplings for transforms and shapes. */
 
 	TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform);
diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h
index 070eb9e..6c242f9 100644
--- a/source/blender/alembic/intern/abc_exporter.h
+++ b/source/blender/alembic/intern/abc_exporter.h
@@ -24,6 +24,7 @@
 #define __ABC_EXPORTER_H__
 
 #include <Alembic/Abc/All.h>
+#include <fstream>
 #include <map>
 #include <set>
 #include <vector>
@@ -75,6 +76,7 @@ class AbcExporter {
 
 	const char *m_filename;
 
+	std::ofstream m_out_file;
 	Alembic::Abc::OArchive m_archive;
 	unsigned int m_trans_sampling_index, m_shape_sampling_index;
 
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index f42c708..d057cc3 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -29,6 +29,12 @@
 #include <Alembic/AbcCoreOgawa/All.h>
 #include <Alembic/AbcMaterial/IMaterial.h>
 
+#include <fstream>
+
+#ifdef WIN32
+#  include "utfconv.h"
+#endif
+
 #include "abc_camera.h"
 #include "abc_curves.h"
 #include "abc_hair.h"
@@ -109,49 +115,97 @@ using Alembic::AbcGeom::V3fArraySamplePtr;
 
 using Alembic::AbcMaterial::IMaterial;
 
-struct AbcArchiveHandle {
-	int unused;
-};
-
-ABC_INLINE IArchive *archive_from_handle(AbcArchiveHandle *handle)
-{
-	return reinterpret_cast<IArchive *>(handle);
-}
-
-ABC_INLINE AbcArchiveHandle *handle_from_archive(IArchive *archive)
+static IArchive open_archive(const std::string &filename,
+                             const std::vector<std::istream *> &input_streams,
+                             bool &is_hdf5)
 {
-	return reinterpret_cast<AbcArchiveHandle *>(archive);
-}
-
-static IArchive *open_archive(const std::string &filename)
-{
-	Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr;
-	IArchive *archive;
-
 	try {
-		archive = new IArchive(Alembic::AbcCoreOgawa::ReadArchive(),
-		                       filename.c_str(), ErrorHandler::kThrowPolicy,
-		                       cache_ptr);
+		is_hdf5 = false;
+		Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams);
+
+		return IArchive(archive_reader(filename),
+		                kWrapExisting,
+		                ErrorHandler::kThrowPolicy);
 	}
 	catch (const Exception &e) {
 		std::cerr << e.what() << '\n';
 
 #ifdef WITH_ALEMBIC_HDF5
 		try {
-			archive = new IArchive(Alembic::AbcCoreHDF5::ReadArchive(),
-			                       filename.c_str(), ErrorHandler::kThrowPolicy,
-			                       cache_ptr);
+			is_hdf5 = true;
+			Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr;
+
+			return IArchive(Alembic::AbcCoreHDF5::ReadArchive(),
+			                filename.c_str(), ErrorHandler::kThrowPolicy,
+			                cache_ptr);
 		}
 		catch (const Exception &) {
 			std::cerr << e.what() << '\n';
-			return NULL;
+			return IArchive();
 		}
 #else
-		return NULL;
+		return IArchive();
 #endif
 	}
 
-	return archive;
+	return IArchive();
+}
+
+/* Wrapper around an archive to be able to use streams so that unicode paths
+ * work on Windows (T49112), and to make sure the input stream remains valid as
+ * long as the archive is open. */
+class ArchiveWrapper {
+	IArchive m_archive;
+	std::ifstream m_infile;
+	std::vector<std::istream *> m_streams;
+
+public:
+	explicit ArchiveWrapper(const char *filename)
+	{
+#ifdef WIN32
+		UTF16_ENCODE(filename);
+		std::wstring wstr(filename_16);
+		m_infile.open(wstr.c_str(), std::ios::in | std::ios::binary);
+		UTF16_UN_ENCODE(filename);
+#else
+		m_infile.open(filename, std::ios::in | std::ios::binary);
+#endif
+
+		m_streams.push_back(&m_infile);
+
+		bool is_hdf5;
+		m_archive = open_archive(filename, m_streams, is_hdf5);
+
+		/* We can't open an HDF5 file from a stream, so close it. */
+		if (is_hdf5) {
+			m_infile.close();
+			m_streams.clear();
+		}
+	}
+
+	bool valid() const
+	{
+		return m_archive.valid();
+	}
+
+	IObject getTop()
+	{
+		return m_archive.getTop();
+	}
+};
+
+struct AbcArchiveHandle {
+	int unused;
+};
+
+ABC_INLINE ArchiveWrapper *archive_from_handle(AbcArchiveHandle *handle)
+{
+	return reinterpret_cast<ArchiveWrapper *>(handle);
+}
+
+ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveWrapper *archive)
+{
+	return reinterpret_cast<AbcArchiveHandle *>(archive);
 }
 
 //#define USE_NURBS
@@ -247,9 +301,10 @@ static void gather_objects_paths(const IObject &object, ListBase *object_paths)
 
 AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths)
 {
-	IArchive *archive = open_archive(filename);
+	ArchiveWrapper *archive = new ArchiveWrapper(filename);
 
-	if (!archive) {
+	if (!archive->valid()) {
+		delete archive;
 		return NULL;
 	}
 
@@ -582,12 +637,10 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
 	data->do_update = do_update;
 	data->progress = progress;
 
-	IArchive *archive = open_archive(data->filename);
+	ArchiveWrapper *archive = new ArchiveWrapper(data->filename);
 
-	if (!archive || !archive->valid()) {
-		if (archive) {
-			delete archive;
-		}
+	if (!archive->valid()) {
+		delete archive;
 		data->error_code = ABC_ARCHIVE_FAIL;
 		return;
 	}
@@ -812,7 +865,7 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
 
 void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_path, float r_mat[4][4], float time, float scale)
 {
-	IArchive *archive = archive_from_handle(handle);
+	ArchiveWrapper *archive = archive_from_handle(handle);
 
 	if (!archive || !archive->valid()) {
 		return;
@@ -1088,7 +1141,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle,
                            const char **err_str,
                

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list