To avoid any possibility of uninitialized memory.
The exceptions are:
- where the allocation is immediately overwritten by a memcpy or struct copy.
- arrays of structs to avoid any performance impact (except when the
array is returned by the public API).
The default RGB colorspace must be converted to the GPU's colorspace
using CGColorTransformConvertUsingCMSConverter. Profiling has shown this
function to consume as much as 48% of a redraw cycle in gdk-quartz.
There seems to be no named colorspace that matches the one stored on the
display, so we use the one associated with the main display. This has
some risks for users with multiple monitors but in testing with my own
two-monitor setup, one of which is HDR and the other not, the colorspace
was the same for both.
This is applied to quartz surfaces created with
cairo_quartz_surface_create(); surfaces created with
cairo_quartz_surface_create_for_cg_context will inherit the colorspace
from the context.
In order to generate PNGs that look right I've converted the
existing debugging functions for writing a quartz surface to png
into private functions and wired cairo-boilerplate-quartz to use
them. Using the generic cairo routine produced washed-out PNGs.
Fixes https://gitlab.freedesktop.org/cairo/cairo/-/issues/330
Use a CGBitmapContext mapping the underlying image surface's data instead
of maintaining a CGImage. Generalize the quartz surface snapshot mechanism
to work with both cairo_quartz_surface_t and cairo_quartz_image_surface_t
and to use the latter to get a CGContext around non-quartz surfaces.
Use this snapshot machanism to get a CGImageRef when needed from a
cairo_quartz_image_surface_t.
The problem is _cairo_recording_surface_replay_and_create_regions()
stores the cairo_recording_region_type_t in the same structure as the
recording commands. This does not work well when the recording surface
is used as source by multiple surfaces
Fix this by moving the cairo_recording_region_type_t into a separate
struct cairo_recording_regions_array_t. This struct is stored in a
list that allows multiple create regions results to be store in the
surface.
The new function _cairo_recording_surface_region_array_attach() is
used to create a new cairo_recording_regions_array_t, attach it to the
recording surface and return a unique region id.
The _cairo_recording_surface_replay_and_create_regions() and
_cairo_recording_surface_replay_region() functions use this region id
to identify the cairo_recording_regions_array_t.
To handle nested recording surfaces, when replaying a recording, the
region id is passed to the target as an extra parameter in the surface
pattern. The wrapper surface makes a temporary copy of the pattern to
ensure the snapshot pattern in the recording surface is not modified.
cairo_recording_regions_array_t has a reference count so the target
can hold on to the cairo_recording_regions_array_t after the paginated
surface has called _cairo_recording_surface_region_array_remove().
Since the if/else was replaced by a switch() here in 2e0075e265,
the size field of pbounds is not being set in the EXTEND_NONE case,
which means we end up passing uninitialized values to CGPatternCreate.
CGContextDrawTiledImage turned up as a significant time-user while
profiling a benchmark created to evaluate
https://gitlab.gnome.org/GNOME/gtk/-/issues/3714. Without this commit
the benchmark is able to perform a mean frame rate of 2.19 frames per
second with a standard deviation of 0.09; with the commit the mean frame
rate is 2.37 fps, s.d. 0.30, both over 15 10-second samples. Student's
t-test reports a 9.8% likelyhood that the two represent the same
distribution.
Motivation: Avoid need to recreate CGImages for unchanged surfaces,
an expensive operation, while ensuring that the CGImages are properly
freed and new ones created when the surface does change.
Thanks to Uli Schlacter for suggestion and coding guidance.
We define _GNU_SOURCE globally in both the Autotools build, through the
use of the AC_USE_SYSTEM_EXTENSIONS macro; and in the Meson build, with
add_project_arguments().
Since we now copy the data that CGImage needs we don't need to
keep the surface around anymore, nor release it or the image in the
DataProviderReleaseCallback.
_cairo_malloc(0) always returns NULL, but has not been used
consistently. This patch replaces many calls to malloc() with
_cairo_malloc().
Fixes: fdo# 101547
CVE: CVE-2017-9814 Heap buffer overflow at cairo-truetype-subset.c:1299
Reviewed-by: Bryce Harrington <bryce@osg.samsung.com>
Some blend operators have a (small, but potentially noticeable)
different behaviour in Quartz and pixman. Use the Quartz ones only for
the operators which match pixman except for rounding errors.
Fixes:
- extended-blend
- extended-blend-alpha
- extended-blend-mask
- extended-blend-alpha-mask
- extended-blend-solid
- extended-blend-solid-alpha
The Quartz framework provides several quality settings, but they were
not used. Now the translation of cairo_filter_t to Quartz filtering
modes tries to match the quality settings from image as much as
possible.
Specifically, CAIRO_FILTER_GOOD and CAIRO_FILTER_BILINEAR are now
converted to kCGInterpolationLow, which seems to be a bilinear filter.
Fixes:
- pixman-downscale-bilinear-24
- pixman-downscale-bilinear-95
- pixman-downscale-good-24
- pixman-downscale-good-95
- pthread-same-source
- recording-surface-extend-none
- recording-surface-extend-reflect
- recording-surface-extend-repeat
- recording-surface-over
- recording-surface-source
- surface-pattern-big-scale-down
- surface-pattern-scale-down
- surface-pattern-scale-down-extend-none
- surface-pattern-scale-down-extend-reflect
- surface-pattern-scale-down-extend-repeat
The quartz-image backend uses _cairo_surface_is_quartz(), which
therefore needs to be made available to it. Fixed as suggested by
Bryce in the referenced bugreport.
References: https://bugs.freedesktop.org/show_bug.cgi?id=84569
Signed-off-by: Andrea Canciani <ranma42@gmail.com>
This is a follow-up patch on top of 150c1e7044
As discussed in the mailing list, http://lists.cairographics.org/archives/cairo/2014-September/025647.html,
check if the surfaces are of particular backend type or not, before proceeding further.
These changes are based on _cairo_surface_is_xlib() and _cairo_surface_is_image()
Signed-off-by: Ravi Nanjundappa <nravi.n@samsung.com>
Recording surfaces should be replayed with the transform matrix used
in the pattern, otherwise the image surface will be transformed,
introducing artifacts.
Fixes record{1414x,2x}-paint-alpha-{,solid-clip,clip},
record2x-{self-intersecting,text-transform} and record90-paint-alpha.
and reuse it to implement acquire_source.
Fixes
cairo-quartz-surface.c: In function '_cairo_quartz_surface_map_to_image':
cairo-quartz-surface.c:1568: warning: return from incompatible pointer type
cairo-quartz-surface.c:1576: warning: return from incompatible pointer type
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
Documentation comments should always start with "/**" and end with
"**/". This is not required by gtk-doc, but it makes the
documentations formatting more consistent and simplifies the checking
of documentation comments.
The following Python script tries to enforce this.
from sys import argv
from sre import search
for filename in argv[1:]:
in_doc = False
lines = open(filename, "r").read().split("\n")
for i in range(len(lines)):
ls = lines[i].strip()
if ls == "/**":
in_doc = True
elif in_doc and ls == "*/":
lines[i] = " **/"
if ls.endswith("*/"):
in_doc = False
out = open(filename, "w")
out.write("\n".join(lines))
out.close()
This fixes most 'documentation comment not closed with **/' warnings
by check-doc-syntax.awk.
CAIRO_ANTIALIAS_{FAST,GOOD,BEST} were introduced and used in
cairo-quartz-font.c by commit 70cd3b473d.
Fixes the warnings:
cairo-quartz-surface.c: In function '_cairo_quartz_cg_glyphs':
cairo-quartz-surface.c:1976: warning: enumeration value 'CAIRO_ANTIALIAS_FAST' not handled in switch
cairo-quartz-surface.c:1976: warning: enumeration value 'CAIRO_ANTIALIAS_GOOD' not handled in switch
cairo-quartz-surface.c:1976: warning: enumeration value 'CAIRO_ANTIALIAS_BEST' not handled in switch