void structGraphicsScreen :: v_fillArea (long numberOfPoints, double *xyDC) { #if cairo if (our d_cairoGraphicsContext == NULL) return; // cairo_new_path (our d_cairoGraphicsContext); // move_to() automatically creates a new path cairo_move_to (our d_cairoGraphicsContext, xyDC [0], xyDC [1]); for (long i = 1; i < numberOfPoints; i ++) cairo_line_to (our d_cairoGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); cairo_close_path (our d_cairoGraphicsContext); cairo_fill (our d_cairoGraphicsContext); #elif win MY_BRUSH BeginPath (our d_gdiGraphicsContext); MoveToEx (our d_gdiGraphicsContext, xyDC [0], xyDC [1], NULL); for (long i = 1; i < numberOfPoints; i ++) LineTo (our d_gdiGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); EndPath (our d_gdiGraphicsContext); FillPath (our d_gdiGraphicsContext); DEFAULT #elif mac GraphicsQuartz_initDraw (this); quartzPrepareFill (this); CGContextBeginPath (our d_macGraphicsContext); CGContextMoveToPoint (our d_macGraphicsContext, xyDC [0], xyDC [1]); for (long i = 1; i < numberOfPoints; i ++) { CGContextAddLineToPoint (our d_macGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); } CGContextFillPath (our d_macGraphicsContext); GraphicsQuartz_exitDraw (this); #endif }
static void _GraphicsScreen_imageFromFile (GraphicsScreen me, const wchar_t *relativeFileName, double x1, double x2, double y1, double y2) { long x1DC = wdx (x1), x2DC = wdx (x2), y1DC = wdy (y1), y2DC = wdy (y2); long width = x2DC - x1DC, height = my yIsZeroAtTheTop ? y1DC - y2DC : y2DC - y1DC; #if 0 structMelderFile file = { 0 }; Melder_relativePathToFile (relativeFileName, & file); try { autoPhoto photo = Photo_readFromImageFile (& file); if (x1 == x2 && y1 == y2) { width = photo -> nx, x1DC -= width / 2, x2DC = x1DC + width; height = photo -> ny, y2DC -= height / 2, y1DC = y2DC + height; } else if (x1 == x2) { width = height * (double) photo -> nx / (double) photo -> ny; x1DC -= width / 2, x2DC = x1DC + width; } else if (y1 == y2) { height = width * (double) photo -> ny / (double) photo -> nx; y2DC -= height / 2, y1DC = y2DC + height; } autoNUMmatrix <double_rgbt> z (1, photo -> ny, 1, photo -> nx); for (long iy = 1; iy <= photo -> ny; iy ++) { for (long ix = 1; ix <= photo -> nx; ix ++) { z [iy] [ix]. red = photo -> d_red -> z [iy] [ix]; z [iy] [ix]. green = photo -> d_green -> z [iy] [ix]; z [iy] [ix]. blue = photo -> d_blue -> z [iy] [ix]; z [iy] [ix]. transparency = photo -> d_transparency -> z [iy] [ix]; } } _cellArrayOrImage (me, NULL, z.peek(), NULL, 1, photo -> nx, x1DC, x2DC, 1, photo -> ny, y1DC, y2DC, 0.0, 1.0, //wdx (my d_x1WC), wdx (my d_x2WC), wdy (my d_y1WC), wdy (my d_y2WC), // in case of clipping LONG_MIN, LONG_MAX, LONG_MAX, LONG_MIN, // in case of no clipping true); } catch (MelderError) { Melder_clearError (); } #elif win if (my d_useGdiplus) { structMelderFile file = { 0 }; Melder_relativePathToFile (relativeFileName, & file); Gdiplus::Bitmap image (file. path); if (x1 == x2 && y1 == y2) { width = image. GetWidth (), x1DC -= width / 2, x2DC = x1DC + width; height = image. GetHeight (), y2DC -= height / 2, y1DC = y2DC + height; } else if (x1 == x2) { width = height * (double) image. GetWidth () / (double) image. GetHeight (); x1DC -= width / 2, x2DC = x1DC + width; } else if (y1 == y2) { height = width * (double) image. GetHeight () / (double) image. GetWidth (); y2DC -= height / 2, y1DC = y2DC + height; } Gdiplus::Graphics dcplus (my d_gdiGraphicsContext); Gdiplus::Rect rect (x1DC, y2DC, width, height); dcplus. DrawImage (& image, rect); } else { } #elif mac structMelderFile file = { 0 }; Melder_relativePathToFile (relativeFileName, & file); char utf8 [500]; Melder_wcsTo8bitFileRepresentation_inline (file. path, utf8); CFStringRef path = CFStringCreateWithCString (NULL, utf8, kCFStringEncodingUTF8); CFURLRef url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, false); CFRelease (path); CGImageSourceRef imageSource = CGImageSourceCreateWithURL (url, NULL); CFRelease (url); if (imageSource != NULL) { CGImageRef image = CGImageSourceCreateImageAtIndex (imageSource, 0, NULL); CFRelease (imageSource); if (image != NULL) { if (x1 == x2 && y1 == y2) { width = CGImageGetWidth (image), x1DC -= width / 2, x2DC = x1DC + width; height = CGImageGetHeight (image), y2DC -= height / 2, y1DC = y2DC + height; } else if (x1 == x2) { width = height * (double) CGImageGetWidth (image) / (double) CGImageGetHeight (image); x1DC -= width / 2, x2DC = x1DC + width; } else if (y1 == y2) { height = width * (double) CGImageGetHeight (image) / (double) CGImageGetWidth (image); y2DC -= height / 2, y1DC = y2DC + height; } GraphicsQuartz_initDraw (me); CGContextSaveGState (my d_macGraphicsContext); NSCAssert(my d_macGraphicsContext, @"nil context"); CGContextTranslateCTM (my d_macGraphicsContext, 0, y1DC); CGContextScaleCTM (my d_macGraphicsContext, 1.0, -1.0); CGContextDrawImage (my d_macGraphicsContext, CGRectMake (x1DC, 0, width, height), image); CGContextRestoreGState (my d_macGraphicsContext); GraphicsQuartz_exitDraw (me); CGImageRelease (image); } } #endif }
static void _GraphicsScreen_cellArrayOrImage (GraphicsScreen me, double **z_float, double_rgbt **z_rgbt, unsigned char **z_byte, long ix1, long ix2, long x1DC, long x2DC, long iy1, long iy2, long y1DC, long y2DC, double minimum, double maximum, long clipx1, long clipx2, long clipy1, long clipy2, int interpolate) { /*long t=clock();*/ long nx = ix2 - ix1 + 1; /* The number of cells along the horizontal axis. */ long ny = iy2 - iy1 + 1; /* The number of cells along the vertical axis. */ double dx = (double) (x2DC - x1DC) / (double) nx; /* Horizontal pixels per cell. Positive. */ double dy = (double) (y2DC - y1DC) / (double) ny; /* Vertical pixels per cell. Negative. */ double scale = 255.0 / (maximum - minimum), offset = 255.0 + minimum * scale; if (x2DC <= x1DC || y1DC <= y2DC) return; trace ("scale %f", scale); /* Clip by the intersection of the world window and the outline of the cells. */ //Melder_casual ("clipy1 %ld clipy2 %ld", clipy1, clipy2); if (clipx1 < x1DC) clipx1 = x1DC; if (clipx2 > x2DC) clipx2 = x2DC; if (clipy1 > y1DC) clipy1 = y1DC; if (clipy2 < y2DC) clipy2 = y2DC; /* * The first decision is whether we are going to use the standard rectangle drawing * (cellArray only), or whether we are going to write into a bitmap. * The standard drawing is best for small numbers of cells, * provided that some cells are larger than a pixel. */ if (! interpolate && nx * ny < 3000 && (dx > 1.0 || dy < -1.0)) { try { /*unsigned int cellWidth = (unsigned int) dx + 1;*/ unsigned int cellHeight = (unsigned int) (- (int) dy) + 1; long ix, iy; #if cairo cairo_pattern_t *grey [256]; for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) { double v = igrey / ((double) (sizeof (grey) / sizeof (*grey)) - 1.0); grey [igrey] = cairo_pattern_create_rgb (v, v, v); } #elif win static HBRUSH greyBrush [256]; RECT rect; if (! greyBrush [0]) for (int igrey = 0; igrey <= 255; igrey ++) greyBrush [igrey] = CreateSolidBrush (RGB (igrey, igrey, igrey)); // once #elif mac GraphicsQuartz_initDraw (me); CGContextSetAlpha (my d_macGraphicsContext, 1.0); CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal); #endif autoNUMvector <long> lefts (ix1, ix2 + 1); for (ix = ix1; ix <= ix2 + 1; ix ++) lefts [ix] = x1DC + (long) ((ix - ix1) * dx); for (iy = iy1; iy <= iy2; iy ++) { long bottom = y1DC + (long) ((iy - iy1) * dy), top = bottom - cellHeight; if (top > clipy1 || bottom < clipy2) continue; if (top < clipy2) top = clipy2; if (bottom > clipy1) bottom = clipy1; #if win rect. bottom = bottom; rect. top = top; #endif for (ix = ix1; ix <= ix2; ix ++) { long left = lefts [ix], right = lefts [ix + 1]; if (right < clipx1 || left > clipx2) continue; if (left < clipx1) left = clipx1; if (right > clipx2) right = clipx2; if (z_rgbt) { #if cairo // NYI #elif win // NYI #elif mac double red = z_rgbt [iy] [ix]. red; double green = z_rgbt [iy] [ix]. green; double blue = z_rgbt [iy] [ix]. blue; double transparency = z_rgbt [iy] [ix]. transparency; red = ( red <= 0.0 ? 0.0 : red >= 1.0 ? 1.0 : red ); green = ( green <= 0.0 ? 0.0 : green >= 1.0 ? 1.0 : green ); blue = ( blue <= 0.0 ? 0.0 : blue >= 1.0 ? 1.0 : blue ); CGContextSetRGBFillColor (my d_macGraphicsContext, red, green, blue, 1.0 - transparency); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } else { #if cairo long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); cairo_set_source (my d_cairoGraphicsContext, grey [value <= 0 ? 0 : value >= sizeof (grey) / sizeof (*grey) ? sizeof (grey) / sizeof (*grey) : value]); cairo_rectangle (my d_cairoGraphicsContext, left, top, right - left, bottom - top); cairo_fill (my d_cairoGraphicsContext); #elif win long value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); rect. left = left; rect. right = right; FillRect (my d_gdiGraphicsContext, & rect, greyBrush [value <= 0 ? 0 : value >= 255 ? 255 : value]); #elif mac double value = offset - scale * ( z_float ? z_float [iy] [ix] : z_byte [iy] [ix] ); double igrey = ( value <= 0 ? 0 : value >= 255 ? 255 : value ) / 255.0; CGContextSetRGBFillColor (my d_macGraphicsContext, igrey, igrey, igrey, 1.0); CGContextFillRect (my d_macGraphicsContext, CGRectMake (left, top, right - left, bottom - top)); #endif } } } #if cairo for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey ++) cairo_pattern_destroy (grey [igrey]); #elif mac CGContextSetRGBFillColor (my d_macGraphicsContext, 0.0, 0.0, 0.0, 1.0); GraphicsQuartz_exitDraw (me); #endif } catch (MelderError) { } } else { long xDC, yDC; long undersampling = 1; /* * Prepare for off-screen bitmap drawing. */ #if cairo long arrayWidth = clipx2 - clipx1; long arrayHeight = clipy1 - clipy2; trace ("arrayWidth %f, arrayHeight %f", (double) arrayWidth, (double) arrayHeight); cairo_surface_t *sfc = cairo_image_surface_create (CAIRO_FORMAT_RGB24, arrayWidth, arrayHeight); unsigned char *bits = cairo_image_surface_get_data (sfc); int scanLineLength = cairo_image_surface_get_stride (sfc); unsigned char grey [256]; trace ("image surface address %p, bits address %p, scanLineLength %d, numberOfGreys %d", sfc, bits, scanLineLength, sizeof(grey)/sizeof(*grey)); for (int igrey = 0; igrey < sizeof (grey) / sizeof (*grey); igrey++) grey [igrey] = 255 - (unsigned char) (igrey * 255.0 / (sizeof (grey) / sizeof (*grey) - 1)); #elif win long bitmapWidth = clipx2 - clipx1, bitmapHeight = clipy1 - clipy2; int igrey; /* * Create a device-independent bitmap, 32 bits deep. */ struct { BITMAPINFOHEADER header; } bitmapInfo; long scanLineLength = bitmapWidth * 4; // for 24 bits: (bitmapWidth * 3 + 3) & ~3L; HBITMAP bitmap; unsigned char *bits; // a pointer to memory allocated by VirtualAlloc or by CreateDIBSection () bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER); bitmapInfo. header.biWidth = bitmapWidth; // scanLineLength; bitmapInfo. header.biHeight = bitmapHeight; bitmapInfo. header.biPlanes = 1; bitmapInfo. header.biBitCount = 32; bitmapInfo. header.biCompression = 0; bitmapInfo. header.biSizeImage = 0; bitmapInfo. header.biXPelsPerMeter = 0; bitmapInfo. header.biYPelsPerMeter = 0; bitmapInfo. header.biClrUsed = 0; bitmapInfo. header.biClrImportant = 0; bitmap = CreateDIBSection (my d_gdiGraphicsContext /* ignored */, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, (VOID **) & bits, NULL, 0); #elif mac long bytesPerRow = (clipx2 - clipx1) * 4; Melder_assert (bytesPerRow > 0); long numberOfRows = clipy1 - clipy2; Melder_assert (numberOfRows > 0); unsigned char *imageData = Melder_malloc_f (unsigned char, bytesPerRow * numberOfRows); #endif /* * Draw into the bitmap. */ #if cairo #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif win #define ROW_START_ADDRESS (bits + (clipy1 - 1 - yDC) * scanLineLength) #define PUT_PIXEL \ if (1) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } #elif mac #define ROW_START_ADDRESS (imageData + (clipy1 - 1 - yDC) * bytesPerRow) #define PUT_PIXEL \ if (my colourScale == kGraphics_colourScale_GREY) { \ unsigned char kar = value <= 0 ? 0 : value >= 255 ? 255 : (int) value; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = kar; \ *pixelAddress ++ = 0; \ } else if (my colourScale == kGraphics_colourScale_BLUE_TO_RED) { \ if (value < 0.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ } else if (value < 64.0) { \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = (int) (value * 3 + 63.999); \ *pixelAddress ++ = 0; \ } else if (value < 128.0) { \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = (int) (value * 4 - 256.0); \ *pixelAddress ++ = 255; \ *pixelAddress ++ = 0; \ } else if (value < 192.0) { \ *pixelAddress ++ = 255; \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = (int) ((256.0 - value) * 4 - 256.0); \ *pixelAddress ++ = 0; \ } else if (value < 256.0) { \ *pixelAddress ++ = (int) ((256.0 - value) * 3 + 63.999); \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } else { \ *pixelAddress ++ = 63; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ *pixelAddress ++ = 0; \ } \ } #else #define ROW_START_ADDRESS NULL #define PUT_PIXEL #endif if (interpolate) { try { autoNUMvector <long> ileft (clipx1, clipx2); autoNUMvector <long> iright (clipx1, clipx2); autoNUMvector <double> rightWeight (clipx1, clipx2); autoNUMvector <double> leftWeight (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double ix_real = ix1 - 0.5 + ((double) nx * (xDC - x1DC)) / (x2DC - x1DC); ileft [xDC] = floor (ix_real), iright [xDC] = ileft [xDC] + 1; rightWeight [xDC] = ix_real - ileft [xDC], leftWeight [xDC] = 1.0 - rightWeight [xDC]; if (ileft [xDC] < ix1) ileft [xDC] = ix1; if (iright [xDC] > ix2) iright [xDC] = ix2; } for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { double iy_real = iy2 + 0.5 - ((double) ny * (yDC - y2DC)) / (y1DC - y2DC); long itop = ceil (iy_real), ibottom = itop - 1; double bottomWeight = itop - iy_real, topWeight = 1.0 - bottomWeight; unsigned char *pixelAddress = ROW_START_ADDRESS; if (itop > iy2) itop = iy2; if (ibottom < iy1) ibottom = iy1; if (z_float) { double *ztop = z_float [itop], *zbottom = z_float [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } else if (z_rgbt) { double_rgbt *ztop = z_rgbt [itop], *zbottom = z_rgbt [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double red = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. red + bottomWeight * zbottom [iright [xDC]]. red) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. red + bottomWeight * zbottom [ileft [xDC]]. red); double green = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. green + bottomWeight * zbottom [iright [xDC]]. green) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. green + bottomWeight * zbottom [ileft [xDC]]. green); double blue = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. blue + bottomWeight * zbottom [iright [xDC]]. blue) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. blue + bottomWeight * zbottom [ileft [xDC]]. blue); double transparency = rightWeight [xDC] * (topWeight * ztop [iright [xDC]]. transparency + bottomWeight * zbottom [iright [xDC]]. transparency) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]]. transparency + bottomWeight * zbottom [ileft [xDC]]. transparency); if (red < 0.0) red = 0.0; else if (red > 1.0) red = 1.0; if (green < 0.0) green = 0.0; else if (green > 1.0) green = 1.0; if (blue < 0.0) blue = 0.0; else if (blue > 1.0) blue = 1.0; if (transparency < 0.0) transparency = 0.0; else if (transparency > 1.0) transparency = 1.0; #if win *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = 0; #elif mac *pixelAddress ++ = red * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = transparency * 255.0; #elif cairo *pixelAddress ++ = blue * 255.0; *pixelAddress ++ = green * 255.0; *pixelAddress ++ = red * 255.0; *pixelAddress ++ = transparency * 255.0; #endif } } else { unsigned char *ztop = z_byte [itop], *zbottom = z_byte [ibottom]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double interpol = rightWeight [xDC] * (topWeight * ztop [iright [xDC]] + bottomWeight * zbottom [iright [xDC]]) + leftWeight [xDC] * (topWeight * ztop [ileft [xDC]] + bottomWeight * zbottom [ileft [xDC]]); double value = offset - scale * interpol; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } else { try { autoNUMvector <long> ix (clipx1, clipx2); for (xDC = clipx1; xDC < clipx2; xDC += undersampling) ix [xDC] = floor (ix1 + (nx * (xDC - x1DC)) / (x2DC - x1DC)); for (yDC = clipy2; yDC < clipy1; yDC += undersampling) { long iy = ceil (iy2 - (ny * (yDC - y2DC)) / (y1DC - y2DC)); unsigned char *pixelAddress = ROW_START_ADDRESS; Melder_assert (iy >= iy1 && iy <= iy2); if (z_float) { double *ziy = z_float [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } else { unsigned char *ziy = z_byte [iy]; for (xDC = clipx1; xDC < clipx2; xDC += undersampling) { double value = offset - scale * ziy [ix [xDC]]; PUT_PIXEL } } } } catch (MelderError) { Melder_clearError (); } } /* * Copy the bitmap to the screen. */ #if cairo cairo_matrix_t clip_trans; cairo_matrix_init_identity (& clip_trans); cairo_matrix_scale (& clip_trans, 1, -1); // we painted in the reverse y-direction cairo_matrix_translate (& clip_trans, - clipx1, - clipy1); cairo_pattern_t *bitmap_pattern = cairo_pattern_create_for_surface (sfc); trace ("bitmap pattern %p", bitmap_pattern); if (cairo_status_t status = cairo_pattern_status (bitmap_pattern)) { Melder_casual ("bitmap pattern status: %s", cairo_status_to_string (status)); } else { cairo_pattern_set_matrix (bitmap_pattern, & clip_trans); cairo_save (my d_cairoGraphicsContext); cairo_set_source (my d_cairoGraphicsContext, bitmap_pattern); cairo_paint (my d_cairoGraphicsContext); cairo_restore (my d_cairoGraphicsContext); } cairo_pattern_destroy (bitmap_pattern); #elif win SetDIBitsToDevice (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS); //StretchDIBits (my d_gdiGraphicsContext, clipx1, clipy2, bitmapWidth, bitmapHeight, 0, 0, 0, bitmapHeight, // bits, (CONST BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS, SRCCOPY); #elif mac CGImageRef image; static CGColorSpaceRef colourSpace = NULL; if (colourSpace == NULL) { colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); // used to be kCGColorSpaceUserRGB Melder_assert (colourSpace != NULL); } if (1) { CGDataProviderRef dataProvider = CGDataProviderCreateWithData (NULL, imageData, bytesPerRow * numberOfRows, _mac_releaseDataCallback // we need this because we cannot release the image data immediately after drawing, // because in PDF files the imageData has to stay available through EndPage ); Melder_assert (dataProvider != NULL); image = CGImageCreate (clipx2 - clipx1, numberOfRows, 8, 32, bytesPerRow, colourSpace, kCGImageAlphaNone, dataProvider, NULL, false, kCGRenderingIntentDefault); CGDataProviderRelease (dataProvider); } else if (0) { Melder_assert (CGBitmapContextCreate != NULL); CGContextRef bitmaptest = CGBitmapContextCreate (imageData, 100, 100, 8, 800, colourSpace, 0); Melder_assert (bitmaptest != NULL); CGContextRef bitmap = CGBitmapContextCreate (NULL/*imageData*/, clipx2 - clipx1, numberOfRows, 8, bytesPerRow, colourSpace, kCGImageAlphaLast); Melder_assert (bitmap != NULL); image = CGBitmapContextCreateImage (bitmap); // release bitmap? } Melder_assert (image != NULL); GraphicsQuartz_initDraw (me); CGContextDrawImage (my d_macGraphicsContext, CGRectMake (clipx1, clipy2, clipx2 - clipx1, clipy1 - clipy2), image); GraphicsQuartz_exitDraw (me); //CGColorSpaceRelease (colourSpace); CGImageRelease (image); #endif /* * Clean up. */ #if cairo cairo_surface_destroy (sfc); #elif win DeleteBitmap (bitmap); #endif }
void structGraphicsScreen :: v_polyline (long numberOfPoints, double *xyDC, bool close) { #if cairo if (duringXor) { #if ALLOW_GDK_DRAWING gdkPrepareLine (this); for (long i = 0; i < numberOfPoints - 1; i ++) { gdk_draw_line (our d_window, our d_gdkGraphicsContext, xyDC [i + i], xyDC [i + i + 1], xyDC [i + i + 2], xyDC [i + i + 3]); } gdkRevertLine (this); gdk_flush (); #endif } else { if (our d_cairoGraphicsContext == NULL) return; cairoPrepareLine (this); // cairo_new_path (d_cairoGraphicsContext); // move_to() automatically creates a new path cairo_move_to (our d_cairoGraphicsContext, xyDC [0], xyDC [1]); for (long i = 1; i < numberOfPoints; i ++) { cairo_line_to (our d_cairoGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); } if (close) cairo_close_path (our d_cairoGraphicsContext); cairo_stroke (our d_cairoGraphicsContext); cairoRevertLine (this); } #elif win winPrepareLine (this); POINT *points = Melder_malloc (POINT, numberOfPoints + close); if (points) { for (long i = 0; i < numberOfPoints; i ++) { points [i]. x = *xyDC, xyDC ++; points [i]. y = *xyDC, xyDC ++; } if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); if (our d_fatNonSolid) { for (long i = 0; i < numberOfPoints; i ++) points [i]. x -= 1; if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); for (long i = 0; i < numberOfPoints; i ++) { points [i]. x += 1; points [i]. y -= 1; } if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); } } DEFAULT #elif mac GraphicsQuartz_initDraw (this); quartzPrepareLine (this); CGContextBeginPath (our d_macGraphicsContext); CGContextMoveToPoint (our d_macGraphicsContext, xyDC [0], xyDC [1]); // starts a new subpath for (long i = 1; i < numberOfPoints; i ++) { CGContextAddLineToPoint (our d_macGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); } if (close) CGContextClosePath (our d_macGraphicsContext); // closes only the subpath CGContextStrokePath (our d_macGraphicsContext); quartzRevertLine (this); GraphicsQuartz_exitDraw (this); #endif }