office-gobmx/vcl
Caolán McNamara 4557bd79fe merge duplicate CairoTextRender impls
drop getSurfaceOffset because both impls just set these to 0, so its
a no opt

Change-Id: Ie4f28d57fb8a170c7a46d3cafceef3e049c26e2f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145325
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2023-01-12 11:33:24 +00:00
..
android Revert "svp: don't directly yield in main thread" 2022-06-23 07:55:06 +02:00
backendtest Move tools/diagnose_ex.h to comphelper/diagnose_ex.hxx 2022-08-18 17:10:19 +02:00
headless merge duplicate CairoTextRender impls 2023-01-12 11:33:24 +00:00
inc merge duplicate CairoTextRender impls 2023-01-12 11:33:24 +00:00
ios rename SwIndex->SwContentIndex 2022-07-25 15:28:39 +02:00
jsdialog tdf#86630 sw: Add one-step page number insertion wizard 2023-01-06 07:42:32 +00:00
null VCL move PrinterInfoManager into GenericUnixSalData 2022-01-14 09:07:28 +01:00
osx rename BitmapEx::GetAlpha to GetAlphaMask 2023-01-11 08:57:13 +00:00
qa vcl: introduce a BitmapEx::DumpAsPng() 2023-01-12 06:54:30 +00:00
qt5 drop internal support for 1-bit images 2023-01-12 06:52:42 +00:00
qt6 qt a11y: Remember and reuse existing QObject for XAccessible 2022-08-24 19:05:35 +02:00
quartz Related: tdf#146842 Eliminate temporary copies of SkiaSalBitmap when printing 2022-12-29 14:14:36 +00:00
skia rename BitmapEx::GetAlpha to GetAlphaMask 2023-01-11 08:57:13 +00:00
source Resolves: tdf#107625 make ctrl+tab act like tab when tab is an input char 2023-01-12 08:48:26 +00:00
uiconfig we don't use urgency-hint or want any gravity hints 2022-09-07 15:55:49 +02:00
unx merge duplicate CairoTextRender impls 2023-01-12 11:33:24 +00:00
win No need for bool return value here 2022-12-21 06:44:59 +00:00
workben rename BitmapEx::GetAlpha to GetAlphaMask 2023-01-11 08:57:13 +00:00
AllLangMoTarget_vcl.mk
commonfuzzer.mk merge sdfilt library into sd 2022-09-14 15:11:46 +02:00
CppunitTest_vcl_animation.mk vcl: rename ImplAnimView to AnimationRenderer 2022-06-21 07:47:29 +02:00
CppunitTest_vcl_apitests.mk
CppunitTest_vcl_app_test.mk tdf#124672 for hicontrast white/black bg select either Sifr vs Sifr Dark 2022-10-08 17:34:34 +02:00
CppunitTest_vcl_backend_test.mk fix Skia copyArea() not coping with coordinates outside (tdf#145811) 2021-11-30 22:06:15 +01:00
CppunitTest_vcl_bitmap_render_test.mk
CppunitTest_vcl_bitmap_test.mk Disable epoxy test with --disable-gui 2022-01-05 18:00:59 +01:00
CppunitTest_vcl_bitmapprocessor_test.mk
CppunitTest_vcl_blocklistparser_test.mk
CppunitTest_vcl_cjk.mk Fix setting SAL_NON_APPLICATION_FONT_USE 2022-09-02 12:12:29 +02:00
CppunitTest_vcl_dialogs_test.mk
CppunitTest_vcl_drawmode.mk
CppunitTest_vcl_errorhandler.mk
CppunitTest_vcl_filter_igif.mk
CppunitTest_vcl_filter_ipdf.mk CppunitTest_vcl_filter_ipdf: inherit from UnoApiTest 2022-11-22 14:19:44 +01:00
CppunitTest_vcl_filters_test.mk support for the WebP image format (tdf#114532) 2022-01-31 10:44:29 +01:00
CppunitTest_vcl_font.mk vcl: test getting glyph boundary rect from LogicalFontInstance 2022-11-27 10:40:17 +01:00
CppunitTest_vcl_fontcharmap.mk
CppunitTest_vcl_fontfeature.mk
CppunitTest_vcl_fontmetric.mk
CppunitTest_vcl_gen.mk UnoApiTest: simplify code by using tempfile member 2022-11-08 11:54:22 +01:00
CppunitTest_vcl_gradient.mk vcl: migrate AddGradientActions() from OutputDevice to Gradient 2022-01-05 05:42:32 +01:00
CppunitTest_vcl_graphic_test.mk
CppunitTest_vcl_jpeg_read_write_test.mk
CppunitTest_vcl_lifecycle.mk
CppunitTest_vcl_mnemonic.mk
CppunitTest_vcl_outdev.mk
CppunitTest_vcl_pdfexport.mk CppunitTest_vcl_pdfexport: inherit from UnoApiTest 2022-11-09 19:09:15 +01:00
CppunitTest_vcl_pdfium_library_test.mk
CppunitTest_vcl_png_test.mk
CppunitTest_vcl_skia.mk
CppunitTest_vcl_svm_test.mk Disable epoxy test with --disable-gui 2022-01-05 18:00:59 +01:00
CppunitTest_vcl_text.mk gbuild: set SAL_NON_APPLICATION_FONT_USE in gb_CppunitTest_use_more_fonts 2022-09-01 11:52:36 +02:00
CppunitTest_vcl_timer.mk
CppunitTest_vcl_type_serializer_test.mk
CppunitTest_vcl_widget_definition_reader_test.mk
CustomTarget_gtk3_kde5_moc.mk
CustomTarget_kf5_moc.mk
CustomTarget_nativecalc.mk
CustomTarget_nativecore.mk
CustomTarget_nativedraw.mk
CustomTarget_nativemath.mk
CustomTarget_nativewriter.mk
CustomTarget_qt5_moc.mk qt a11y: Drop unnecessary QObject inheritance 2022-08-23 15:34:50 +02:00
CustomTarget_qt6_moc.mk qt a11y: Drop unnecessary QObject inheritance 2022-08-23 15:34:50 +02:00
Executable_602fuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_bmpfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_cgmfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_dbffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_diffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_docxfuzzer.mk oss-fuzz: convert to static cross-build 2021-12-25 17:05:08 +01:00
Executable_dxffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_epsfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_fftester.mk
Executable_fodpfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_fodsfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_fodtfuzzer.mk oss-fuzz: convert to static cross-build 2021-12-25 17:05:08 +01:00
Executable_giffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_htmlfuzzer.mk oss-fuzz: convert to static cross-build 2021-12-25 17:05:08 +01:00
Executable_hwpfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_icontest.mk Drop support for OpenGL denylist on X11 2022-03-28 14:31:07 +02:00
Executable_jpgfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_listfonts.mk vcl: Create listfonts utility 2022-01-08 12:58:14 +01:00
Executable_listglyphs.mk vcl: list the glyphs and bound rects of a specified font 2022-11-25 14:04:20 +01:00
Executable_lo_kde5filepicker.mk
Executable_lockfuzzer.mk add a fuzzer for our lock files 2022-06-20 21:43:02 +02:00
Executable_lwpfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_metfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_minvcl.mk tdf#146478 vcl: vcldemo and other vcl examples segfault on close 2022-01-21 12:43:30 +01:00
Executable_mmlfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_mtfdemo.mk Drop support for OpenGL denylist on X11 2022-03-28 14:31:07 +02:00
Executable_mtpfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_olefuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pcdfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pctfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pcxfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pngfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_ppmfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pptfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_pptxfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_psdfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_qpwfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_rasfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_rtffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_scrtffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_sftfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_slkfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_svdemo.mk tdf#146478 vcl: vcldemo and other vcl examples segfault on close 2022-01-21 12:43:30 +01:00
Executable_svmfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_svpclient.mk
Executable_svptest.mk
Executable_tgafuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_tiffuzzer.mk for fuzzers add libtiff to common externals, not just tiffuzzer 2022-05-22 22:23:44 +02:00
Executable_vcldemo.mk Drop support for OpenGL denylist on X11 2022-03-28 14:31:07 +02:00
Executable_visualbackendtest.mk Drop support for OpenGL denylist on X11 2022-03-28 14:31:07 +02:00
Executable_webpfuzzer.mk support for the WebP image format (tdf#114532) 2022-01-31 10:44:29 +01:00
Executable_wksfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_wmffuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_ww2fuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_ww6fuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_ww8fuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_xbmfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_xlsfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_xlsxfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
Executable_xpmfuzzer.mk oss-fuzz: use fuzzer_statics for default statics 2021-12-25 15:24:51 +01:00
IwyuFilter_vcl.yaml Remove some unused includes 2022-11-24 08:09:53 +01:00
Library_desktop_detector.mk Add HAVE_(UNIX_)DLAPI config header define 2022-01-18 13:44:53 +01:00
Library_vcl.mk merge duplicate CairoTextRender impls 2023-01-12 11:33:24 +00:00
Library_vclplug_gen.mk merge duplicate CairoTextRender impls 2023-01-12 11:33:24 +00:00
Library_vclplug_gtk3.mk tdf#150683 gtk3 a11y: Expose AtkTableCell interface for cells 2022-09-03 23:17:52 +02:00
Library_vclplug_gtk3_kde5.mk tdf#150683 gtk3 a11y: Expose AtkTableCell interface for cells 2022-09-03 23:17:52 +02:00
Library_vclplug_gtk4.mk gtk4: add a surface_cell_renderer 2022-04-12 20:51:47 +02:00
Library_vclplug_kf5.mk tdf#125925 Qt migrate KF5 theme font settings code 2022-05-25 08:32:12 +02:00
Library_vclplug_osx.mk Don't link against private CoreUI framework when sandboxed 2022-06-29 15:36:07 +02:00
Library_vclplug_qt5.mk qt a11y: Remember and reuse existing QObject for XAccessible 2022-08-24 19:05:35 +02:00
Library_vclplug_qt6.mk qt a11y: Remember and reuse existing QObject for XAccessible 2022-08-24 19:05:35 +02:00
Library_vclplug_win.mk Related: tdf#118320 enable some windows dark theme support 2022-03-16 22:16:01 +01:00
Makefile
Module_vcl.mk Don't bother building the vcldemo executable for WASM unless using Qt5 2023-01-12 08:26:22 +00:00
Package_fontunxppds.mk
Package_fontunxpsprint.mk
Package_opengl_denylist.mk
Package_osxres.mk
Package_skia_denylist.mk
Package_theme_definitions.mk
Package_tipoftheday.mk
Package_toolbarmode.mk
README.GDIMetaFile.md
README.lifecycle.md
README.md VCL drop m_pInstance from *nix SalData 2022-01-14 16:13:04 +01:00
README.scheduler.md Improve vcl scheduler documentation 2022-07-30 20:34:50 +02:00
README.vars.md VCL fix shutdown when run via system loop 2022-01-21 12:42:20 +01:00
StaticLibrary_fuzzer_calc.mk
StaticLibrary_fuzzer_core.mk
StaticLibrary_fuzzer_draw.mk
StaticLibrary_fuzzer_math.mk
StaticLibrary_fuzzer_writer.mk
StaticLibrary_vclmain.mk
UIConfig_vcl.mk tdf#141026 Put user and computer name into collapsed section 2022-06-20 15:46:48 +02:00
vcl.common.component Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.android Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.headless Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.ios Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.macosx Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.unx Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vcl.common.component.windows Disallow multiple component files per library 2021-12-21 00:20:36 +01:00
vclplug_win.component
WinResTarget_vcl.mk

Visual Class Library (VCL)

Visual Class Library (VCL) is responsible for the widgets (windowing, buttons, controls, file-pickers etc.), operating system abstraction, including basic rendering (e.g. the output device).

It should not be confused with Borland's Visual Component Library, which is entirely unrelated.

VCL provides a graphical toolkit similar to gtk+, Qt, SWING etc.

  • source/

    • the main cross-platform chunk of source
  • inc/

    • cross-platform abstraction headers
  • headless/

    • a backend renderer that draws to bitmaps
  • android/

    • Android backend
  • osx/

    • macOS backend
  • ios/

    • iOS backend
  • quartz/

    • code common to macOS and iOS
  • win/

    • Windows backend
  • qt5/

    • Qt5 (under construction)
  • unx/

  • How the platform abstraction works

    • InitVCL calls 'CreateSalInstance'
      • this is implemented by the compiled platform backends
    • the SalInstance vtable is the primary outward facing gateway API for platform backends
      • It is a factory for: SalFrames, SalVirtualDevices, SalPrinters, Timers, the SolarMutex, Drag&Drop and other objects, as well as the primary event loop wrapper.

Note: references to "SV" in the code mean StarView, which was a portable C++ class library for GUIs, with very old roots, that was developed by StarDivision. Nowadays it is not used by anything except LibreOffice (and OpenOffice).

"svp" stands for "StarView Plugin".

SalData implementations

Each backend must provide an implementation of the SalData class. There is no defined interface, so feel free to implement whatever suits your platform.

If your platform does font handling based on Freetype and Fontconfig, it's highly recommended to use GenericUnixSalData as the base class; there isn't really much *nix stuff in it.

Currently Windows, iOS and MacOSX have independent SalData implementations.

COM Threading

The way COM is used in LO generally:

  • vcl puts main thread into Single-threaded Apartment (STA)
  • oslWorkerWrapperFunction() puts every thread spawned via oslCreateThread() into MTA (free-threaded)

GDIMetafile

GDIMetafile is a vector drawing representation that corresponds directly to the SVM (StarView Metafile) format; it is extremely important as an intermediate format in all sorts of drawing and printing operations.

There is a class MetafileXmlDump in include/vcl/mtfxmldump.hxx that can store a GDIMetafile as XML, which makes debugging much easier since you can just use "diff" to see changes.

EMF+

emf+ is vector file format used by MSO and is successor of wmf and emf formats. see http://msdn.microsoft.com/en-us/library/cc230724.aspx for documentation. note that we didn't have this documentation from start, so part of the code predates to the time when we had guessed some parts and can be enhanced today. there also still many thing not complete

emf+ is handled a bit differently compared to original emf/wmf files, because GDIMetafile is missing features we need (mostly related to transparency, argb colors, etc.)

emf/wmf is translated to GDIMetafile in import filter vcl/source/filter/wmf and so special handling ends here

emf+ is encapsulated into GDIMetafile inside comment records and parsed/rendered later, when it reaches cppcanvas. It is parsed and rendered in cppcanvas/source/mtfrenderer. also note that there are emf+-only and emf+-dual files. dual files contains both types of records (emf and emf+) for rendering the images. these can used also in applications which don't know emf+. in that case we must ignore emf records and use emf+ for rendering. for more details see the documentation.

Parsing

wmf/emf filter --> GDI metafile with emf+ in comments --> cppcanvas metafile renderer

lately the GDIMetafile rendering path changed which also influenced emf+ rendering. now many things happen in drawing layer, where GDIMetafile is translated into drawing layer primitives. for metafiles with emf+ we let the mtfrenderer render them into bitmap (with transparency) and use this bitmap in drawinlayer. cleaner solution for current state would be to extend the drawing layer for missing features and move parsing into drawing layer (might be quite a lot of work). intermediary enhancement would be to know better the needed size/resolution of the bitmap, before we render emf+ into bitmap in drawing layer. Thorsten is working on the same problem with svg rendering, so hopefully his approach could be extended for emf+ as well. the places in drawing layer where we use canvas mtfrenderer to render into bitmaps can be found when you grep for GetUseCanvas. also look at vcl/source/gdi/gdimetafile.cxx where you can look for UseCanvas again. moving the parsing into drawinglayer might also have nice side effect for emf+-dual metafiles. in case the emf+ records are broken, it would be easier to use the duplicit emf rendering. fortunately we didn't run into such a broken emf+ file yet. but there were already few cases where we first though that the problem might be because of broken emf+ part. so far it always turned out to be another problem.

Rendering

before

vcl --> cppcanvas metafile renderer --> vcl

now

drawing layer --> vcl --> cppcanvas metafile renderer --> vcl --> drawing layer

another interesting part is actual rendering into canvas bitmap and using that bitmap later in code using vcl API.

EMF+ implementation has some extensive logging, best if you do a dbgutil build, and then

export SAL_LOG=+INFO.cppcanvas.emf+INFO.vcl.emf

before running LibreOffice; it will give you lots of useful hints.

You can also fallback to EMF (from EMF+) rendering via

export EMF_PLUS_DISABLE=1

Printing/PDF Export

Printing from Writer works like this:

  1. individual pages print by passing an appropriate OutputDevice to XRenderable
  2. in drawinglayer, a VclMetafileProcessor2D is used to record everything on the page (because the OutputDevice has been set up to record a GDIMetaFile)
  3. the pages' GDIMetaFiles are converted to PDF by the vcl::PDFWriter in vcl/source/gdi/pdfwriter*

Creating the ODF thumbnail for the first page works as above except step 3 is:

  1. the GDIMetaFile is replayed to create the thumbnail

On-screen display differs in step 1 and 2:

  1. the VCL Window gets invalidated somehow and paints itself
  2. in drawinglayer, a VclPixelProcessor2D is used to display the content

Debugging PDF export

Debugging the PDF export becomes much easier when compression is disabled (so the PDF file is directly readable) and the MARK function puts comments into the PDF file about which method generated the following PDF content.

The compression can be disabled even using an env. var:

export VCL_DEBUG_DISABLE_PDFCOMPRESSION=1

To de-compress the contents of a PDF file written by a release build or other programs, use the "pdfunzip" tool:

bin/run pdfunzip input.pdf output.pdf

SolarMutexGuard

The solar mutex is the "big kernel lock" of LibreOffice, a global one. It's a recursive mutex, so it's allowed to take the lock on the same thread multiple times, and only the last unlock will actually release the mutex.

UNO methods on components can be called from multiple threads, while the majority of the codebase is not prepared for multi-threading. One way to get around this mismatch is to create a SolarMutexGuard instance at the start of each & every UNO method implementation, but only when it is necessary:

  • Only acquire the SolarMutex if you actually need it (e.g., not in functions that return static information).

  • Only around the code that actually needs it (i.e., never call out with it locked).

This way you ensure that code (not prepared for multithreading) is still executed only on a single thread.

In case you expect that your caller takes the solar mutex, then you can use the DBG_TESTSOLARMUTEX() macro to assert that in dbgutil builds.

Event listeners are a special (but frequent) case of the "never call out with a mutex (SolarMutex or other) locked" fundamental rule:

  • UNO methods can be called from multiple threads, so most implementations take the solar mutex as their first action when necessary.

  • This can be problematic if later calling out (an event handler is called), where the called function may be an UNO method implementation as well and may be invoked on a different thread.

  • So we try to not own the solar mutex, whenever we call out (invoke event listeners).

In short, never hold any mutex unless necessary, especially not when calling out.

Read More