/* Some of these are present in earlier versions of the OS than where *theyarepublic;otherarenotpublicatall
*/ /* public since 10.5 */ staticvoid (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL;
/* public since 10.6 */ static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL; staticvoid (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
/* not yet public */ staticunsignedint (*CGContextGetTypePtr) (CGContextRef) = NULL; staticbool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
/* CTFontDrawGlyphs is not available until 10.7 */ staticvoid (*CTFontDrawGlyphsPtr) (CTFontRef, const CGGlyph[], const CGPoint[], size_t, CGContextRef) = NULL;
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050 static PrivateCGCompositeMode
_cairo_quartz_cairo_operator_to_quartz_composite (cairo_operator_t op)
{ switch (op) { case CAIRO_OPERATOR_CLEAR: return kPrivateCGCompositeClear; case CAIRO_OPERATOR_SOURCE: return kPrivateCGCompositeCopy; case CAIRO_OPERATOR_OVER: return kPrivateCGCompositeSourceOver; case CAIRO_OPERATOR_IN: return kPrivateCGCompositeSourceIn; case CAIRO_OPERATOR_OUT: return kPrivateCGCompositeSourceOut; case CAIRO_OPERATOR_ATOP: return kPrivateCGCompositeSourceAtop; case CAIRO_OPERATOR_DEST_OVER: return kPrivateCGCompositeDestinationOver; case CAIRO_OPERATOR_DEST_IN: return kPrivateCGCompositeDestinationIn; case CAIRO_OPERATOR_DEST_OUT: return kPrivateCGCompositeDestinationOut; case CAIRO_OPERATOR_DEST_ATOP: return kPrivateCGCompositeDestinationAtop; case CAIRO_OPERATOR_XOR: return kPrivateCGCompositeXOR; case CAIRO_OPERATOR_ADD: return kPrivateCGCompositePlusLighter;
case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_SATURATE: case CAIRO_OPERATOR_MULTIPLY: case CAIRO_OPERATOR_SCREEN: case CAIRO_OPERATOR_OVERLAY: case CAIRO_OPERATOR_DARKEN: case CAIRO_OPERATOR_LIGHTEN: case CAIRO_OPERATOR_COLOR_DODGE: case CAIRO_OPERATOR_COLOR_BURN: case CAIRO_OPERATOR_HARD_LIGHT: case CAIRO_OPERATOR_SOFT_LIGHT: case CAIRO_OPERATOR_DIFFERENCE: case CAIRO_OPERATOR_EXCLUSION: case CAIRO_OPERATOR_HSL_HUE: case CAIRO_OPERATOR_HSL_SATURATION: case CAIRO_OPERATOR_HSL_COLOR: case CAIRO_OPERATOR_HSL_LUMINOSITY: default:
ASSERT_NOT_REACHED;
}
} #endif
static CGBlendMode
_cairo_quartz_cairo_operator_to_quartz_blend (cairo_operator_t op)
{ switch (op) { case CAIRO_OPERATOR_MULTIPLY: return kCGBlendModeMultiply; case CAIRO_OPERATOR_SCREEN: return kCGBlendModeScreen; case CAIRO_OPERATOR_OVERLAY: return kCGBlendModeOverlay; case CAIRO_OPERATOR_DARKEN: return kCGBlendModeDarken; case CAIRO_OPERATOR_LIGHTEN: return kCGBlendModeLighten; case CAIRO_OPERATOR_COLOR_DODGE: return kCGBlendModeColorDodge; case CAIRO_OPERATOR_COLOR_BURN: return kCGBlendModeColorBurn; case CAIRO_OPERATOR_HARD_LIGHT: return kCGBlendModeHardLight; case CAIRO_OPERATOR_SOFT_LIGHT: return kCGBlendModeSoftLight; case CAIRO_OPERATOR_DIFFERENCE: return kCGBlendModeDifference; case CAIRO_OPERATOR_EXCLUSION: return kCGBlendModeExclusion; case CAIRO_OPERATOR_HSL_HUE: return kCGBlendModeHue; case CAIRO_OPERATOR_HSL_SATURATION: return kCGBlendModeSaturation; case CAIRO_OPERATOR_HSL_COLOR: return kCGBlendModeColor; case CAIRO_OPERATOR_HSL_LUMINOSITY: return kCGBlendModeLuminosity;
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 case CAIRO_OPERATOR_CLEAR: return kCGBlendModeClear; case CAIRO_OPERATOR_SOURCE: return kCGBlendModeCopy; case CAIRO_OPERATOR_OVER: return kCGBlendModeNormal; case CAIRO_OPERATOR_IN: return kCGBlendModeSourceIn; case CAIRO_OPERATOR_OUT: return kCGBlendModeSourceOut; case CAIRO_OPERATOR_ATOP: return kCGBlendModeSourceAtop; case CAIRO_OPERATOR_DEST_OVER: return kCGBlendModeDestinationOver; case CAIRO_OPERATOR_DEST_IN: return kCGBlendModeDestinationIn; case CAIRO_OPERATOR_DEST_OUT: return kCGBlendModeDestinationOut; case CAIRO_OPERATOR_DEST_ATOP: return kCGBlendModeDestinationAtop; case CAIRO_OPERATOR_XOR: return kCGBlendModeXOR; case CAIRO_OPERATOR_ADD: return kCGBlendModePlusLighter; #else case CAIRO_OPERATOR_CLEAR: case CAIRO_OPERATOR_SOURCE: case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_IN: case CAIRO_OPERATOR_OUT: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST_OVER: case CAIRO_OPERATOR_DEST_IN: case CAIRO_OPERATOR_DEST_OUT: case CAIRO_OPERATOR_DEST_ATOP: case CAIRO_OPERATOR_XOR: case CAIRO_OPERATOR_ADD: #endif
case CAIRO_OPERATOR_DEST: case CAIRO_OPERATOR_SATURATE: default:
ASSERT_NOT_REACHED;
} return kCGBlendModeNormal; /* just to silence clang warning [-Wreturn-type] */
}
/* Quartz doesn't support SATURATE at all. COLOR_DODGE and *COLOR_BURNinQuartzfollowtheISO32000definition,butcairo *usesthedefinitionfromtheAdobeSupplement.Alsofallback *onSOFT_LIGHTandHSL_HUE,becausetheirresultsare *significantlydifferentfromthoseprovidedbypixman.
*/ if (op == CAIRO_OPERATOR_SATURATE ||
op == CAIRO_OPERATOR_SOFT_LIGHT ||
op == CAIRO_OPERATOR_HSL_HUE ||
op == CAIRO_OPERATOR_COLOR_DODGE ||
op == CAIRO_OPERATOR_COLOR_BURN)
{ return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* When the destination has no color components, we can avoid some *fallbacks,butwehavetoworkaroundoperatorswhichbehave
* differently in Quartz. */ if (surface->base.content == CAIRO_CONTENT_ALPHA) {
assert (op != CAIRO_OPERATOR_ATOP); /* filtered by surface layer */
if (op == CAIRO_OPERATOR_SOURCE ||
op == CAIRO_OPERATOR_IN ||
op == CAIRO_OPERATOR_OUT ||
op == CAIRO_OPERATOR_DEST_IN ||
op == CAIRO_OPERATOR_DEST_ATOP ||
op == CAIRO_OPERATOR_XOR)
{ return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (op == CAIRO_OPERATOR_DEST_OVER)
op = CAIRO_OPERATOR_OVER; elseif (op == CAIRO_OPERATOR_SATURATE)
op = CAIRO_OPERATOR_ADD; elseif (op == CAIRO_OPERATOR_COLOR_DODGE)
op = CAIRO_OPERATOR_OVER; elseif (op == CAIRO_OPERATOR_COLOR_BURN)
op = CAIRO_OPERATOR_OVER;
}
case CAIRO_LINE_JOIN_MITER: return kCGLineJoinMiter;
case CAIRO_LINE_JOIN_ROUND: return kCGLineJoinRound;
case CAIRO_LINE_JOIN_BEVEL: return kCGLineJoinBevel;
}
}
staticinline CGInterpolationQuality
_cairo_quartz_filter_to_quartz (cairo_filter_t filter)
{ /* The CGInterpolationQuality enumeration values seem to have the *followingmeaning: *-kCGInterpolationNone:nearestneighbor *-kCGInterpolationLow:bilinear *-kCGInterpolationHigh:bicubic?Lanczos?
*/
switch (filter) { case CAIRO_FILTER_NEAREST: case CAIRO_FILTER_FAST: return kCGInterpolationNone;
case CAIRO_FILTER_BEST: return kCGInterpolationHigh;
case CAIRO_FILTER_GOOD: case CAIRO_FILTER_BILINEAR: return kCGInterpolationLow;
case CAIRO_FILTER_GAUSSIAN: return kCGInterpolationDefault;
/* Quartz computes a small number of samples of the gradient color *function.OnMacOSX10.5itapparentlycomputesonly1024
* samples. */ #define MAX_GRADIENT_RANGE 1024
if (gradient->base.extend == CAIRO_EXTEND_PAD) {
t[0] = MAX (t[0], -0.5);
t[1] = MIN (t[1], 1.5);
} elseif (t[1] - t[0] > MAX_GRADIENT_RANGE) return NULL;
/* set the input range for the function -- the function knows how
to map values outside of 0.0 .. 1.0 to the correct color */
input_value_range[0] = t[0];
input_value_range[1] = t[1];
} else {
input_value_range[0] = 0;
input_value_range[1] = 1;
}
image_data = _cairo_malloc_ab (image_surface->height, image_surface->stride); if (unlikely (!image_data))
{ if (acquired)
_cairo_surface_release_source_image (source, image_surface, image_extra); else
cairo_surface_destroy (&image_surface->base);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
// The last row of data may have less than stride bytes so make sure we // only copy the minimum amount required from that row.
memcpy (image_data, image_surface->data,
(image_surface->height - 1) * image_surface->stride +
cairo_format_stride_for_width (image_surface->format,
image_surface->width));
*image_out = CairoQuartzCreateCGImage (image_surface->format,
image_surface->width,
image_surface->height,
image_surface->stride,
image_data, TRUE,
NULL,
DataProviderReleaseCallback,
image_data);
/* TODO: differentiate memory error and unsupported surface type */ if (unlikely (*image_out == NULL))
status = CAIRO_INT_STATUS_UNSUPPORTED;
if (acquired)
_cairo_surface_release_source_image (source, image_surface, image_extra); else
cairo_surface_destroy (&image_surface->base);
return status;
}
/* Generic #cairo_pattern_t -> CGPattern function */
CGContextDrawImage (context, info->imageBounds, info->image); if (info->do_reflect) { /* draw 3 more copies of the image, flipped. *DrawImagedrawstheimageaccordingtothecurrentY-directionintotherectanglegiven *(imageBounds);atthetimeofthefirstDrawImageabove,theoriginisatthebottomleft *ofthebaseimageposition,andtheYaxisisextendingupwards.
*/
/* Make the y axis extend downwards, and draw a flipped image below */
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, info->imageBounds, info->image);
/* Shift over to the right, and flip vertically (translation is 2x, *sincewe'llbeflippingandthusrenderingtherectangle"backwards"
*/
CGContextTranslateCTM (context, 2 * info->imageBounds.size.width, 0);
CGContextScaleCTM (context, -1, 1);
CGContextDrawImage (context, info->imageBounds, info->image);
/* Then unflip the Y-axis again, and draw the image above the point. */
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, info->imageBounds, info->image);
}
}
/* The pattern matrix is relative to the bottom left, again; the *incomingcairopatternmatrixisrelativetotheupperleft. *Sowetakethepatternmatrixandtheoriginalcontextmatrix, *whichgivesusthecorrectbasetranslation/yflip.
*/
ptransform = CGAffineTransformConcat (stransform, dest->cgContextBaseCTM);
/* Source layer to be rendered when using DO_LAYER. Unlike'layer'above,thisisnotownedbythedrawingstate
but by the source surface. */
CGLayerRef sourceLayer;
} cairo_quartz_drawing_state_t;
/* Quartz seems to tile images at pixel-aligned regions only -- this *leadstoseamsiftheimagedoesn'tendupscalingtofillthe *spaceexactly.TheCGPatterntilingapproachdoesn'thavethis *problem.Checkifwe'regoingtofillupthespace(withinsome *epsilon),andifnot,fallbacktotheCGPatterntype.
*/
if ((fw & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON &&
(fh & CAIRO_FIXED_FRAC_MASK) <= CAIRO_FIXED_EPSILON)
{ /* We're good to use DrawTiledImage, but ensure that
* the math works out */
// let's hope they don't add YUV under us
colorspace = CGBitmapContextGetColorSpace (surface->cgContext);
color_comps = CGColorSpaceGetNumberOfComponents(colorspace);
// XXX TODO: We can handle all of these by converting to // pixman masks, including non-native-endian masks if (bpc != 8) return CAIRO_INT_STATUS_UNSUPPORTED;
if (bpp != 32 && bpp != 8) return CAIRO_INT_STATUS_UNSUPPORTED;
if (color_comps != 3 && color_comps != 1) return CAIRO_INT_STATUS_UNSUPPORTED;
if (IS_EMPTY (surface)) return CAIRO_STATUS_SUCCESS;
/* Restore our saved gstate that we use to reset clipping */
CGContextRestoreGState (surface->cgContext);
_cairo_surface_clipper_reset (&surface->clipper);
/* ClipToMask is essentially drawing an image, so we need to flip the CTM
* to get the image to appear oriented the right way */
CGContextConcatCTM (state.cgMaskContext, CGAffineTransformInvert (mask_matrix));
CGContextTranslateCTM (state.cgMaskContext, 0.0, rect.size.height);
CGContextScaleCTM (state.cgMaskContext, 1.0, -1.0);
if (! need_temp) {
mask_surf = extents->mask_pattern.surface.surface;
/* When an opaque surface used as a mask in Quartz, its *luminosityisusedasthealphavalue,sowecononlyuse
* surfaces with alpha without creating a temporary mask. */
need_temp = ! (mask_surf->content & CAIRO_CONTENT_ALPHA);
}
if (! need_temp) {
CGInterpolationQuality mask_filter;
cairo_bool_t simple_transform;
/* Quartz only allows one interpolation to be set for mask and *source,sowecanskipthetempsurfaceonlyifthesource
* filtering makes the mask look correct. */ if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
need_temp = ! (simple_transform || filter == mask_filter); else
filter = mask_filter;
}
if (need_temp) { /* Render the mask to a surface */
mask_surf = _cairo_quartz_surface_create_similar (surface,
CAIRO_CONTENT_ALPHA,
surface->extents.width,
surface->extents.height);
status = mask_surf->status; if (unlikely (status)) goto BAIL;
/* mask_surf is clear, so use OVER instead of SOURCE to avoid a
* temporary layer or fallback to cairo-image. */
status = _cairo_surface_paint (mask_surf, CAIRO_OPERATOR_OVER, mask, NULL); if (unlikely (status)) goto BAIL;
cairo_matrix_init_identity (&matrix);
}
status = _cairo_quartz_cg_mask_with_surface (extents,
mask_surf, &matrix, filter);
rv = _cairo_quartz_setup_state (&state, extents); if (unlikely (rv)) goto BAIL;
// Turning antialiasing off used to cause misrendering with // single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels). // That's been since fixed in at least 10.5, and in the latest 10.4 dot releases.
CGContextSetShouldAntialias (state.cgMaskContext, (antialias != CAIRO_ANTIALIAS_NONE));
CGContextSetLineWidth (state.cgMaskContext, style->line_width);
CGContextSetLineCap (state.cgMaskContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
CGContextSetLineJoin (state.cgMaskContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
CGContextSetMiterLimit (state.cgMaskContext, style->miter_limit);
/* Convert glyph positions to glyph advances. */
cg_glyphs[0] = glyphs[0].index; for (i = 1; i < num_glyphs; i++) {
CGSize advance = CGSizeMake (glyphs[i].x - glyphs[i-1].x,
glyphs[i].y - glyphs[i-1].y);
cg_advances[i] = CGSizeApplyAffineTransform (advance, invTextTransform);
cg_glyphs[i] = glyphs[i].index;
}
if (CTFontDrawGlyphsPtr) { /* If CTFontDrawGlyphs is available, we want to use that *insteadofthedeprecatedCGContextShowGlyphsWithAdvances *sothatcolored-bitmapfontslikeAppleColorEmojiwill
* render properly. */
/* Accumulate the glyph advances into glyph positions, *overwritingthem.Startat(0,0)becausetheCTMalready
* takes into account the position of the first glyph. */
CGPoint pos = CGPointMake (0, 0);
cg_positions = (CGPoint *) cg_advances;
cg_positions[0] = pos; for (i = 1; i < num_glyphs; i++) {
pos.x += cg_advances[i].width;
pos.y += cg_advances[i].height;
cg_positions[i] = pos;
}
/* Revert the changes to the CTM. This fragment cannot rely on
* CG{Save,Restore}GState, as that would reset the clip. */
CGContextConcatCTM (state.cgMaskContext, invTextTransform);
CGContextTranslateCTM (state.cgMaskContext, -glyphs[0].x, -glyphs[0].y);
if (state.action != DO_DIRECT)
_cairo_quartz_draw_source (&state, extents->op);
BAIL: if (didForceFontSmoothing)
CGContextSetAllowsFontSmoothingPtr (state.cgMaskContext, FALSE);
_cairo_quartz_teardown_state (&state, extents);
if (cg_advances != cg_advances_static)
free (cg_advances);
if (IS_EMPTY (surface)) return CAIRO_STATUS_SUCCESS;
if (path == NULL) { /* If we're being asked to reset the clip, we can only do it *byrestoringthegstatetoourprevioussavedone,and *savingitagain. * *NotethatthisassumesthatALLquartzsurfacecreation *functionswilldoaSaveGStatefirst;wedothisincreate_internal.
*/
CGContextRestoreGState (surface->cgContext);
CGContextSaveGState (surface->cgContext);
} else {
CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
if (fill_rule == CAIRO_FILL_RULE_WINDING)
CGContextClip (surface->cgContext); else
CGContextEOClip (surface->cgContext);
}
ND ((stderr, "-- intersect_clip_path\n"));
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_quartz_surface_link (cairo_quartz_surface_t *surface,
cairo_bool_t begin, constchar *attributes)
{
cairo_link_attrs_t link_attrs;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS; int i, num_rects;
/* We only process the 'begin' tag, and expect a rect attribute; usingtheextentsofthedrawingoperationsenclosedbythebegin/end
link tags to define the clickable area is not implemented. */ if (!begin) return status;
status = _cairo_tag_parse_link_attributes (attributes, &link_attrs); if (unlikely (status)) return status;
num_rects = _cairo_array_num_elements (&link_attrs.rects); if (num_rects > 0) { /* Create either a named destination or a URL, depending which is present
in the link attributes. */
CFURLRef url = NULL;
CFStringRef name = NULL; if (link_attrs.uri && *link_attrs.uri)
url = CFURLCreateWithBytes (NULL,
(const UInt8 *) link_attrs.uri,
strlen (link_attrs.uri),
kCFStringEncodingUTF8,
NULL); elseif (link_attrs.dest && *link_attrs.dest)
name = CFStringCreateWithBytes (kCFAllocatorDefault,
(const UInt8 *) link_attrs.dest,
strlen (link_attrs.dest),
kCFStringEncodingUTF8, FALSE); else/* silently ignore link that doesn't have a usable target */ goto cleanup;
for (i = 0; i < num_rects; i++) {
CGRect link_rect;
cairo_rectangle_t rectf;
_cairo_array_copy_element (&link_attrs.rects, i, &rectf);
/* Currently the only tags we support are CAIRO_TAG_LINK and CAIRO_TAG_DEST */ if (!strcmp (tag_name, CAIRO_TAG_LINK)) return _cairo_quartz_surface_link (surface, begin, attributes);
if (!strcmp (tag_name, CAIRO_TAG_DEST)) return _cairo_quartz_surface_dest (surface, begin, attributes);
/* Unknown tag names are silently ignored here. */ return CAIRO_INT_STATUS_SUCCESS;
}
// XXXtodo implement show_page; need to figure out how to handle begin/end
/* Save so we can always get back to a known-good CGContext -- this is *requiredforproperbehaviourofintersect_clip_path(NULL)
*/
CGContextSaveGState (cgContext);
if (!_cairo_quartz_verify_surface_size(width, height)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
/* If we pass zero width or height into CGLayerCreateWithContext below, *itwillfail.
*/ if (width == 0 || height == 0) { return (cairo_surface_t*)
_cairo_quartz_surface_create_internal (NULL, content,
width, height);
}
ctx = CGLayerGetContext (layer); /* Flip it when we draw into it, so that when we finally composite it *toaflippedtarget,thedirectionsmatchandQuartzwilloptimize *thecompositionproperly
*/
CGContextTranslateCTM (ctx, 0, height);
CGContextScaleCTM (ctx, 1, -1);
CGContextRetain (ctx);
surf = _cairo_quartz_surface_create_internal (ctx, content,
width, height); if (surf->base.status) {
CGLayerRelease (layer); // create_internal will have set an error return (cairo_surface_t*) surf;
}
surf->cgLayer = layer;
if (format == CAIRO_FORMAT_ARGB32 ||
format == CAIRO_FORMAT_RGB24)
{
cgColorspace = CGColorSpaceCreateDeviceRGB ();
bitinfo = kCGBitmapByteOrder32Host; if (format == CAIRO_FORMAT_ARGB32)
bitinfo |= kCGImageAlphaPremultipliedFirst; else
bitinfo |= kCGImageAlphaNoneSkipFirst;
bitsPerComponent = 8;
stride = width * 4;
} elseif (format == CAIRO_FORMAT_A8) {
cgColorspace = NULL;
stride = width;
bitinfo = kCGImageAlphaOnly;
bitsPerComponent = 8;
} elseif (format == CAIRO_FORMAT_A1) { /* I don't think we can usefully support this, as defined by *cairo_format_t--theseare1-bitpixelsstoredin32-bit *quantities.
*/ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
} else { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
}
/* The Apple docs say that for best performance, the stride and the data *pointershouldbe16-bytealigned.mallocalreadyalignsto16-bytes, *sowedon'thavetoanythingspecialonallocation.
*/
stride = (stride + 15) & ~15;
if (!cgc) {
free (imageData); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
/* flip the Y axis */
CGContextTranslateCTM (cgc, 0.0, height);
CGContextScaleCTM (cgc, 1.0, -1.0);
surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
width, height); if (surf->base.status) {
CGContextRelease (cgc);
free (imageData); // create_internal will have set an error return &surf->base;
}
GraphicsExportComponent grex = 0; unsignedlong sizeWritten;
ComponentResult result;
// create the data reference
result = QTNewDataReferenceFromFullPathCFString (inPath, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
if (NULL != dataRef && noErr == result) { // get the PNG exporter
result = OpenADefaultComponent (GraphicsExporterComponentType, kQTFileTypePNG,
&grex);
if (grex) { // tell the exporter where to find its source image
result = GraphicsExportSetInputCGImage (grex, inImageRef);
if (noErr == result) { // tell the exporter where to save the exporter image
result = GraphicsExportSetOutputDataReference (grex, dataRef,
dataRefType);
if (noErr == result) { // write the PNG file
result = GraphicsExportDoExport (grex, &sizeWritten);
}
}
// remember to close the component
CloseComponent (grex);
}
// remember to dispose of the data reference handle
DisposeHandle (dataRef);
}
}
if (dest == NULL) {
fprintf (stderr, "** Writing %p to foo%d\n", nq, sctr);
sprintf (sptr, "/Users/vladimir/Desktop/foo%d.png", sctr);
sctr++;
dest = sptr;
}
CGImageRef imgref = CGBitmapContextCreateImage (nq->cgContext); if (imgref == NULL) {
fprintf (stderr, "quartz surface at %p is not a bitmap context!\n", nq); return;
}
ExportCGImageToPNGFile (imgref, dest);
CGImageRelease (imgref);
}
#endif/* QUARTZ_DEBUG */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.34 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.