Apache OpenOffice (AOO) Bugzilla – Issue 100373
Textshapes in Metafiles render wrong if systems have different fonts
Last modified: 2009-04-21 11:38:16 UTC
Load the attached document on a windows system. You can see that the font of several texts look broken: 'Fruits, Apple, Banana, Ananas, a text shape in a Writer OLE'. All those are text shapes within an OLE object. For the OLE objects meta files are created on save and displayed on load. The file was create on Linux with OOO310m6. Same problem exists also if the file is created on Solaris. Activating the OLE object and refreshing the metafile creates a correct display on windows. So there seems to be missing some information within the meta file when they are saved on unix.
Created attachment 61054 [details] exmple showing the problem
pl->hw,hdu: could you please have a look ?
AW->HDU: All of this happens in VCL and has to do with fonts, Primitives are not involved when plyaing a MetaFile. Please have a look.
The problem is a combination of 1. the stupid legacy concept of a "font's average charwidth", which could almost be considered to be a font-specific random number 2. OLE previews seem to export any font-stretching not by a font-stretch factor (e.g. 120%), but by the font-specific random number multiplied by that stretching factor (e.g. NimbusL.avgcharwidth*120%) 3. different platforms have different fonts. E.g. NimbusSansL which is often available on Unix systems is rarely available on Mac or Windows), so the random font-specific numbers would not match. The font- stretch-factor as the ratio of the written-avgcharwidth and the usedfont-avgcharwidth would be off by the difference of the font-specific random numbers. So the central root cause is item 2: don't depend on arithmetic with random numbers if you need consistent results. The solution would be easy by explicitly writing out the font-stretch-factor instead of the bogus stretchfactor*random value, but this has problems with backwards compatibility. @iha,aw.sj: For unstretched fonts such as in the attached document the solution would be quite easy though: just request the "default-font-width" for unstretched fonts during the metafile export! The "regression" probably comes from the fact, that the new drawing layer is much more accurate and so even factors of 100.0001% get the "stretched font treatment", which has the problem with random- numbers of the legacy metafiles outlined above. If the above suggestion (request default-width for is done then most of the problem is solved. The remainder of this issue would to extend the old metafile format to use font-stretch-factors instead of the insane multiplication product. Since the drawinglayer rework aims to replace the legacy metafiles by a much better approach based on drawing primitives (which on my advice avoid the random width number to calculate stretch factors) this remaining task to extend the legacy metafile will become redundant soon.
>@iha,aw.sj: For unstretched fonts such as in the attached document the solution >would be quite easy though: just request the "default-font-width" for >unstretched fonts during the metafile export! I see no way to easily do this. MetaFiles are recorded by using multiple calls to OutputDevice. At least it needs to be done in VCL then. >The "regression" probably comes >from the fact, that the new drawing layer is much more accurate and so >even factors of 100.0001% get the "stretched font treatment", which has the >problem with random-numbers of the legacy metafiles outlined above. No, for MetaFile replay, the primitives are not used, but still the VCL MetaFile Play command. Primitives are currently not involved in MetaFile replay. >If the above suggestion (request default-width for is done then most of the >problem is solved. The remainder of this issue would to extend the old >metafile format to use font-stretch-factors instead of the insane >multiplication product. Since the drawinglayer rework aims to replace the >legacy metafiles by a much better approach based on drawing primitives (which >on my advice avoid the random width number to calculate stretch factors) this >remaining task to extend the legacy metafile will become redundant soon. The primitive solution will in one of the next steps no longer use VCLs Play() command for MetaFiles, but interpret the MetaFile and change it to primitives, but this also requires the correct information in the MetaFiles themselves. Also, for OLE, only for own OLEs (Chart) it would be possible to change geometry transfer to primitives, so we will keep the MetaFile for OLEs for a long time. Thus i see no way around fixing this in the current MetaFile first. It will not be redundant, but necessary even for the future.
> I see no way to easily do this. MetaFiles are recorded by using multiple calls to OutputDevice. > At least it needs to be done in VCL then. If the layers above VCL cannot possibly remember that a font was intended to be unstretched then VCL could indeed try to guess that intention by using a heuristic and update the metafile on the fly while writing. This approach would be better than the current situation but not as good as getting the correct information. Reassigning the issue back to implement this second best solution, unless it show that the better solution I outlined in my other comment is not so difficult after all.
>If the layers above VCL cannot possibly remember that a font was intended to be >unstretched then VCL could indeed try to guess that intention by using a >heuristic and update the metafile on the fly while writing. The Layers above VCL are external Applications for OLE. I see no way how they should remember that. I also do not see how this should help when WE need to play the MetaFile. I also see no reason for guessing. Does the MetaFile action created when calling DrawText() not contain all necessary information to record the current text output and to replay it? If Yes, why is it going wrong? If not, this is a design error (maybe not in our MetaFile, but in mtf as file format (?). At least fo our MetaFiles we should somehow add that needed information to the MetaFiles then; maybe in a MetaFileComment, as we already do with other infos. This would at least solve the problem for MetaFiles we created ourselves (and would be backward compatible, too). Shouldn't that be the fix to do...?
> Does the MetaFile action created when calling DrawText() not contain all necessary information > to record the current text output and to replay it? No, as long as the font-specific random number is involved only the exactly same system and its relatives can replay it exactly. > If not, this is a design error (maybe not in our MetaFile, but in mtf as file format) Yes. The problem with fixing it is that the error is so old and got into binary files. Currently this part of metafiles cannot be replayed reliably. > At least fo our MetaFiles we should somehow add that needed information to the > MetaFiles then; maybe in a MetaFileComment, as we already do with other infos That's probably the best solution: It will improve the cross-system compatibility and not make things worse from a backwards compatibility aspect.
reassigning for now as discussed
AW: I will check some aspects and look for an easy solution, but i have to make clear that i'm not the MetaFile expert and only take over currently since HDU is on vacation. Taking a look...
AW: Annotation to the "regression" keyword and 'broken' Flag: This behaviour exists since we have MetaFiles on different systems, so this is in no way 3.1 specific, but exists in all former versions.
Perhaps the problem is old, but the effect in 3.1 is new. It isn't possible to share documents with OLE objects between UNIX and Windows anymore, because the font is broken on Windows systems. This wasn't in OOo 3.0.1 and older versions. As I wrote the consequence of this bug is worst in 3.1. I set this bug to 3.1 target and will announce it as showstopper, because it isn't possible anymore to share documents platform independently. This is broken in 3.1.
AW: I have a pretty simple, working fix which i checked in different scenarios. Basic problem is that the Fonts streamed to the MetaFiles when creating the OLE contents is slightly different for WIN32 nad other systems. On WIN32, the definition for not scaled fonts is that FontWidth == 0, while on all other systems this definition and Width == Height are allowed. This means that definitions when using them in WIN32 need to be either also interpreted using both definitions or to be corrected. When correcting the Font import (which is uded on MetaFile read) in font.cxx SvStream& operator>>( SvStream& rIStm, Impl_Font& rImpl_Font ) using #ifdef WIN32 // #i100373# handle font scaling for WIN32 // // When width and height are identical and we are on a windows system, // translate the width to zero to express that the font is not to be // scaled at all. The width == height definition was probably created // by another Linux- or Mac-based system, but will be interpreted // different on WIN32 systems, thus this correction on import is // necessary if(rImpl_Font.maSize.getWidth() == rImpl_Font.maSize.getHeight()) { rImpl_Font.maSize.setWidth(0); } #endif after the line rIStm >> rImpl_Font.maSize; this difference gets corrected and the visualisation works as expected. The advantage is that this solution does not change the current MetaFile format or it's creation, but only corrects the import, so all already written files will work. The better solution would be to have a unique definition for non-scaled fonts in WIN32 and all other systems. This means to interpret Width==Height as non-scaled on WIN32, too. It would be hard to ensure this, there may be several places in VCL involved (HDU would know). AW->PL: Do You see any caveats with such a solution? I checked WIN32- and Linux-created MetaFiles, viewed on WIN32 and Linux, all seems to work well.
AW->TZ: I loaded the bugdoc with a 3.0, and it looks exactly the same (wrong) as in a OOO310. I have not checked with a 3.0.1 yet. I do not mention this to state that we will not fix it (it should have been fixed in former versions already), but to show my surprise about the regression and broken flag usage here. Else i would have changed those flags.
AW: Oops, forgot to add PL to discussion...
@aw: depending on who else uses the stream operator this might invent some strange compatibility issues (e.g. I don't know how fonts came into the binary formats). Moreover: how do you distinguish the unstretched case from the case where the font is stretched and the stretched width matches the font height ?
=>AW: That is correct, that the attached file looks broken in 3.0 and 3.0.1. But you couldn't _create_ such broken files in 3.0 and 3.0.1. Therefore I do not know if it is correct to fix the import. Because the creation of such files is the problem. And when you fix the import in 3.1 you can create such broken files which looks ugly in versions lower than 3.1.
AW->TZ: That is a very (if not the) important hint. Thus the export did somehow change. For some reason width==height non-scaled Font definitions are now created in the MetaFiles. I will check for this now. AW->PL: I think noone else uses the stream operator. For the how do you distinguish question: You cannot. That's a problem with the existing definitions HDU is aware of (that whole area needs rework IMHO).
AW: Cheched MetaFile creation. In VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D a VCL Font is created by default using a width==height definition (as HDU suggested as better definition). This is corrected in the method actually for WIN32 to start with width==0 for internal use, but not for non-WIN32 systems. Thus, non-WIN32 systems will write MetaFiles containing the width==height non-font-scaling definition. When these are loaded on WIN32-system, we have a usage of a Font-definition not correct for the current system. This could be corrected by import, but not for existing offices. So it needs to be corrected (1) at font creation time, or (2) at MetaFile export time. (1) will fix the problem and use the 0==width definition for all systems, thus also creating the correct MetaFiles, but internally use the less good definition even for systems which support width==height (2) will guarantee compatible MetaFiles for all existing offices (3.0, etc.). It would need to be applied to all Font event exports where width==height in the font definition. Both will work, whereby (2) seems even to be more secure since the same MetaFile definitions as previously are forced to be created, independent from the MetaFile source. OTOH (1) works well and is closer on what the VCL-users (old DoPaintObject implementations) did. Mayne (1) and (2) should be done to ensure correct MetaFile creations even when (1) should be reworked/changed again internally.
AW: Experimented with (1) and (2), creating CWS aw068 for this task. I will use (1), also checked for streched text support on all systems and in-between systems using MetaFiles.
AW: Made and commented change in drawinglayer, builds running. Checked on unxlngi6.pro already, with streched text, too. Waiting for wntmsci12.pro version to re-check result.
AW: Done, fixed. All installsets here.
AW->MRU: To test, You need in principle create OLEs with a non-WIN32 version and load in the WIN32-version. Easiest way to do that: - Load BugDoc with non-WIN32 version (e.g. unxlngi6.pro) - Activate all OLEs once, evtl. add streched tex shape - save with another name - load new doc with WIN32 installation -> looks good now. Formally all fonts in OLEs were streched wrongly.
Verified in CWS aw068.
Checked in OOO310m10.