Created attachment 124721 [details]
Screen showing the low dpi for rendered image
I have been investigating why certain EMF files containing text are rendered at a low resolution in LibreOffice Draw when printing or magnified(zoom) to 400%
For example: Attached libre.png (using attached Template.emf )
Note, this example file does display correctly by setting the "EMF_PLUS_DISABLE" environment variable.
This is because the "Template.emf" "EMF" records contains the text drawing, and the "EMF+" records do not display anything important.
Of course, ideally we should not need to set this environment variable
If "EMF+" is detected in EnhWMFReader::ReadEnhWMF(), then a different code path is used and the "EMF" is rendered to a bitmap at the incorrect DPI, then drawn to the screen.
So when "EMF_PLUS_DISABLE" is set:
At https://cgit.freedesktop.org/libreoffice/core/tree/vcl/source/filter/wmf/enhwmf.cxx#n621 EnhWMFReader::ReadEnhWMF() Renders the EMF directly to WinMtfOutput (pOut), and ignores EMF+
When "EMF_PLUS_DISABLE" is not set:
At https://cgit.freedesktop.org/libreoffice/core/tree/vcl/source/filter/wmf/enhwmf.cxx#n621 EnhWMFReader::ReadEnhWMF() Detects EMF+ using the signature in EMR_GDICOMMENT (the value 0x2B464D45, which is the ASCII string "+FME)
If detected, this is where it gets complex.
EnhWMFReader::ReadEnhWMF() only processes EMR_GDICOMMENT's (i.e. No longer does any drawing)
1. Creates a header MetaCommentAction( "EMF_PLUS_HEADER_INFO" )
2. Creates the body MetaCommentAction( "EMF_PLUS" )
The drawing layer eventually calls GDIMetaFile::Play and creates a bitmap to render to in GDIMetaFile::ImplPlayWithRenderer() https://cgit.freedesktop.org/libreoffice/core/tree/vcl/source/gdi/gdimtf.cxx#n383
This leads to ImplRenderer::processEMFPlus() ( https://cgit.freedesktop.org/libreoffice/core/tree/cppcanvas/source/mtfrenderer/emfplus.cxx#n1811 ) Which processes the EMF+ commands Notice, this code is in cppcanvas (not vcl)
Still within GDIMetaFile::Play, EnhWMFReader::ReadEnhWMF() is called. The EMF still may contain nested EMF+ data (treated as above). When no EMF+ data exists, the standard EMF is drawn.
I am confused why we do it this way. There must have been a reason place the EMF+ code in cppcanvas (i.e. not alongside the EMF). I cannot understand why each layer is drawn to a different bitmap (also why it's the incorrect DPI)
There is a lot of good code there, and probably fragile. imho, it's risky moving EMF+ out of cppcanvas, and not something that I would want to attempt.
The easy fix would be to fix the DPI setting, however I cannot find where the error is.
Created attachment 124722 [details]
The example emf+ file that can be used to replicate the error
Arch Linux 64-bit, KDE Plasma 5
Build ID: 540fee2dc7553152914f7f1d8a41921e765087ef
CPU Threads: 8; OS Version: Linux 4.5; UI Render: default;
Locale: fi-FI (fi_FI.UTF-8)
Built on April 30th 2016
This bug can be explained by the comments in vcl/README
Look at the "== EMF+ ==" section
I am looking into updating the WMF/EMF code
Setting Assignee back to default. Please assign it back to yourself if you're still working on this issue
Unfortunately, due to work commitments I have not had time to work on this. Sorry for not mentioning this earlier.
Not fixed with new EMF+. This looks like WMF file to me.
Hi, I can confirm this bug is fixed in current master with commit
"tdf#31814 Fix for EMF+ DrawString and DrawImage"
The text is stored in a "DrawImage" record which was rendered as a Bitmap. This is fixed now: It is rendered as a VectorGraphic (Metafile) and therefore rendered in high resolution!
Build ID: 5ea1b4c336d1cad92dc18e7cf7e4b381396f448b
CPU threads: 4; OS: Linux 4.10; UI render: default; VCL: gtk3;
Locale: ca-ES (ca_ES.UTF-8); Calc: group