tdf#81880 Search the Gallery
[LibreOffice.git] / vcl / README.md
blobc6e436aa482ecfcd03260e82b6e22c9f8e8ae4e6
1 # Visual Class Library (VCL)
3 Visual Class Library (VCL) is responsible for the widgets (windowing, buttons, controls,
4 file-pickers etc.), operating system abstraction, including basic rendering (e.g. the output device).
6 It should not be confused with Borland's Visual Component Library, which is entirely unrelated.
8 VCL provides a graphical toolkit similar to gtk+, Qt, SWING etc.
10 + source/
11         + the main cross-platform chunk of source
13 + inc/
14         + cross-platform abstraction headers
16 + headless/
17         + a backend renderer that draws to bitmaps
19 + android/
20         + Android backend
22 + osx/
23         + macOS backend
25 + ios/
26         + iOS backend
28 + quartz/
29         + code common to macOS and iOS
31 + win/
32         + Windows backend
34 + qt5/
35         + Qt5
37 + qt6/
38         + Qt6
40 + unx/
41         + X11 backend and its sub-platforms
42                 + gtk3/
43                         + GTK3 support
44                 + gtk4/
45                         + GTK4 support (experimental)
46                 + kf5/
47                         + KF5 support (based on qt5 VCL plugin mentioned above)
48                 + kf6
49                         + KF6 support (based on qt6 VCL plugin mentioned above)
50                 + gtk3_kde5/
51                         + GTK3 support with KDE5 file pickers (alternative to native kf5 one)
52                 + generic/
53                         + raw X11 support
55                 + dtrans/
56                         + "data transfer" - clipboard handling
57                         + http://stackoverflow.com/questions/3261379/getting-html-source-or-rich-text-from-the-x-clipboard
58                           for tips how to show the current content of the
59                           clipboard
62 + How the platform abstraction works
64         + InitVCL calls 'CreateSalInstance'
65                 + this is implemented by the compiled platform backends
66         + the SalInstance vtable is the primary outward facing gateway
67           API for platform backends
68                 + It is a factory for:
69                   SalFrames, SalVirtualDevices, SalPrinters,
70                   Timers, the SolarMutex, Drag&Drop and other
71                   objects, as well as the primary event loop wrapper.
73 Note: references to "SV" in the code mean StarView, which was a
74 portable C++ class library for GUIs, with very old roots, that was
75 developed by StarDivision. Nowadays it is not used by anything except
76 LibreOffice (and OpenOffice).
78 "svp" stands for "StarView Plugin".
80 ## SalData implementations
82 Each backend must provide an implementation of the SalData class. There is no
83 defined interface, so feel free to implement whatever suits your platform.
85 If your platform does font handling based on Freetype and Fontconfig, it's
86 highly recommended to use GenericUnixSalData as the base class; there isn't
87 really much *nix stuff in it.
89 Currently Windows, iOS and MacOSX have independent SalData implementations.
91 ## COM Threading
93 The way COM is used in LO generally:
94 - vcl puts main thread into Single-threaded Apartment (STA)
95 - oslWorkerWrapperFunction() puts every thread spawned via `oslCreateThread()`
96   into MTA (free-threaded)
98 ## GDIMetafile
100 GDIMetafile is a vector drawing representation that corresponds directly
101 to the SVM (StarView Metafile) format; it is extremely important as
102 an intermediate format in all sorts of drawing and printing operations.
104 There is a class `MetafileXmlDump` in `include/vcl/mtfxmldump.hxx` that
105 can store a GDIMetafile as XML, which makes debugging much easier
106 since you can just use "diff" to see changes.
108 ## EMF+
110 emf+ is vector file format used by MSO and is successor of wmf and
111 emf formats. see
112 http://msdn.microsoft.com/en-us/library/cc230724.aspx for
113 documentation. note that we didn't have this documentation from
114 start, so part of the code predates to the time when we had guessed
115 some parts and can be enhanced today. there also still many thing not
116 complete
118 emf+ is handled a bit differently compared to original emf/wmf files,
119 because GDIMetafile is missing features we need (mostly related to
120 transparency, argb colors, etc.)
122 emf/wmf is translated to GDIMetafile in import filter
123 `vcl/source/filter/wmf` and so special handling ends here
125 emf+ is encapsulated into GDIMetafile inside comment records and
126 parsed/rendered later, when it reaches cppcanvas. It is parsed and
127 rendered in cppcanvas/source/mtfrenderer. also note that there are
128 emf+-only and emf+-dual files. dual files contains both types of
129 records (emf and emf+) for rendering the images. these can used also
130 in applications which don't know emf+. in that case we must ignore
131 emf records and use emf+ for rendering. for more details see
132 the documentation.
134 ## Parsing
136  wmf/emf filter --> GDI metafile with emf+ in comments --> cppcanvas metafile renderer
138 lately the GDIMetafile rendering path changed which also influenced
139 emf+ rendering. now many things happen in drawing layer, where
140 GDIMetafile is translated into drawing layer primitives. for
141 metafiles with emf+ we let the mtfrenderer render them into bitmap
142 (with transparency) and use this bitmap in drawinlayer. cleaner
143 solution for current state would be to extend the drawing layer for
144 missing features and move parsing into drawing layer (might be quite
145 a lot of work). intermediary enhancement would be to know better the
146 needed size/resolution of the bitmap, before we render emf+ into
147 bitmap in drawing layer. Thorsten is working on the same problem with
148 svg rendering, so hopefully his approach could be extended for emf+ as
149 well. the places in drawing layer where we use canvas mtfrenderer to
150 render into bitmaps can be found when you grep for GetUseCanvas. also
151 look at vcl/source/gdi/gdimetafile.cxx where you can look for
152 UseCanvas again. moving the parsing into drawinglayer might also have
153 nice side effect for emf+-dual metafiles. in case the emf+ records
154 are broken, it would be easier to use the duplicit emf
155 rendering. fortunately we didn't run into such a broken emf+ file
156 yet. but there were already few cases where we first though that the
157 problem might be because of broken emf+ part. so far it always turned
158 out to be another problem.
160 ## Rendering
162  before
164  vcl --> cppcanvas metafile renderer --> vcl
166  now
168  drawing layer --> vcl --> cppcanvas metafile renderer --> vcl --> drawing layer
170 another interesting part is actual rendering into canvas bitmap and
171 using that bitmap later in code using vcl API.
173 EMF+ implementation has some extensive logging, best if you do a dbgutil
174 build, and then
176     export SAL_LOG=+INFO.cppcanvas.emf+INFO.vcl.emf
178 before running LibreOffice; it will give you lots of useful hints.
180 You can also fallback to EMF (from EMF+) rendering via
182     export EMF_PLUS_DISABLE=1
185 ## Printing/PDF Export
187 Printing from Writer works like this:
189 1) individual pages print by passing an appropriate OutputDevice to XRenderable
190 2) in drawinglayer, a VclMetafileProcessor2D is used to record everything on
191    the page (because the OutputDevice has been set up to record a GDIMetaFile)
192 3) the pages' GDIMetaFiles are converted to PDF by the vcl::PDFWriter
193    in `vcl/source/gdi/pdfwriter*`
195 Creating the ODF thumbnail for the first page works as above except step 3 is:
197 3) the GDIMetaFile is replayed to create the thumbnail
199 On-screen display differs in step 1 and 2:
201 1) the VCL Window gets invalidated somehow and paints itself
202 2) in drawinglayer, a `VclPixelProcessor2D` is used to display the content
205 ### Debugging PDF export
207 Debugging the PDF export becomes much easier when
208 compression is disabled (so the PDF file is directly readable) and
209 the MARK function puts comments into the PDF file about which method
210 generated the following PDF content.
212 The compression can be disabled even using an env. var:
214     export VCL_DEBUG_DISABLE_PDFCOMPRESSION=1
216 To de-compress the contents of a PDF file written by a release build or
217 other programs, use the "pdfunzip" tool:
219     bin/run pdfunzip input.pdf output.pdf
221 ### SolarMutexGuard
223 The solar mutex is the "big kernel lock" of LibreOffice, a global one. It's a
224 recursive mutex, so it's allowed to take the lock on the same thread multiple
225 times, and only the last unlock will actually release the mutex.
227 UNO methods on components can be called from multiple threads, while the
228 majority of the codebase is not prepared for multi-threading. One way to get
229 around this mismatch is to create a SolarMutexGuard instance at the start of
230 each & every UNO method implementation, but only when it is necessary:
232 - Only acquire the SolarMutex if you actually need it (e.g., not in functions
233   that return static information).
235 - Only around the code that actually needs it (i.e., never call out with it
236   locked).
238 This way you ensure that code (not prepared for multithreading) is still
239 executed only on a single thread.
241 In case you expect that your caller takes the solar mutex, then you can use
242 the `DBG_TESTSOLARMUTEX()` macro to assert that in dbgutil builds.
244 Event listeners are a special (but frequent) case of the "never call out with
245 a mutex (`SolarMutex` or other) locked" fundamental rule:
247 - UNO methods can be called from multiple threads, so most implementations
248   take the solar mutex as their first action when necessary.
250 - This can be problematic if later calling out (an event handler is called),
251   where the called function may be an UNO method implementation as well and
252   may be invoked on a different thread.
254 - So we try to not own the solar mutex, whenever we call out (invoke event
255   listeners).
257 In short, never hold any mutex unless necessary, especially not when calling
258 out.
260 ## Read More
261 * [Environment variables in VCL](README.vars.md)
262 * [GDIMetaFile class](README.GDIMetaFile.md)
263 * [Understanding transitional VCL lifecycle](README.lifecycle.md)
264 * [VCL scheduler](README.scheduler.md)