In commit 1d9f4ae520,
_cairo_matrix_has_unity_scale() was rewritten. As I understand the
commit message, the intention was to allow small rounding errors. In
practice however, this function would now also accepts matrices that it
should not, such as the matrix in the test added in the previous commit.
That matrix has a determinant of 1, but one axis is scaled by 5 and the
other one by 1/5.
In this commit, I revert the algorithmic change done in the function
above. This _cairo_matrix_has_unity_scale() now again compares all the
relevant fields of the matrix again without looking at the determinant.
To keep the intention of the above commit, this comparison still allows
some small inaccuracies.
This fixes the unit test added in the previous commit for most backends
(xlib*, xcb*, image, recording). The test still fails for svg, script,
ps, and image16.
Fixes: #927
Signed-off-by: Uli Schlachter <psychon@znc.in>
Make sure surface->object_stream.stream is cleaned up even if things
failed
In poppler oss-fuzz tests we are getting this leak reported
Direct leak of 64 byte(s) in 1 object(s) allocated from:
#0 0x5747417eabd9 in __interceptor_calloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:74:3
#1 0x574742706f5b in _cairo_memory_stream_create cairo/src/cairo-output-stream.c:741:14
#2 0x5747426757b8 in _cairo_pdf_surface_open_object_stream cairo/src/cairo-pdf-surface.c:2307:34
#3 0x57474266b880 in _cairo_pdf_surface_finish cairo/src/cairo-pdf-surface.c:2700:14
#4 0x57474261afc6 in _cairo_surface_finish cairo/src/cairo-surface.c:1043:11
#5 0x57474261afc6 in cairo_surface_finish cairo/src/cairo-surface.c:1092:5
#6 0x57474270808a in _cairo_paginated_surface_finish cairo/src/cairo-paginated-surface.c:215:2
#7 0x5747426175c2 in _cairo_surface_finish cairo/src/cairo-surface.c:1043:11
#8 0x5747426175c2 in cairo_surface_destroy cairo/src/cairo-surface.c:978:2
This fixes it.
_cairo_pdf_surface_finish was succeeding past
_cairo_pdf_surface_open_object_stream that allocates surface->object_stream.stream,
failing when calling _cairo_pdf_surface_emit_font_subsets
and that memory was never freed
They don't support C11 anyway. Additionally, CLang defines a very
conservative __GNUC__ value (which is also configurable via the
-fgnuc-version= command-line argument)
When cairo_is_all_clipped return true, we must not attempt
to change any of the clip fields, since it is pointing to
the static const __cairo_clip_all.
Moving the check for ->region into the 'if' is fine, since
it will always be NULL for _cairo_clip_all.
This was causing a crash in inkscape, see
https://gitlab.com/inkscape/inkscape/-/issues/5631
IDWriteGlyphRunAnalysis supports gray-scale antialiasing only when
created via IDWriteFactory2 (and newer), introduced in Windows 8.1
Fallback to using DIrect2D on A8 targets when IDWriteFactory2 is
not available.
...by checking for IUnknown.
This makes GeometryRecorder::QueryInterface compliant with the
rules of COM.
QueryInterface for IUnknown has a special meaning in COM: it's
used to check whether two interface pointers refer to the same
object.
STDMETHOD / IFACEMETHOD macros already add __declspec(nothrow), but
noexcept is better. From MSDN [1]:
We recommend that all new code use the noexcept operator rather than
__declspec(nothrow).
This attribute tells the compiler that the declared function and the
functions it calls never throw an exception. However, it does not
enforce the directive. In other words, it never causes std::terminate
to be invoked, unlike noexcept, or in std:c++17 mode (Visual Studio
2017 version 15.5 and later), throw().
See also [2]:
Non-throwing functions are permitted to call potentially-throwing
functions. Whenever an exception is thrown and the search for a handler
encounters the outermost block of a non-throwing function, the function
std::terminate is called:
extern void f(); // potentially-throwing
void g() noexcept {
f(); // valid, even if f throws
throw 42; // valid, effectively a call to std::terminate
}
References:
[1] https://learn.microsoft.com/en-us/cpp/cpp/nothrow-cpp?view=msvc-170
[2] https://en.cppreference.com/w/cpp/language/noexcept_spec
IFACEMETHOD already adds the __override / __allowed(on_function) SAL
annotation (only on Windows SDK, not mingw-w64), which is understood
by some code analysis tools [1]. Since we're compiling in C++11 mode,
we can add the override specifier, so that the compiler is informed
as well.
[1] https://devblogs.microsoft.com/oldnewthing/20200911-00/?p=104205
Fixes the following warnings on CLang:
../cairo/src/win32/cairo-dwrite-font.cpp:869:27: warning: exception specification
of overriding function is more lax than base version [-Wmicrosoft-exception-spec]
869 | IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode)
| ^
D:/msys64/clang64/include/d2d1.h:1491:22: note: overridden virtual function is here
1491 | STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode) PURE;
|
COM objects are usually implemented like that:
1. The class is defined with only method declarations. For that,
one should use IFACEMETHOD macros.
2. Then methods are implemented (defined), outside of the class
definition. For that, one should use the IFACEMETHODIMP macros
If one really wants to provide inline method definitions (that is,
inside the class definition), then IFACEMETHOD macros should be used
(and not IFACEMETHODIMP, though it's a definition / implementation).
...to _cairo_win32_print_api_error, since it should not be used
with most GDI functions. Also move the function definition to
cairo-win32-system.c and change argument signature.
Most GDI functions do not set the last error, so GetLastError() returns
unrelated error codes. There are some exceptions, however, like BitBlt
and CreateDIBSection.
Whether a GDI function sets the last error is stated in the reference
documentation on MSDN.
Bit-shifting a signed integer (which is what 1 is here) left is
undefined behavior – you can see it when compiling with
`-fsanitize=undefined`. Explicitly declaring 1 as unsigned fixes this.
...and make the code use that instead of the original IDWriteFontFace
in the font face subclass. We do that because to apply a few settings
(font variations) a new IDWriteFontFace must be created out of the
original one.
For now the IDWriteFontFace in the scaled font is a copy of the one in
the font face. In the next commit we'll add code to create a different
object.
DWRITE_GLYPH_IMAGE_FORMATS is now defined by dcommon.h
In file included from C:/msys64/ucrt64/include/minwindef.h:163,
from C:/msys64/ucrt64/include/windef.h:9,
from C:/msys64/ucrt64/include/windows.h:69,
from ..\src/cairo-mutex-impl-private.h:182,
from ..\src/cairo-mutex-type-private.h:45,
from ..\src/cairo-scaled-font-private.h:45,
from ..\src/cairoint.h:415,
from ../src/win32/cairo-dwrite-font.cpp:37:
../src/win32/dw-extra.h:26:1: error: redefinition of 'DWRITE_GLYPH_IMAGE_FORMATS operator|(DWRITE_GLYPH_IMAGE_FORMATS, DWRITE_GLYPH_IMAGE_FORMATS)'
26 | DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
C:/msys64/ucrt64/include/dcommon.h:67:1: note: 'DWRITE_GLYPH_IMAGE_FORMATS operator|(DWRITE_GLYPH_IMAGE_FORMATS, DWRITE_GLYPH_IMAGE_FORMATS)' previously defined here
67 | DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../src/cairo-colr-glyph-render.c:37:
../src/cairo-ft-private.h:87:30: error: unknown type name 'FT_Color'
87 | FT_Color *palette,
| ^~~~~~~~
Fixes https://gitlab.freedesktop.org/cairo/cairo/-/issues/792
Signed-off-by: Thomas Devoogdt <thomas@devoogdt.com>