156 Commits
Author SHA1 Message Date
Xisco Fauli dae32b5f57 CppunitTest_emfio_emf: fix test on Windows
gerrit_windows_wsl was configure to build with 'make build'
so this failure wasn't caught in time.
Now gerrit_windows_wsl builds with 'make build unitcheck slowcheck'
and it fails with
Test name: testExtTextOutScaleGM_COMPATIBLE::TestBody
double equality assertion failed
- Expected: 199
- Actual  : 201
- Delta   : 1
- In <>, attribute 'width' of '/primitive2D/metafile/transform/textsimpleportion[3]' incorrect value.

Change-Id: Ibce7398946ef52eea05438feacc7a1dcaa22d579
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/208165
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-07-16 00:42:18 +02:00
Andras Timar c043f65f66 tdf#167641 emfio: render PDF in EMR_COMMENT_MULTIFORMATS with Version=0
MS Office writes the EmrFormat.Version field as 0 in the
EMR_COMMENT_MULTIFORMATS record carrying an embedded PDF. Per
[MS-EMF] 2.3.3.4.2 EmrFormat, Version MUST be 0x00000001 only when
Signature == EPS_SIGNATURE; for any other signature it MUST be
ignored. The reader rejected anything but 1, so the embedded PDF
was dropped on the floor.

Real-world files also use an empty OutputRect (0,0,0,0); per
[MS-EMF] 2.3.3.4.3 it is in logical coordinates, so fall back to
the EMF's logical bounds (mrclBounds) when it is degenerate, so
ResolveBitmapActions has somewhere to draw the PDF bitmap.

The new fixture is the existing pdf-in-emf.pptx EMF with the two
fields patched to reproduce the regression in 776 bytes.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: I432f75a1cac11d84448db07c1a1815cd0be60744
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/1904
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit a5d7b2935718bf7f1f6cc0352c8d8681e6713f4b)
Cherry-pick note: the test fails on macOS in CI
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205084
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-05-13 09:57:03 +02:00
Andras Timar 783914b216 emfio: fill each EmfPlusFillRects rect independently
The handler accumulated every rect from one EmfPlusFillRects
record into a single B2DPolyPolygon and emitted a single
PolyPolygonColorPrimitive2D, which drawinglayer fills under the
even-odd rule. With overlapping rects, even-odd cancels pairwise
overlaps - three south-east-shifted gray squares rendered as
filled-then-hollow-then-filled stripes (the triple-overlap centre
came back as filled because three crossings is again odd).

Per MS-EMFPLUS each rect in EmfPlusFillRects fills its interior
independently; there is no fill-rule choice. Emit one fill
primitive per rect inside the loop and keep the polypolygon path
only for EmfPlusDrawRects, where stroking is independent of fill
rule so the existing single-call shape stays correct.

Tests: testEmfPlusFillRectsOverlap with three 300x300 squares
shifted south-east by 100px each (extracted from the tdf#107034
sample EMF) asserts three separate polypolygoncolor primitives
rather than one combined.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: I567e6a06d103684a723f513297684c66f700587a
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2314
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 679c654a5b9a5f4a1cd787e5fa2d2380eb5574fb)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205087
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
2026-05-12 16:21:49 +02:00
Andras Timar f8084808c2 emfio: render EMF+ PathGradient brushes
Replace the previous SvgRadialGradientPrimitive2D approximation of
PathGradientBrush with a bitmap-textured polypolygongraphic fill,
where the bitmap content is computed by a per-triangle Gouraud
shading of the brush boundary.

The old approximation positioned the gradient centre via
Map(brush->firstPoint), which typically landed far outside the
polygon's unit-coordinate range because the brush's path lives in
its own coordinate space; with SpreadMethod::Pad the gradient then
degenerated into a flat boundary-colour fill - the "orange square
instead of tiled gradient circles" of tdf#143031.

The bitmap is allocated with the brush bbox's aspect ratio
(longest side 256 px) and anchored to aBrushBounds.getMinX/MinY in
raw EMF coords, so when maMapTransform sends it to world space it
lines up with the fill polygon. wrapMode != WrapModeClamp routes
it through the existing texture-tiling path so larger fill polygons
repeat the bitmap.

Per-pixel content (Gouraud sweep):
- Partition the brush boundary into N triangles formed by (centre,
  V_i, V_{i+1}) and Gouraud-shade each one with vertex colours
  (centerColor, surround[i], surround[(i+1) % nSurround]). Inside a
  triangle the pixel colour is the barycentric blend of the three
  vertex colours; this reproduces multi-surround-colour brushes
  (e.g. the libUEMF 5-pointed star with red/blue/red/blue/magenta
  outer points and green inner indents on a black centre) and
  collapses to a smooth radial gradient when all surround colours
  are equal.
- The brush's BlendFactors curve (sampleFactor) remaps the
  centre/edge parameter t before mixing centre and per-segment
  edge colour. PresetColors / ColorBlend (sampleColor), when
  present, override the centre/edge mix entirely with a sampled
  stop colour. Both fall back to a linear centre-to-edge mix when
  the brush carries no curve.

Rasterization is done per-triangle: Pass 1 walks each fan
triangle's pixel-space AABB (clipped to the bitmap) and writes
only the pixels that fall inside, so total work is O(sum of
triangle AABB areas) rather than O(bitmap area * triangle count).
Structurally this is what cairo's mesh-pattern rasterizer
(cairo-mesh-pattern-rasterizer.c) does for PDF type-7 shadings -
each patch paints into its own pixel range rather than every
pixel testing every patch. With N up to ~512 boundary segments
after Bezier flattening, that turns a 256x256-pixel bitmap from
a ~30M pixel-tests-triangle loop into ~50k AABB iterations
(per-pixel arithmetic is unchanged so the rendered colours match
bit-for-bit).

Boundary handling:
- BrushDataPath set: take the brush's path polygon and flatten
  Bezier segments via adaptiveSubdivideByDistance with bound =
  bbox/512 so the boundary closely follows the curve.
- BrushDataPath unset: use a new EMFPPath::GetRawPointsPolygon()
  helper that builds a polygon directly from the boundary points.
  GetPolygon() can't be used here because the trailing bytes of
  boundary-only brush data don't encode valid path-point types and
  produce a degenerate polygon.

Pixels outside every fan triangle (in the bitmap bbox but not in
the boundary) are handled per wrapMode in a second pass:
- Tile / TileFlipX / TileFlipY / TileFlipXY: left transparent so
  adjacent tiles in the fill polygon stay visually separate. Pass
  2 is skipped entirely for these wrap modes.
- Clamp: extended using the closest triangle's edge colour
  (smallest-negative-margin barycentric weights), eliminating
  sub-pixel transparent jaggies along smooth Bezier fill polygons
  that extend slightly past the flattened boundary.

Tests: testEmfPlusBrushPathGradientWithBlendColors expectations
updated to assert the new polypolygongraphic-with-bitmap structure
(single bitmap copy fills the polygon when bitmap and polygon bbox
coincide). New testEmfPlusBrushPathGradientMultiSurroundColor
with a hand-extracted libUEMF 5-pointed-star EMF exercises the
boundary-only / multi-surround-colour path. testEmfPlusBrushPath-
GradientTiled covers the texture-tiling case where the brush
gradient is repeated across a larger fill polygon.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: I92aa6d90ef6d2106f1d8d1cad97a3bb83594bd23
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2209
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit fa76144b9cf130e232465c2480a5a7127bb282ed)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205086
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
2026-05-12 16:21:43 +02:00
Andras Timar 05f4321345 emfio: honour Winding fill mode on EMF+ FillClosedCurve
The fill-mode bit (0x2000) of EMF+ FillClosedCurve records was
logged but ignored, so a self-intersecting closed curve drawn with
WINDING semantics rendered the same as ALTERNATE - the centre of a
pentagram fill came out as a hole instead of being filled. Convert
the polypolygon at parse time the same way the pre-existing
EMR_SETPOLYFILLMODE path does (solveCrossovers +
stripNeutralPolygons + mergeToSinglePolyPolygon for single self-
intersecting polygons, createNonzeroConform for nested poly-
polygons) so the resulting even-odd fill of primitive2d primitives
matches the intended winding-fill visual.

Add a unit test with a minimal EMF+ FillClosedCurve drawing a
self-intersecting pentagram in winding mode.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: Ic02048aae223527dca0f556f0171f117baf147c0
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2313
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit fd018f6203f61aaf0c8c781c11a93578bf1eaf6b)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205085
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-05-12 16:21:36 +02:00
Andras Timar d271bc432b tdf#116623 emfio: apply RGN_COPY region data in EMR_EXTSELECTCLIPRGN
[MS-EMF] 2.3.2.2 says the RegionData field "MUST be ignored" when
iMode is RGN_COPY, but real EMFs include data with RGN_COPY and
expect the clip to be replaced with the given region (verified
against MS Word reference rendering of test files such as
TestCreatePen.emf and a chart EMF where the colored plot lines
were leaking outside the plot frame). Treat the record like the
Win32 ExtSelectClipRgn API: a non-NULL region with RGN_COPY
replaces the clip, a NULL region (cbRgnData == 0) with RGN_COPY
resets the clip to the default null region.

Add a minimal hand-crafted EMF (TestExtSelectClipRgnCopy.emf) that
draws a (0,0)-(200,200) rectangle through a (50,50)-(150,150)
RGN_COPY clip and asserts the imported metafile wraps the rectangle
in a clip-region mask matching the requested rectangle.

Update existing test expectations to reflect the new clip-region
group/mask wrappers that now appear in the metafile primitive tree
where RGN_COPY data is present (testCreatePen, testPolyPolygon,
testTextMapMode, testEmfPlusSetPageTransform,
testDrawImagePointsWithMetafile, testSine).

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: Id123157b64b75d817b4736443eac14804b04bb89
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2206
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 1c2ff94b6079451a7047a2afb45467d6fe31cb4f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205072
Tested-by: Jenkins
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
2026-05-12 07:40:42 +02:00
Andras Timar 6bfe01ec89 emfio: handle pattern brush in non-rectangular shape primitives
DrawPolygon and DrawRect already route Pattern fill style through
ImplEmitPatternFill, but DrawEllipse, DrawRoundRect, DrawPie,
DrawChord, and DrawPolyPolygon still emit their plain Meta*Action
which leaves the shape unfilled. Route Pattern fill through the
helper for those too, converting the shape to its polygon
equivalent and emitting the clipped MetaWallpaperAction.

Add a unit test that draws an ellipse with a DIB pattern brush and
asserts the wallpaper is emitted in the metafile dump. Without the
fix the ellipse renders as a hairline outline only.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: I2d4e273029770ddc727bc24d9b3205fe079fafd6
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2205
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit e87013a0457d270d442841610f4a3430e82f1274)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205041
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-05-11 12:25:29 +02:00
Andras Timar 7ed015807a emfio: invalidate fill style cache on SETBKMODE for hatched brushes
UpdateFillStyle short-circuits when maLatestFillStyle == maFillStyle,
but for a hatched brush the emitted MetaFillColorAction depends on
mnBkMode (bk color when OPAQUE, transparent when TRANSPARENT). With
no brush change between two rectangles separated only by SETBKMODE,
the second rectangle inherits the previous OPAQUE bk color fill, so
the gaps between hatch lines stay opaque.

Make SetBkMode invalidate maLatestFillStyle.aFillColor (using the
same sentinel that ResetInternalState uses) when the mode actually
changes, forcing the next UpdateFillStyle to re-emit a fresh
MetaFillColorAction with the correct bk-mode-dependent fill.

Add a unit test with a minimal hand-crafted WMF that draws two
rectangles using the same hatched brush across a SETBKMODE flip
and asserts that both a #ff0000 (OPAQUE bk color) and a #000000
(TRANSPARENT) fillcolor are emitted in the metafile.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: I34b8984989f3ce9108464ad5a8c379174a988b59
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2204
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 41ddf034e276a5493f4fd56be61702a8b28e9649)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205040
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-05-11 11:57:59 +02:00
Andras Timar acc568fd2a emfio: render WMF DIB pattern brushes as tiled bitmap fills
META_DIBCREATEPATTERNBRUSH with Style=BS_PATTERN was dropped on the
floor with a SAL_WARN, and BS_DIBPATTERN averaged the bitmap to a
solid color, so neither produced a real pattern fill. Read both
variants into a real Bitmap (DIB or, for BS_PATTERN, a 1bpp Bitmap16)
and store it as a Pattern WinMtfFillStyle. Real-world generators
emit a DIB even with Style=BS_PATTERN, so peek the leading DWORD to
decide between DIB and Bitmap16. The same Bitmap16 helper handles
the obsolete META_CREATEPATTERNBRUSH record (32-byte legacy BITMAP +
reserved padding per MS-WMF 2.3.4.4).

The Pattern fill type was only handled in DrawPolygon, and that path
emitted XPATHFILL_SEQ_BEGIN/END comments with no actual paint
primitives. wmfemfhelper does not consume those comments, so the
PNG/drawinglayer rendering path saw nothing. Replace the comment
emission with a clip-region wrapped MetaWallpaperAction (Tile style)
which is fully consumed downstream. Factor the emission into
ImplEmitPatternFill and call it from DrawRect too, where Pattern
was previously not handled at all.

WinMtfFillStyle::operator== did not compare aBmp, so successive
pattern brushes with different bitmaps but identical solid-fill
fields compared equal and UpdateFillStyle short-circuited, leaving
maLatestFillStyle pointing at the previous bitmap. Include aBmp in
the equality check.

Add a unit test with a minimal hand-crafted WMF that asserts the
expected wallpaper sequence in the metafile dump.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: Ia2662de9cac5fcf1a7153237f9974467b8f849de
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/2203
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 66dcbef6b5ceec8d9ccd4542509d5f9d7fdce2c1)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/205039
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-05-11 11:34:08 +02:00
Andras Timar 60c4f98cee tdf#143056 EMF+: honor StringFormat tracking when drawing strings
The tracking field was parsed but ignored, so DrawString always
used the font's natural character advances. Now build a DX-array
by multiplying each cumulative width by tracking, and pass it to
the text primitive. Also use the stretched width for alignment
math so center/far positioning stays correct.

testDrawStringTracking loads an EMF+ with tracking == 1.5 and checks
that the resulting textsimpleportion carries a stretched DX-array.

testDrawStringAlign turned out to use a file with tracking == 1.03 and
its expected x positions were based on the old buggy behavior (tracking
silently ignored).  Update the centered/right-aligned expectations to
match the corrected text width.

Signed-off-by: Andras Timar <andras.timar@collabora.com>
Change-Id: Ica93f6ba11d2d951688ee18230e5993d97a34db6
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/1986
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
(cherry picked from commit 1a9cce32f7408aab06289295c63b3e24146472a0)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204839
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
2026-05-06 09:36:55 +02:00
Andras Timar 14be550da2 emfio: implement BS_HATCHED brushes and pens
Handle BS_HATCHED brush style in EMR_CREATEBRUSHINDIRECT,
W_META_CREATEBRUSHINDIRECT, and EMR_EXTCREATEPEN.

For brushes (hatch indices 0-5), map Windows hatch styles
(HS_HORIZONTAL..HS_DIAGCROSS) to VCL Hatch objects and emit
MetaHatchAction in all polygon/polypolygon fill paths.

For EMF-specific hatch indices 6-11, use the appropriate color
source per [MS-EMF] 2.1.17: brush color (6-7), text color (8-9),
or background color (10-11) as solid fills.

For wide geometric pens with BS_HATCHED (EMR_EXTCREATEPEN),
create stroke area geometry via createAreaGeometry and render
the hatch pattern inside the pen stroke area, replacing the
normal MetaPolyLineAction/MetaLineAction. This covers all
drawing paths including LineTo, DrawPolyLine, DrawPolygon,
DrawPolyPolygon, DrawRect, DrawRoundRect, DrawEllipse, DrawArc,
DrawPie, DrawChord, DrawPolyBezier, and StrokeAndFillPath.

Change-Id: Ie8482ac53b6d4d263793488ce10a97fa1716c68d
Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/325
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 8808d550d12afb3e7abc4fe6a3145d80fc5bdde4)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204389
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
2026-04-27 08:58:20 +02:00
Andras Timar 857fd268e8 emfio: implement EMR_SETPOLYFILLMODE and W_META_SETPOLYFILLMODE
The polygon fill mode (ALTERNATE vs WINDING) was ignored in both EMF
and WMF readers.  ALTERNATE (even-odd) is the default; WINDING
(non-zero winding) appears in 2541/6939 EMF files and 135/467 WMF
files that set the mode.  Self-intersecting polygons like pentagram
stars render differently under the two rules.

Store the fill mode state in MtfTools with save/restore in Push/Pop,
wire up the record handlers, and fix the hardcoded fillNonZero in
DrawPolygon pattern fills to respect the current mode.

Add a unit test with a pentagram star EMF using WINDING mode.

Change-Id: I1d9127b79cc6c3b67f39bebe2c82e806c9db4ce8
Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/324
Tested-by: Andras Timar <andras.timar@collabora.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204388
Tested-by: Jenkins
2026-04-27 08:58:11 +02:00
Andras Timar 2ac3353184 emfio: implement EMR_EXCLUDECLIPRECT
Wire up EMR_EXCLUDECLIPRECT (record type 29) in the EMF reader.
ExcludeClipRect() was already implemented in MtfTools and used by the
WMF reader, but missing from the EMF record dispatch. This record
subtracts a rectangle from the current clipping region, creating a
"hole" that prevents drawing in that area.

Present in 291 of 6,939 real-world EMF files (4.2%).

Change-Id: I7bff53473c19453605e5fd88fdeff101f213fd85
Reviewed-on: https://gerrit.collaboraoffice.com/c/core/+/320
Tested-by: Andras Timar <andras.timar@collabora.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 38e963b2b4b12471b2530e11208a543f403bf4f2)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204247
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-04-27 01:03:44 +02:00
Andrea Gelmini c21f0a4a42 Fix typo
Change-Id: Ib019fb6e87f3da356a69a14729864f31b777c8bf
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201196
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Simon Chenery <simon_chenery@yahoo.com>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
2026-03-19 09:51:46 +01:00
Bartosz Kosiorek f0a3081314 tdf119973 tdf160063 emfio: Reset GDI trackers on EMF+ GetDC record
When an EMF+ Dual Mode file switches back to GDI records via
EmfPlusRecordType::GetDC (0x4004), the GDI parser (MtfTools)
might have outdated information about the current state of the
VCL MetaFile, as EMF+ records could have modified it in the meantime.

By introducing ResetInternalState(), we invalidate the "latest"
trackers for fill style, line style, and text attributes. This
forces the parser to re-emit the necessary GDI actions (like
SetFillColor) for the subsequent GDI records, preventing issues
like incorrect colors (e.g., black shapes instead of white).

Change-Id: I1665daba2d9a2105f135e2b638af48d2b14150eb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201720
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2026-03-15 17:46:51 +01:00
Bartosz Kosiorek c1fb4c337d tdf59814 tdf168886 EMF+ Use Frame size and DPI instead Bound
Previously, nested EMF images were sized based on rclBounds, which
only encompasses the drawn objects. This caused incorrect scaling
and offsets when the drawing did not fill the entire logical canvas.

Changes:
- Switched from rclBounds to rclFrame for logical canvas dimensions.
- Implemented DPI calculation using szlDevice and szlMillimeters
  from the EMF header.
- Correctly mapped rclFrame (0.01mm units) to image pixel
  coordinates (x, y, width, height).

Change-Id: I32f6679bedb26e86b069abd6b4d270a385ca7e89
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201586
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Tested-by: Jenkins
2026-03-13 11:44:54 +01:00
Noel Grandin 8459f0be51 XmlWriter::attribute(double) should actually write a double value
And not truncate it to an integer value.

Add additional overload for attribute that takes an enumerated type, otherwise
the compiler will complain about ambiguous conversion because it cannot
choose between the attribute that takes a integral value and the one that
takes a double value.

Change-Id: I9eae22817ec3b26da7b9468d1c8b5e6f3e900538
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201193
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Tested-by: Jenkins
2026-03-10 15:49:17 +01:00
Xisco Fauli 6709dd178f CppunitTest_emfio_emf: fix build on Windows
Change-Id: Iffc791557eea3e38b02262f81c26c5dece6c343b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201136
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-03-07 09:19:56 +01:00
Bartosz Kosiorek 4dccec254c tdf166084 tdf138087 tdf59814 EMF+ Fix scale and trans DrawImagePoints Metafile
This commit fixes the incorrect positioning and scaling of Metafiles
rendered via EMF+ DrawImagePoints.

Key changes:
- Implemented a normalization matrix for Metafiles to properly map
  source coordinates (SrcRect) to the destination.
- Updated EMFPImage to parse and store bounds from nested EMF headers,
  ensuring correct dimensions (x, y, width, height) are available.

Change-Id: I07b4d99c334611a10e7faff42b76699f04fa1520
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201084
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2026-03-06 22:13:37 +01:00
Bartosz Kosiorek 6c05a6339c tdf#129342 tdf#170985 EMF+ Implement BrushTypeTextureFill for bitmaps
This patch implements the missing TextureFill brush support for EMF+
records. Previously, texture fills were ignored, resulting in missing
backgrounds or shapes.

Change-Id: I61f80a9851f3929651f54b68d6d4d21e65720aa6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200547
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2026-02-28 08:04:39 +01:00
Gabor Kelemen eb087d25b3 tdf#146619 Use more forward declarations in include/drawinglayer
Change-Id: I5911dfb1cfc2bfd291758334b69123cfbce559a5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199387
Reviewed-by: Gabor Kelemen <gabor.kelemen@collabora.com>
Tested-by: Jenkins
2026-02-22 12:08:33 +01:00
Bartosz Kosiorek b6857c1f16 tdf#138087 tdf#142548 EMF Fix font scaling and orientation in GM_COMPATIBLE
When importing EMF files, certain records (like EXTTEXTOUTW) in
GM_COMPATIBLE mode were not respecting non-proportional scaling
or single-axis mirroring. This resulted in text that was too wide/narrow
or rotated in the wrong direction.

Key changes:
- Added font width scaling based on the ratio between fXScale and fYScale.
- Handled 180-degree rotation when both axes are negative.
- Corrected font orientation for single-axis mirroring by inverting the
  angle (3600 - orientation) to compensate for the reversed chirality
  of the coordinate system.

Change-Id: Ib1126c192a80b973f343f25bf20ec119d94d71a8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199770
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2026-02-21 08:30:48 +01:00
Xisco Fauli ba3fb9026c merge UnoApiText and UnoApiXmlTest
in preparation for a follow-up commit

Change-Id: I3449c031696fe3ab13d4832e2671da08eb483cdb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199552
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2026-02-18 21:17:13 +01:00
Bartosz Kosiorek 8b002437fb tdf#168227 EMF+ Fix implementation of SetPageTransform
The implementation of SetPageTransform was incorrectly overwriting mnMmX and mnMmY
with calculated pixel values.

These variables represent the Reference Device size from the EMF+ header and should
remain constant. Overwriting them causes mappingChanged() to calculate an incorrect
transformation matrix, as it relies on the original ratio between reference
millimeters and pixels. This led to incorrect scaling and cumulative errors
if multiple SetPageTransform records were present in the document.

This patch ensures that header constants are preserved and the Page Scale
is applied as a separate step in the transformation pipeline.

Change-Id: I7a957f57894cc079292e8f93c119dd0fdb456fb4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199380
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2026-02-15 12:21:53 +01:00
Andras Timar aa616d930e Revert tdf#159306 EMF: fix PS_COSMETIC pen width regression
Commit be9d6e414e4b forced all PS_COSMETIC pen widths to 1 in both
EMR_CREATEPEN and EMR_EXTCREATEPEN handlers. Since PS_COSMETIC is
0x00000000 (same value as PS_SOLID), the check
"if (nPenStyle == PS_COSMETIC)" matched every simple PS_SOLID pen,
causing all line widths to be lost. This made all lines render as
hairlines regardless of the actual width specified in the EMF file.

The style sanitization check for invalid PS_STYLE_MASK values is
retained, but the width forcing is removed. Pen widths from the
file are now used as-is: width=0 produces a hairline, width>=1
produces a scaled line. This effectively reverts to the behavior
established by tdf#140271 (commit 8932c8906ff3), which recognized
that real-world EMF producers use EMR_CREATEPEN with widths > 1
and expect them to be honored.

Change-Id: I9a3acf83ce03b4e646e9b95fe0db54f8ce403a49
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198904
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Jenkins
2026-02-09 06:43:06 +01:00
Andras Timar aad62f783b tdf#142226 emfio: implement EMR_SMALLTEXTOUT
Change-Id: Ib031c0d771045b80c99274974de8267e759e8557
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198903
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
2026-02-08 19:20:56 +01:00
Andras Timar eddbe3b36d tdf#126965 emfio: fix opaque background on underlined text...
when BkMode is TRANSPARENT

In DrawText, the font's fill color was unconditionally set to maBkColor
before checking the background mode. When BkMode is TRANSPARENT, VCL's
underline rendering uses the font's fill color directly, ignoring the
transparency flag, causing an unwanted opaque background behind
underlined text.

Set COL_TRANSPARENT as the fill color when BkMode is TRANSPARENT, and
only use maBkColor when OPAQUE.

Change-Id: I0e94d2a1beae8ce2feecb0f7c0f8e03b36d2d80a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198889
Reviewed-by: Andras Timar <andras.timar@collabora.com>
Tested-by: Jenkins
2026-02-07 23:43:38 +01:00
Gabor Kelemen 0bdcfc2900 tdf#146619 Use more forward declarations in include/unotools/
This shaves off some 40M of input

Change-Id: I12e10deb87ceea1f7a23f3de4ea624befe187c3f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198238
Reviewed-by: Gabor Kelemen <gabor.kelemen@collabora.com>
Tested-by: Jenkins
2026-02-05 17:35:46 +01:00
Gabor Kelemen b63115f3fa tdf#146619 Use more forward declarations in include/vcl/[d-g]*
Found after running bin/find-unneeded-includes --headersfwd include/vcl/[d-g]*

This shaves off about 150M input

Change-Id: I2b15257451d4b392dca3e5d07f4a443ee653b04c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196395
Tested-by: Jenkins
Reviewed-by: Gabor Kelemen <gabor.kelemen@collabora.com>
2026-01-11 21:38:37 +01:00
Mike Kaganski 44ab8a915c Simplify XmlTestTools::dumpAndParse for default dumper case
... which is the majority of cases.
Make dumper's methods const, where it makes sense.

Change-Id: I4368a15d18bd0843a3c7b125b03bbbf623cd10c2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195424
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2025-12-11 15:56:00 +01:00
Gabor Kelemen 3ea68d1b8d tdf#146619 Run IWYU on e...
embeddedobj/ emfio/ extensions/ eventattacher/

Change-Id: I7a86b19d1c5ff3859cb5f97a4ef74cf8e01de3b6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190909
Tested-by: Jenkins
Reviewed-by: Gabor Kelemen <gabor.kelemen.extern@allotropia.de>
2025-09-23 16:24:45 +02:00
Bartosz Kosiorek b33cc5a738 tdf#159306 WMF/EMF Fix PS_COSMETIC lines display
Change-Id: I3a2572a76aae61bcf8552e4623168cd72411373a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190816
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2025-09-12 00:46:24 +02:00
Bartosz Kosiorek cd410d0f38 tdf#103859 EMF Fix size of the corners in ROUNDRECT record
After EMF_ROUNDRECT rendering comparison of Office 365 and
Libreoffice, it appears that radius of corners in LO is twice too large.
EMF_ROUNDRECT implementation has to be aligned and
conversion from ellipse width and height to ellipse vertical
and horizontal radius have been applied (values was divided by 2).

After apply this patch the ROUNDRECT looks identical as in Office.

The issue is also visible in previous version of LO (24.2.7).

Change-Id: I861fcd0e8d8a39d946215cc08ecc95403cd23fad
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190391
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Tested-by: Jenkins
2025-08-31 04:49:40 +02:00
Bartosz Kosiorek dea3d83e9a tdf#103859 EMF Improve interpolation of the EMR_ROUNDRECT by Bezier curve
Change-Id: I9d297489415e2b36e9566aa358d5eb9a2e94c398
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190146
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2025-08-27 21:47:26 +02:00
Noel Grandin 281aa3db6d BitmapEx->Bitmap in emfio
Since Bitmap can handle transparency now.

Which flushes out a bug in ImpGraphic::getBitmap - Since we are
returning a Bitmap capable of handling transparency, drop the code that
removes transparency

And also flushes out a silly typo in Bitmap::ReplaceTransparency

Change-Id: Ib4fb658e4b4ef6bba70484a1653ff9508859f1b2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190216
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2025-08-26 17:33:40 +02:00
Bartosz Kosiorek ccf1476f70 tdf#103859 EMF Fix quality of EMR_ELLIPSE by using Bazier curve for drawing
Change-Id: I7eaca22dac921229b4a88e07739d379948730bd9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189024
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Tested-by: Jenkins
2025-08-08 17:46:09 +02:00
Bartosz Kosiorek e24f16560d tdf#103859 EMF Fix quality of EMR_ROUNDRECT by using Bazier curve for drawing
As WMF and EMF is using integers and previous EMR_ROUNDRECT implementation
used many small lines to display curves, it produces low quality curves.
With this implementation using Bezier curves,
EMR_ROUNDRECT images are scalable without any loss of quality.

Change-Id: I3ef7f15ed9e3835065030bdf196b9bfa044d84a3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189016
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2025-08-06 22:06:09 +02:00
Bartosz Kosiorek 1b68f85903 tdf#167616 EMF Add support for EMR_ANGLEARC record
Change-Id: Ic872f80b2a318ac7c0f3b0cbdb4ad285795989c8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188865
Tested-by: Jenkins
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
2025-08-06 14:47:01 +02:00
Noel Grandin 047eb23bb4 BitmapEx->Bitmap in CreateFromData
now that Bitmap can handle transparency

Also add a utility method Bitmap::GetPixelColor, to use
in unit test code.

One of the unit tests needed tweaking because we are
converting back and forth a few times which adds some
inaccuracy.

Change-Id: I760c7da8845488e547b16ed243819fe3288b0985
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188537
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Jenkins
2025-08-01 09:31:43 +02:00
Noel Grandin 11b1557147 convert KernArray from sal_Int32 to double
which allows us to eliminate a bunch of rounding at various layers, and
consequently maintain a lot more precision

Change-Id: I911dedd7c041c1d67396c082e5695346ea689acb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175814
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2024-10-31 12:10:52 +01:00
Mike Kaganski a6a6921123 Use good old string literals in assertXPath and friends
These are only sent to an external API expecting char*-like strings,
or for comparison. Having every assertXPath having three of _[ou]str
is too much syntactic noise, making the unit tests almost unreadable.

Change-Id: Ic004a36ea75e7bfe0b96f405c40f926a957b51cc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174416
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Tested-by: Jenkins
2024-10-05 10:06:44 +02:00
Jonathan Clark 3bd4a79772 tdf#119785 Implement the EMF TA_RTLREADING alignment flag
EMF has two ways to indicate that text should be treated as RTL:

- The ExtTextOut ETO_RTLREADING flag
- The SetTextAlign TA_RTLREADING flag

Previously, only the former was implemented. This change implements the
latter.

Change-Id: If1023b4a0a3b6eb2ce47d2b764edbfd1a5c0dd5a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173579
Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
Tested-by: Jenkins
2024-09-18 05:59:51 +02:00
Xisco Fauli 629a9d68ee drawinglayer: getHeight() -> getWidth()
Since 01ded1e6d3
"WMF tdf#55058 tdf#142722 Add implementation of BitBlt and StretchBlt"

Change-Id: Ib99e940c954fe44f2dbee2b14dfa9d2c79468500
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172919
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
2024-09-05 20:06:21 +02:00
Noel Grandin c920881f39 loplugin:ostr in emfio
Change-Id: I3ec70a070fec1e62992eead0405ef689debb9fb7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167283
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2024-05-07 18:15:01 +02:00
Mike Kaganski cfa9990d47 Enable this test on all platforms
The original issue that prevented the test on Linux is reproducible.
I didn't debug the cause, so this is just a workaround.

Change-Id: Ifa8fa2a7884adabf797ea2d711f62b6be382dfec
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166351
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-04-20 11:28:25 +02:00
Mike Kaganski 089398e514 Return double from OutputDevice::GetTextArray
And introduce GetTextWidth / GetTextHeight variants returning double.
It allows to avoid premature rounding.

At least in one case - testTdf145111_anchor_in_Fontwork - it allowed
to make the test DPI-independent (at least in my testing on Windows,
using 125, 150, and 175% UI scaling).

Change-Id: I973d2c729ec6bb7114b4f99b9027f1ead7c1d061
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166237
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-04-20 08:53:26 +02:00
Mike Kaganski 1f1f423200 Round in XmlWriter::attribute when passing a double
Before, it truncated. Rounding provides a closer value.

Change-Id: I213e6ae34ada2f5081cb2c8b2ef431448c712b37
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165947
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-04-14 15:13:10 +02:00
Mike Kaganski 4695d84b78 Use more o3tl::convert
Change-Id: Ia525e051b53dd6082f2f11ff884677c8b8c6a20c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166051
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-04-13 18:48:38 +02:00
Mike Kaganski a01a642ebb UnoApiTest::loadFromURL -> UnoApiTest::loadFromFile
The old name was misleading (it doesn't take an URL, but a filename);
also, now it's easier to grep for it - doesn't get mixed with
vcl::graphic::loadFromURL.

Change-Id: Ib88d2194200a6a54d2326971e0306ba39f0c7025
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161578
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2024-01-03 07:51:28 +01:00
Stephan Bergmann 7575e8afca loplugin:ostr (macOS)
Change-Id: I1b169e0c170c26a49941d22f0982a24ef547f941
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160391
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
2023-12-07 07:15:25 +01:00