Due to little-endian/big-endian differences, winelib on Sparc can't read windows metafiles generated on a PC (or on Wine on x86), and conversely PCs can't read metafiles created on a Sparc. It looks like there are a few ways this could be fixed, and I wanted to make sure we don't go about it the wrong way (and that nobody else is working on it).
I think the right thing to do is make the on-disk and in-memory formats always be little-endian. We would only convert the data to big-endian format when it is generated or used. GetMetaFileBitsEx and SetMetaFileBitsEx would return & take the raw data in little-endian format.
The implementation we're considering involves: - in PlayMetaFileRecord(), convert endianness of paramters as they're used: LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); becomes LineTo(hdc, (SHORT)convert_word_from_little_endian(mr->rdParm[1]), (SHORT)convert_word_from_little_endian(mr->rdParm[0])); - in MFDRV_MetaParam2(), convert endianness *(mr->rdParm) = param2; becomes *(mr->rdParm) = convert_word_to_little_endian(param2); - some similar conversions necessary for anything that reads/writes the header - anything that calls MFDRV_WriteRecord() would need special handling. These seem to be the functions that embed bitmaps or text in the METARECORD, so we'll have to be selective about what gets converted and what gets written as-is.
Is this the right way to go about fixing the problem? Anything we should look out for?
Thanks, Eric
On Thu, 13 Apr 2006 11:58:02 -0400 Eric Frias efrias@syncad.com wrote:
Due to little-endian/big-endian differences, winelib on Sparc can't read windows metafiles generated on a PC (or on Wine on x86), and conversely PCs can't read metafiles created on a Sparc. It looks like there are a few ways this could be fixed, and I wanted to make sure we don't go about it the wrong way (and that nobody else is working on it).
I think the right thing to do is make the on-disk and in-memory formats always be little-endian. We would only convert the data to big-endian format when it is generated or used. GetMetaFileBitsEx and SetMetaFileBitsEx would return & take the raw data in little-endian format.
I have submitted a patch that fixes creation of on-disk _enhanced_ metafiles a few days ago:
http://article.gmane.org/gmane.comp.emulators.wine.patches/23393
It byteswaps EMF records just for writing to disk. Adding byteswapping for reading from disk seems very easy - just feed the file content to the same byteswapper functions. I think it is a bit more clean than your approach.
-- Ph.
On Thu, 13 Apr 2006 22:39:57 +0400 Phil Krylov phil@newstar.rinet.ru wrote:
It byteswaps EMF records just for writing to disk. Adding byteswapping for reading from disk seems very easy - just feed the file content to the same byteswapper functions. I think it is a bit more clean
should be: to the same byteswapper function.
than your approach.
-- Ph.
Phil Krylov wrote:
I have submitted a patch that fixes creation of on-disk _enhanced_ metafiles a few days ago:
http://article.gmane.org/gmane.comp.emulators.wine.patches/23393
Thanks for the pointer, I hadn't seen that patch.
It byteswaps EMF records just for writing to disk. Adding byteswapping for reading from disk seems very easy - just feed the file content to the same byteswapper functions. I think it is a bit more clean than your approach.
I like how yours works -- one function call converts both directions. My only hesitation was that all of the operations -- read, copy, get bits & set bits -- change from simple writes of a block of memory to looping through the records one-by-one to convert them. That's not a bad price to pay for cleaner code...
Here's a question that I guess is worth asking: what kind of data do you expect to get when you call GetMetaFileBitsEx()? Do you get bits in the in-memory format, where METARECORD structures have values in the native format? Or do you get data in the on-disk format? My first reaction was that you'd want the on-disk (platform-independent) format, because you would probably be writing the data to a file or to the clipboard, and you'd want that to be as platform-independent as the .wmf files are. But I was looking over the API and there are also functions like EnumMetaFile() and PlayMetaFileRecord() that give or take one METARECORD, and that suggests that there are programs out there that try to make sense of the data in the individual records and that you'd expect to see native byte order used.
Like you, my immediate problem is just getting wine to write out metafiles that the rest of the world can read. But as soon as I change the file writing, I feel like I should change the reading function to be consistent, and then it starts to get a bit confusing.
Eric
On Thu, 13 Apr 2006 16:39:02 -0400 Eric Frias efrias@syncad.com wrote:
Phil Krylov wrote:
I have submitted a patch that fixes creation of on-disk _enhanced_ metafiles a few days ago:
http://article.gmane.org/gmane.comp.emulators.wine.patches/23393
Thanks for the pointer, I hadn't seen that patch.
It byteswaps EMF records just for writing to disk. Adding byteswapping for reading from disk seems very easy - just feed the file content to the same byteswapper functions. I think it is a bit more clean than your approach.
I like how yours works -- one function call converts both directions. My only hesitation was that all of the operations -- read, copy, get bits & set bits -- change from simple writes of a block of memory to looping through the records one-by-one to convert them. That's not a bad price to pay for cleaner code...
We have to do this conversion one place or another, and I supposed that reading/writing metafile from disk is used less frequently than other metafile operations (mostly record addition and playback).
Here's a question that I guess is worth asking: what kind of data do you expect to get when you call GetMetaFileBitsEx()? Do you get bits in the in-memory format, where METARECORD structures have values in the native format? Or do you get data in the on-disk format? My first reaction was that you'd want the on-disk (platform-independent) format, because you would probably be writing the data to a file or to the clipboard, and you'd want that to be as platform-independent as the .wmf files are. But I was looking over the API and there are also functions like EnumMetaFile() and PlayMetaFileRecord() that give or take one METARECORD, and that suggests that there are programs out there that try to make sense of the data in the individual records and that you'd expect to see native byte order used.
Like you, my immediate problem is just getting wine to write out metafiles that the rest of the world can read. But as soon as I change the file writing, I feel like I should change the reading function to be consistent, and then it starts to get a bit confusing.
Yes it really does...
However, I don't think there are a lot of programs using these APIs... I mean, let's implement it one or another way and wait till some such programs break (when ported to big-endian machines;) and see how exactly they will break and fix it then.
Also, when we're dealing with WineLib, we can just document the endianness-behaviour of these functions and developers can do byteswapping in their apps where needed or use other APIs (e.g. CopyEnhMetaFile instead of GetEnhMetaFileBits followed by a disk write).
-- Ph.
Phil Krylov wrote:
However, I don't think there are a lot of programs using these APIs... I mean, let's implement it one or another way and wait till some such programs break (when ported to big-endian machines;) and see how exactly they will break and fix it then.
True... and probably even less programs use WMF than EMF. If there's no existing plan for how to make this stuff work, the fix-things-as-they-break approach is fine with me. I'll keep an eye on your patch; if it gets accepted, we'll do something analogous for the regular metafiles. Thanks for the input.
Eric