123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 |
- /* GraphicsScreen.cpp
- *
- * Copyright (C) 1992-2012,2014,2015,2016,2017 Paul Boersma, 2013 Tom Naughton
- *
- * This code is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This code is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this work. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "GraphicsP.h"
- #include "Printer.h"
- #include "GuiP.h"
- #if cairo
- #include <cairo/cairo-pdf.h>
- static bool _GraphicsCairo_tryToInitializePango () {
- return _GraphicsLin_tryToInitializeFonts ();
- }
- #elif gdi
- //#include "winport_on.h"
- #include <gdiplus.h>
- //#include "winport_off.h"
- //using namespace Gdiplus;
- static bool _GraphicsWindows_tryToInitializeGdiPlus () {
- Gdiplus::GdiplusStartupInput gdiplusStartupInput;
- ULONG_PTR gdiplusToken;
- GdiplusStartup (& gdiplusToken, & gdiplusStartupInput, nullptr);
- return true;
- }
- #elif quartz
- #include "macport_on.h"
- static RGBColor theBlackColour = { 0, 0, 0 };
- static bool _GraphicsMacintosh_tryToInitializeQuartz () {
- return _GraphicsMac_tryToInitializeFonts ();
- }
- #endif
- Thing_implement (GraphicsScreen, Graphics, 0);
- void structGraphicsScreen :: v_destroy () noexcept {
- #if cairo
- #if ALLOW_GDK_DRAWING
- if (d_gdkGraphicsContext) {
- g_object_unref (d_gdkGraphicsContext);
- d_gdkGraphicsContext = nullptr;
- }
- #endif
- if (d_cairoGraphicsContext) {
- cairo_destroy (d_cairoGraphicsContext);
- d_cairoGraphicsContext = nullptr;
- }
- if (d_cairoSurface) {
- cairo_surface_flush (d_cairoSurface);
- if (d_isPng) {
- #if 1
- cairo_surface_write_to_png (d_cairoSurface, Melder_peek32to8 (d_file. path));
- #else
- unsigned char *bitmap = cairo_image_surface_get_data (my d_cairoSurface); // peeking into the internal bits
- // copy bitmap to PNG structure created with the PNG library
- // save the PNG tructure to a file
- #endif
- }
- cairo_surface_destroy (d_cairoSurface);
- }
- #elif gdi
- if (d_gdiGraphicsContext) {
- SelectPen (d_gdiGraphicsContext, GetStockPen (BLACK_PEN));
- SelectBrush (d_gdiGraphicsContext, GetStockBrush (NULL_BRUSH));
- }
- if (d_winPen) {
- DeleteObject (d_winPen);
- d_winPen = nullptr;
- }
- if (d_winBrush) {
- DeleteObject (d_winBrush);
- d_winBrush = nullptr;
- }
- if (d_isPng && d_gdiBitmap) {
- trace (U"saving the filled bitmap to a PNG file");
- /*
- * Deselect the bitmap from the device context (otherwise GetDIBits won't work).
- */
- //SelectBitmap (d_gdiGraphicsContext, nullptr);
- //SelectBitmap (d_gdiGraphicsContext, CreateCompatibleBitmap (nullptr, 1, 1));
- BITMAP bitmap;
- GetObject (d_gdiBitmap, sizeof (BITMAP), & bitmap);
- int width = bitmap. bmWidth, height = bitmap. bmHeight;
- //int width = 3600, height = 3600;
- trace (U"width ", width, U", height ", height);
- /*
- * Get the bits from the HBITMAP;
- */
- struct { BITMAPINFOHEADER header; } bitmapInfo;
- bitmapInfo. header.biSize = sizeof (BITMAPINFOHEADER);
- bitmapInfo. header.biWidth = width;
- bitmapInfo. header.biHeight = height;
- bitmapInfo. header.biPlanes = 1;
- bitmapInfo. header.biBitCount = 32;
- bitmapInfo. header.biCompression = BI_RGB;
- bitmapInfo. header.biSizeImage = 0;
- bitmapInfo. header.biXPelsPerMeter = 0;
- bitmapInfo. header.biYPelsPerMeter = 0;
- bitmapInfo. header.biClrUsed = 0;
- bitmapInfo. header.biClrImportant = 0;
- unsigned char *bits = Melder_calloc (unsigned char, 4 * width * height);
- //HANDLE handle = GlobalAlloc (GHND, 4 * width * height);
- //unsigned char *bits = (unsigned char *) GlobalLock (handle);
- int numberOfLinesScanned = GetDIBits (GetDC (nullptr), d_gdiBitmap, 0, height, bits, (BITMAPINFO *) & bitmapInfo, DIB_RGB_COLORS);
- trace (numberOfLinesScanned, U" lines scanned");
- trace (U"creating a savable bitmap");
- //Gdiplus::Bitmap gdiplusBitmap (width, height, PixelFormat32bppARGB);
- Gdiplus::Bitmap gdiplusBitmap ((BITMAPINFO *) & bitmapInfo, bits);
- gdiplusBitmap. SetResolution (resolution, resolution);
- trace (U"copying the device-independent bits to the savable bitmap.");
- /*
- for (integer irow = 1; irow <= height; irow ++) {
- for (integer icol = 1; icol <= width; icol ++) {
- unsigned char blue = *bits ++, green = *bits ++, red = *bits ++, alpha = 255 - *bits ++;
- Gdiplus::Color gdiplusColour (alpha, red, green, blue);
- gdiplusBitmap. SetPixel (icol - 1, height - irow, gdiplusColour);
- }
- }
- */
- trace (U"saving");
- UINT numberOfImageEncoders, sizeOfImageEncoderArray;
- Gdiplus::GetImageEncodersSize (& numberOfImageEncoders, & sizeOfImageEncoderArray);
- Gdiplus::ImageCodecInfo *imageEncoderInfos = Melder_malloc (Gdiplus::ImageCodecInfo, sizeOfImageEncoderArray);
- Gdiplus::GetImageEncoders (numberOfImageEncoders, sizeOfImageEncoderArray, imageEncoderInfos);
- for (int iencoder = 0; iencoder < numberOfImageEncoders; iencoder ++) {
- if (! wcscmp (imageEncoderInfos [iencoder]. MimeType, L"image/png")) {
- gdiplusBitmap. Save (Melder_peek32toW (our d_file. path), & imageEncoderInfos [iencoder]. Clsid, nullptr);
- }
- }
- trace (U"cleaning up");
- Melder_free (imageEncoderInfos);
- //bits -= 4 * width * height;
- Melder_free (bits);
- //GlobalUnlock (handle);
- //GlobalFree (handle);
- DeleteObject (d_gdiBitmap);
- Melder_assert (d_gdiGraphicsContext);
- DeleteDC (d_gdiGraphicsContext); // this was a memory leak before 5.3.83
- }
- /*
- * No ReleaseDC here, because we have not created it ourselves,
- * not even with GetDC. Is this a BUG?
- */
- d_gdiGraphicsContext = nullptr;
- #elif quartz
- if (! d_macView && ! d_isPng) {
- CGContextEndPage (d_macGraphicsContext);
- CGContextRelease (d_macGraphicsContext);
- }
- if (d_isPng && d_macGraphicsContext) {
- /*
- * Turn the offscreen bitmap into an image.
- */
- CGImageRef image = CGBitmapContextCreateImage (d_macGraphicsContext);
- Melder_assert (image);
- //CGContextRelease (d_macGraphicsContext);
- /*
- * Create a dictionary with resolution properties.
- */
- CFTypeRef keys [2], values [2];
- keys [0] = kCGImagePropertyDPIWidth;
- keys [1] = kCGImagePropertyDPIHeight;
- float resolution_float = resolution;
- values [1] = values [0] = CFNumberCreate (nullptr, kCFNumberFloatType, & resolution_float);
- CFDictionaryRef properties = CFDictionaryCreate (nullptr,
- (const void **) keys, (const void **) values, 2,
- & kCFTypeDictionaryKeyCallBacks, & kCFTypeDictionaryValueCallBacks);
- Melder_assert (properties);
- /*
- */
- CFURLRef url = CFURLCreateWithFileSystemPath (nullptr,
- (CFStringRef) Melder_peek32toCfstring (d_file. path), kCFURLPOSIXPathStyle, false);
- CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL (url, kUTTypePNG, 1, nullptr);
- if (imageDestination) {
- CGImageDestinationAddImage (imageDestination, image, properties);
- CGImageDestinationFinalize (imageDestination);
- CFRelease (imageDestination);
- }
- CGImageRelease (image);
- CFRelease (properties);
- CFRelease (url);
- }
- Melder_free (d_bits);
- #endif
- trace (U"destroying parent");
- GraphicsScreen_Parent :: v_destroy ();
- trace (U"exit");
- }
- void structGraphicsScreen :: v_flushWs () {
- #if cairo && gtk
- // Ik weet niet of dit is wat het zou moeten zijn ;)
- //gdk_window_process_updates (d_window, true); // this "works" but is incorrect because it's not the expose events that have to be carried out
- //gdk_window_flush (d_window);
- gdk_flush ();
- // TODO: een aanroep die de eventuele grafische buffer ledigt,
- // zodat de gebruiker de grafica ziet ook al blijft Praat in hetzelfde event zitten
- #elif gdi
- /*GdiFlush ();*/
- #elif quartz
- if (d_drawingArea) {
- GuiShell shell = d_drawingArea -> d_shell;
- Melder_assert (shell);
- Melder_assert (shell -> d_cocoaShell);
- [shell -> d_cocoaShell flushWindow];
- NSEvent *nsEvent = [[d_macView window]
- nextEventMatchingMask: NSAnyEventMask
- untilDate: [NSDate distantPast]
- inMode: NSDefaultRunLoopMode
- dequeue: NO
- ];
- }
- #endif
- }
- void Graphics_flushWs (Graphics me) {
- my v_flushWs ();
- }
- void structGraphicsScreen :: v_clearWs () {
- #if cairo && gtk
- GdkRectangle rect;
- if (our d_x1DC < our d_x2DC) {
- rect.x = our d_x1DC;
- rect.width = our d_x2DC - our d_x1DC;
- } else {
- rect.x = our d_x2DC;
- rect.width = our d_x1DC - our d_x2DC;
- }
- if (our d_y1DC < our d_y2DC) {
- rect.y = our d_y1DC;
- rect.height = our d_y2DC - our d_y1DC;
- } else {
- rect.y = our d_y2DC;
- rect.height = our d_y1DC - our d_y2DC;
- }
- if (! d_cairoGraphicsContext) {
- trace (U"clear and null");
- //gdk_window_clear (our window);
- //gdk_window_invalidate_rect (our window, & rect, true); // BUG: it seems weird that this is necessary.
- } else {
- trace (U"clear and not null");
- cairo_set_source_rgb (d_cairoGraphicsContext, 1.0, 1.0, 1.0);
- cairo_rectangle (d_cairoGraphicsContext, rect.x, rect.y, rect.width, rect.height);
- cairo_fill (d_cairoGraphicsContext);
- cairo_set_source_rgb (d_cairoGraphicsContext, 0.0, 0.0, 0.0);
- }
- #elif gdi
- RECT rect;
- rect. left = rect. top = 0;
- rect. right = d_x2DC - d_x1DC;
- rect. bottom = d_y2DC - d_y1DC;
- FillRect (d_gdiGraphicsContext, & rect, GetStockBrush (WHITE_BRUSH));
- /*if (d_winWindow) SendMessage (d_winWindow, WM_ERASEBKGND, (WPARAM) d_gdiGraphicsContext, 0);*/
- #elif quartz
- GuiCocoaDrawingArea *cocoaDrawingArea = (GuiCocoaDrawingArea *) d_drawingArea -> d_widget;
- if (cocoaDrawingArea && ! [cocoaDrawingArea isHiddenOrHasHiddenAncestor]) { // can be called at destruction time
- NSRect rect;
- if (our d_x1DC < our d_x2DC) {
- rect.origin.x = our d_x1DC;
- rect.size.width = our d_x2DC - our d_x1DC;
- } else {
- rect.origin.x = our d_x2DC;
- rect.size.width = our d_x1DC - our d_x2DC;
- }
- if (our d_y1DC < our d_y2DC) {
- rect.origin.y = our d_y1DC;
- rect.size.height = our d_y2DC - our d_y1DC;
- } else {
- rect.origin.y = our d_y2DC;
- rect.size.height = our d_y1DC - our d_y2DC;
- }
- [cocoaDrawingArea lockFocus];
- CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
- CGContextSaveGState (context);
- CGContextSetAlpha (context, 1.0);
- CGContextSetBlendMode (context, kCGBlendModeNormal);
- CGContextSetRGBFillColor (context, 1.0, 1.0, 1.0, 1.0);
- //rect.origin.x -= 1000;
- //rect.origin.y -= 1000;
- //rect.size.width += 2000;
- //rect.size.height += 2000;
- trace (U"clearing ", rect.origin.x, U" ", rect.origin.y, U" ", rect.size.width, U" ", rect.size.height);
- //CGContextTranslateCTM (context, 0, cocoaDrawingArea.bounds.size.height);
- //CGContextScaleCTM (context, 1.0, -1.0);
- CGContextFillRect (context, rect);
- //CGContextSynchronize (context);
- CGContextRestoreGState (context);
- [cocoaDrawingArea unlockFocus];
- //[cocoaDrawingArea setNeedsDisplay: YES];
- //[cocoaDrawingArea display];
- }
- #endif
- }
- void Graphics_clearWs (Graphics me) {
- my v_clearWs ();
- }
- void structGraphicsScreen :: v_updateWs () {
- /*
- * A function that invalidates the graphics.
- * This function is typically called by the owner of the drawing area
- * whenever the data to be displayed in the drawing area has changed;
- * the idea is to generate an expose event to which the drawing area will
- * respond by redrawing its contents from the (changed) data.
- */
- #if cairo && gtk
- //GdkWindow *window = gtk_widget_get_parent_window (GTK_WIDGET (our d_drawingArea -> d_widget));
- GdkRectangle rect;
- if (our d_x1DC < our d_x2DC) {
- rect.x = our d_x1DC;
- rect.width = our d_x2DC - our d_x1DC;
- } else {
- rect.x = our d_x2DC;
- rect.width = our d_x1DC - our d_x2DC;
- }
- if (our d_y1DC < our d_y2DC) {
- rect.y = our d_y1DC;
- rect.height = our d_y2DC - our d_y1DC;
- } else {
- rect.y = our d_y2DC;
- rect.height = our d_y1DC - our d_y2DC;
- }
- if (our d_cairoGraphicsContext && our d_drawingArea) { // update clipping rectangle to new graphics size
- cairo_reset_clip (our d_cairoGraphicsContext);
- cairo_rectangle (our d_cairoGraphicsContext, rect.x, rect.y, rect.width, rect.height);
- cairo_clip (our d_cairoGraphicsContext);
- }
- #if ALLOW_GDK_DRAWING
- gdk_window_clear (our d_window);
- #endif
- gdk_window_invalidate_rect (our d_window, & rect, true);
- //gdk_window_process_updates (our d_window, true);
- #elif gdi
- //clear (this); // lll
- if (our d_winWindow) InvalidateRect (our d_winWindow, nullptr, true);
- #elif quartz
- NSView *view = our d_macView;
- Melder_assert (!! view);
- NSRect rect;
-
- if (our d_x1DC < our d_x2DC) {
- rect.origin.x = our d_x1DC;
- rect.size.width = our d_x2DC - our d_x1DC;
- } else {
- rect.origin.x = our d_x2DC;
- rect.size.width = our d_x1DC - our d_x2DC;
- }
-
- if (our d_y1DC < our d_y2DC) {
- rect.origin.y = our d_y1DC;
- rect.size.height = our d_y2DC - our d_y1DC;
- } else {
- rect.origin.y = our d_y2DC;
- rect.size.height = our d_y1DC - our d_y2DC;
- }
-
- //[view setNeedsDisplayInRect: rect];
- [view setNeedsDisplay: YES];
- #endif
- }
- void Graphics_updateWs (Graphics me) {
- if (me)
- my v_updateWs ();
- }
- void Graphics_beginMovieFrame (Graphics any, Graphics_Colour *p_colour) {
- if (any -> classInfo == classGraphicsScreen) {
- GraphicsScreen me = (GraphicsScreen) any;
- Graphics_clearRecording (me);
- Graphics_startRecording (me);
- if (p_colour) {
- Graphics_setViewport (me, 0.0, 1.0, 0.0, 1.0);
- Graphics_setColour (me, *p_colour);
- Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
- Graphics_fillRectangle (me, 0.0, 1.0, 0.0, 1.0);
- Graphics_setColour (me, Graphics_BLACK);
- }
- }
- }
- void Graphics_endMovieFrame (Graphics any, double frameDuration) {
- if (any -> classInfo == classGraphicsScreen) {
- GraphicsScreen me = (GraphicsScreen) any;
- Graphics_stopRecording (me);
- #if cairo || gdi
- my v_flushWs ();
- #elif quartz
- my v_updateWs ();
- GuiShell_drain (my d_drawingArea -> d_shell);
- #endif
- Melder_sleep (frameDuration);
- }
- }
- static int GraphicsScreen_init (GraphicsScreen me, void *voidDisplay, void *voidWindow) {
- /* Fill in new members. */
- #if cairo && gtk
- my d_display = (GdkDisplay *) gdk_display_get_default ();
- _GraphicsScreen_text_init (me);
- #if ALLOW_GDK_DRAWING
- trace (U"retrieving window");
- my d_window = GDK_DRAWABLE (GTK_WIDGET (voidDisplay) -> window);
- trace (U"retrieved window");
- my d_gdkGraphicsContext = gdk_gc_new (my d_window);
- #else
- my d_window = gtk_widget_get_window (GTK_WIDGET (voidDisplay));
- #endif
- my d_cairoGraphicsContext = gdk_cairo_create (my d_window);
- #elif gdi
- if (my printer) {
- my d_gdiGraphicsContext = (HDC) voidWindow;
- } else if (voidDisplay) {
- my d_gdiGraphicsContext = (HDC) voidDisplay;
- my metafile = true;
- } else {
- my d_winWindow = (HWND) voidWindow;
- my d_gdiGraphicsContext = GetDC (my d_winWindow); // window must have a constant display context; see XtInitialize ()
- }
- Melder_assert (my d_gdiGraphicsContext);
- SetBkMode (my d_gdiGraphicsContext, TRANSPARENT); // not the default!
- /*
- * Create pens and brushes.
- */
- my d_winPen = CreatePen (PS_SOLID, 0, RGB (0, 0, 0));
- my d_winBrush = CreateSolidBrush (RGB (0, 0, 0));
- SelectBrush (my d_gdiGraphicsContext, GetStockBrush (NULL_BRUSH));
- SetTextAlign (my d_gdiGraphicsContext, TA_LEFT | TA_BASELINE | TA_NOUPDATECP); // baseline is not the default!
- _GraphicsScreen_text_init (me);
- #elif quartz
- (void) voidDisplay;
- if (my printer) {
- my d_macView = (NSView *) voidWindow; // in case we do view-based printing
- //my d_macGraphicsContext = (CGContextRef) voidWindow; // in case we do context-based printing
- } else {
- my d_macView = (NSView *) voidWindow;
- (void) my d_macGraphicsContext; // will be retrieved from Core Graphics with every drawing command!
- }
- my d_macColour = theBlackColour;
- my d_depth = my resolution > 150 ? 1 : 8; /* BUG: replace by true depth (1=black/white) */
- _GraphicsScreen_text_init (me);
- #endif
- return 1;
- }
- autoGraphics Graphics_create_screen (void *display, void *window, int resolution) {
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- my screen = true;
- #if cairo
- _GraphicsCairo_tryToInitializePango ();
- #elif gdi
- my d_useGdiplus = _GraphicsWindows_tryToInitializeGdiPlus ();
- #elif quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- my yIsZeroAtTheTop = true;
- Graphics_init (me.get(), resolution);
- Graphics_setWsViewport (me.get(), 0.0, 100.0, 0.0, 100.0);
- GraphicsScreen_init (me.get(), display, window);
- return me.move();
- }
- autoGraphics Graphics_create_screenPrinter (void *display, void *window) {
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- my screen = true;
- my yIsZeroAtTheTop = true;
- my printer = true;
- #if cairo
- _GraphicsCairo_tryToInitializePango ();
- #elif gdi
- my d_useGdiplus = _GraphicsWindows_tryToInitializeGdiPlus ();
- #elif quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- Graphics_init (me.get(), thePrinter. resolution);
- my paperWidth = (double) thePrinter. paperWidth / thePrinter. resolution;
- my paperHeight = (double) thePrinter. paperHeight / thePrinter. resolution;
- //NSLog (@"Graphics_create_screenPrinter: %f %f", my paperWidth, my paperHeight);
- my d_x1DC = my d_x1DCmin = thePrinter. resolution / 2;
- my d_x2DC = my d_x2DCmax = (my paperWidth - 0.5) * thePrinter. resolution;
- my d_y1DC = my d_y1DCmin = thePrinter. resolution / 2;
- my d_y2DC = my d_y2DCmax = (my paperHeight - 0.5) * thePrinter. resolution;
- #if gdi
- /*
- * Map page coordinates to paper coordinates.
- */
- my d_x1DC -= GetDeviceCaps ((HDC) window, PHYSICALOFFSETX);
- my d_x2DC -= GetDeviceCaps ((HDC) window, PHYSICALOFFSETX);
- my d_y1DC -= GetDeviceCaps ((HDC) window, PHYSICALOFFSETY);
- my d_y2DC -= GetDeviceCaps ((HDC) window, PHYSICALOFFSETY);
- #endif
- Graphics_setWsWindow (me.get(), 0, my paperWidth - 1.0, 13.0 - my paperHeight, 12.0);
- GraphicsScreen_init (me.get(), display, window);
- return me.move();
- }
- autoGraphics Graphics_create_xmdrawingarea (GuiDrawingArea w) {
- trace (U"begin");
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- #if cairo && gtk
- GtkRequisition realsize;
- GtkAllocation allocation;
- #elif gdi
- Dimension width, height;
- #endif
- my d_drawingArea = static_cast <GuiDrawingArea> (w); /* Now !!!!!!!!!! */
- Melder_assert (my d_drawingArea -> d_widget);
- my screen = true;
- my yIsZeroAtTheTop = true;
- #if cairo
- _GraphicsCairo_tryToInitializePango ();
- #elif gdi
- my d_useGdiplus = _GraphicsWindows_tryToInitializeGdiPlus ();
- #elif quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- #if cairo && gtk
- Graphics_init (me.get(), Gui_getResolution (my d_drawingArea -> d_widget));
- GraphicsScreen_init (me.get(), GTK_WIDGET (my d_drawingArea -> d_widget), GTK_WIDGET (my d_drawingArea -> d_widget));
- #elif gdi
- Graphics_init (me.get(), Gui_getResolution (my d_drawingArea -> d_widget));
- GraphicsScreen_init (me.get(), XtDisplay (my d_drawingArea -> d_widget), XtWindow (my d_drawingArea -> d_widget));
- #elif quartz
- Graphics_init (me.get(), Gui_getResolution (nullptr));
- GraphicsScreen_init (me.get(), my d_drawingArea -> d_widget, my d_drawingArea -> d_widget);
- #endif
- #if cairo && gtk
- // fb: is really the request meant or rather the actual size, aka allocation?
- gtk_widget_size_request (GTK_WIDGET (my d_drawingArea -> d_widget), & realsize);
- gtk_widget_get_allocation (GTK_WIDGET (my d_drawingArea -> d_widget), & allocation);
- // HIER WAS IK
- trace (U"requested ", realsize.width, U" x ", realsize.height, U", allocated ", allocation.width, U" x ", allocation.height);
- Graphics_setWsViewport (me.get(), 0.0, realsize.width, 0.0, realsize.height);
- #elif gdi
- XtVaGetValues (my d_drawingArea -> d_widget, XmNwidth, & width, XmNheight, & height, nullptr);
- Graphics_setWsViewport (me.get(), 0.0, width, 0.0, height);
- #elif quartz
- NSView *view = (NSView *)my d_drawingArea -> d_widget;
- NSRect bounds = [view bounds];
- Graphics_setWsViewport (me.get(), 0.0, bounds.size.width, 0.0, bounds.size.height);
- #endif
- return me.move();
- }
- autoGraphics Graphics_create_pngfile (MelderFile file, int resolution,
- double x1inches, double x2inches, double y1inches, double y2inches)
- {
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- my screen = true;
- my yIsZeroAtTheTop = true;
- #if cairo
- _GraphicsCairo_tryToInitializePango ();
- #elif gdi
- my d_useGdiplus = _GraphicsWindows_tryToInitializeGdiPlus ();
- #elif quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- Graphics_init (me.get(), resolution);
- my d_isPng = true;
- my d_file = *file;
- my d_x1DC = my d_x1DCmin = 0;
- my d_x2DC = my d_x2DCmax = (x2inches - x1inches) * resolution;
- my d_y1DC = my d_y1DCmin = 0;
- my d_y2DC = my d_y2DCmax = (y2inches - y1inches) * resolution;
- Graphics_setWsWindow (me.get(), x1inches, x2inches, y1inches, y2inches);
- #if cairo
- my d_cairoSurface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
- (x2inches - x1inches) * resolution, (y2inches - y1inches) * resolution);
- my d_cairoGraphicsContext = cairo_create (my d_cairoSurface);
- //cairo_scale (my d_cairoGraphicsContext, 72.0 / resolution, 72.0 / resolution);
- /*
- * Fill in the whole area with a white background.
- */
- cairo_set_source_rgb (my d_cairoGraphicsContext, 1.0, 1.0, 1.0);
- cairo_rectangle (my d_cairoGraphicsContext, 0, 0, my d_x2DC, my d_y2DC);
- cairo_fill (my d_cairoGraphicsContext);
- cairo_set_source_rgb (my d_cairoGraphicsContext, 0.0, 0.0, 0.0);
- #elif gdi
- my metafile = true;
- HDC screenDC = GetDC (nullptr);
- my d_gdiGraphicsContext = CreateCompatibleDC (screenDC);
- trace (U"d_gdiGraphicsContext ", Melder_pointer (my d_gdiGraphicsContext));
- Melder_assert (my d_gdiGraphicsContext);
- my d_gdiBitmap = CreateCompatibleBitmap (screenDC, (x2inches - x1inches) * resolution, (y2inches - y1inches) * resolution);
- trace (U"d_gdiBitmap ", Melder_pointer (my d_gdiBitmap));
- Melder_assert (my d_gdiBitmap);
- ReleaseDC (nullptr, screenDC);
- SelectObject (my d_gdiGraphicsContext, my d_gdiBitmap);
- trace (U"bitmap selected into device context");
- my resolution = resolution;
- SetBkMode (my d_gdiGraphicsContext, TRANSPARENT);
- my d_winPen = CreatePen (PS_SOLID, 0, RGB (0, 0, 0));
- my d_winBrush = CreateSolidBrush (RGB (0, 0, 0));
- SetTextAlign (my d_gdiGraphicsContext, TA_LEFT | TA_BASELINE | TA_NOUPDATECP);
- /*
- * Fill in the whole area with a white background.
- */
- SelectPen (my d_gdiGraphicsContext, GetStockPen (NULL_PEN));
- SelectBrush (my d_gdiGraphicsContext, GetStockBrush (WHITE_BRUSH));
- Rectangle (my d_gdiGraphicsContext, 0, 0, my d_x2DC + 1, my d_y2DC + 1); // plus 1, in order to prevent two black edges
- SelectPen (my d_gdiGraphicsContext, GetStockPen (BLACK_PEN));
- SelectBrush (my d_gdiGraphicsContext, GetStockBrush (NULL_BRUSH));
- #elif quartz
- integer width = (x2inches - x1inches) * resolution, height = (y2inches - y1inches) * resolution;
- integer stride = width * 4;
- stride = (stride + 15) & ~15; // CommonCode/AppDrawing.c: "a multiple of 16 bytes, for best performance"
- my d_bits = Melder_malloc (uint8_t, stride * height);
- static CGColorSpaceRef colourSpace = nullptr;
- if (! colourSpace) {
- colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
- Melder_assert (colourSpace);
- }
- my d_macGraphicsContext = CGBitmapContextCreate (my d_bits,
- width, height,
- 8, // bits per component
- stride,
- colourSpace,
- kCGImageAlphaPremultipliedLast);
- if (! my d_macGraphicsContext)
- Melder_throw (U"Could not create PNG file ", file, U".");
- CGRect rect = CGRectMake (0, 0, width, height);
- CGContextSetAlpha (my d_macGraphicsContext, 1.0);
- CGContextSetBlendMode (my d_macGraphicsContext, kCGBlendModeNormal);
- CGContextSetRGBFillColor (my d_macGraphicsContext, 1.0, 1.0, 1.0, 1.0);
- CGContextFillRect (my d_macGraphicsContext, rect);
- CGContextTranslateCTM (my d_macGraphicsContext, 0, height);
- CGContextScaleCTM (my d_macGraphicsContext, 1.0, -1.0);
- #endif
- return me.move();
- }
- autoGraphics Graphics_create_pdffile (MelderFile file, int resolution,
- double x1inches, double x2inches, double y1inches, double y2inches)
- {
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- my screen = true;
- my yIsZeroAtTheTop = true;
- #if cairo
- _GraphicsCairo_tryToInitializePango ();
- #elif quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- Graphics_init (me.get(), resolution);
- #if cairo
- my d_cairoSurface = cairo_pdf_surface_create (Melder_peek32to8 (file -> path),
- ( isdefined (x1inches) ? x2inches - x1inches : x2inches ) * 72.0,
- ( isdefined (y1inches) ? y2inches - y1inches : y2inches ) * 72.0);
- my d_cairoGraphicsContext = cairo_create (my d_cairoSurface);
- my d_x1DC = my d_x1DCmin = 0;
- my d_x2DC = my d_x2DCmax = ( isdefined (x1inches) ? 7.5 : x2inches ) * resolution;
- my d_y1DC = my d_y1DCmin = 0;
- my d_y2DC = my d_y2DCmax = ( isdefined (y1inches) ? 11.0 : y2inches ) * resolution;
- Graphics_setWsWindow (me.get(),
- isdefined (x1inches) ? 0.0 : 0.0, isdefined (x1inches) ? 7.5 : x2inches,
- isdefined (y1inches) ? 1.0 : 0.0, isdefined (y1inches) ? 12.0 : y2inches);
- cairo_scale (my d_cairoGraphicsContext, 72.0 / resolution, 72.0 / resolution);
- #elif quartz
- CFURLRef url = CFURLCreateWithFileSystemPath (nullptr, (CFStringRef) Melder_peek32toCfstring (file -> path), kCFURLPOSIXPathStyle, false);
- CGRect rect = CGRectMake (0, 0,
- ( isdefined (x1inches) ? x2inches - x1inches : x2inches ) * 72.0,
- ( isdefined (y1inches) ? y2inches - y1inches : y2inches ) * 72.0); // don't tire PDF viewers with funny origins
- CFStringRef key = (CFStringRef) Melder_peek32toCfstring (U"Creator");
- CFStringRef value = (CFStringRef) Melder_peek32toCfstring (U"Praat");
- CFIndex numberOfValues = 1;
- CFDictionaryRef dictionary = CFDictionaryCreate (nullptr, (const void **) & key, (const void **) & value, numberOfValues,
- & kCFTypeDictionaryKeyCallBacks, & kCFTypeDictionaryValueCallBacks);
- my d_macGraphicsContext = CGPDFContextCreateWithURL (url, & rect, dictionary);
- CFRelease (url);
- CFRelease (dictionary);
- if (! my d_macGraphicsContext)
- Melder_throw (U"Could not create PDF file ", file, U".");
- my d_x1DC = my d_x1DCmin = 0;
- my d_x2DC = my d_x2DCmax = ( isdefined (x1inches) ? 7.5 : x2inches ) * resolution;
- my d_y1DC = my d_y1DCmin = 0;
- my d_y2DC = my d_y2DCmax = ( isdefined (y1inches) ? 11.0 : y2inches ) * resolution;
- Graphics_setWsWindow (me.get(),
- ( isdefined (x1inches) ? 0.0 : 0.0 ), ( isdefined (x1inches) ? 7.5 : x2inches ),
- ( isdefined (y1inches) ? 1.0 : 0.0 ), ( isdefined (y1inches) ? 12.0 : y2inches ));
- CGContextBeginPage (my d_macGraphicsContext, & rect);
- CGContextScaleCTM (my d_macGraphicsContext, 72.0 / resolution, 72.0 / resolution);
- CGContextTranslateCTM (my d_macGraphicsContext,
- ( isdefined (x1inches) ? - x1inches : 0.0 ) * resolution,
- ( isdefined (y1inches) ? (12.0 - y1inches) : y2inches ) * resolution);
- CGContextScaleCTM (my d_macGraphicsContext, 1.0, -1.0);
- #endif
- return me.move();
- }
- autoGraphics Graphics_create_pdf (void *context, int resolution,
- double x1inches, double x2inches, double y1inches, double y2inches)
- {
- autoGraphicsScreen me = Thing_new (GraphicsScreen);
- my screen = true;
- my yIsZeroAtTheTop = true;
- #if quartz
- _GraphicsMacintosh_tryToInitializeQuartz ();
- #endif
- Graphics_init (me.get(), resolution);
- #if quartz
- my d_macGraphicsContext = static_cast <CGContext *> (context);
- CGRect rect = CGRectMake (0, 0, (x2inches - x1inches) * 72, (y2inches - y1inches) * 72); // don't tire PDF viewers with funny origins
- my d_x1DC = my d_x1DCmin = 0;
- my d_x2DC = my d_x2DCmax = 7.5 * resolution;
- my d_y1DC = my d_y1DCmin = 0;
- my d_y2DC = my d_y2DCmax = 11.0 * resolution;
- Graphics_setWsWindow (me.get(), 0, 7.5, 1.0, 12.0);
- Melder_assert (my d_macGraphicsContext);
- CGContextBeginPage (my d_macGraphicsContext, & rect);
- CGContextScaleCTM (my d_macGraphicsContext, 72.0 / resolution, 72.0 / resolution);
- CGContextTranslateCTM (my d_macGraphicsContext, - x1inches * resolution, (12.0 - y1inches) * resolution);
- CGContextScaleCTM (my d_macGraphicsContext, 1.0, -1.0);
- #endif
- return me.move();
- }
- #if cairo
- void *Graphics_x_getCR (Graphics me) {
- return ((GraphicsScreen) me) -> d_cairoGraphicsContext;
- }
- void Graphics_x_setCR (Graphics me, void *cairoGraphicsContext) {
- ((GraphicsScreen) me) -> d_cairoGraphicsContext = (cairo_t *) cairoGraphicsContext;
- }
- #endif
- #if quartz
- void GraphicsQuartz_initDraw (GraphicsScreen me) {
- if (my d_macView) {
- [my d_macView lockFocus];
- //if (! my printer) {
- my d_macGraphicsContext = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
- //}
- Melder_assert (my d_macGraphicsContext);
- if (my printer) {
- //CGContextTranslateCTM (my d_macGraphicsContext, 0, [my d_macView bounds]. size. height);
- //CGContextScaleCTM (my d_macGraphicsContext, 1.0, -1.0);
- }
- }
- }
- void GraphicsQuartz_exitDraw (GraphicsScreen me) {
- if (my d_macView) {
- //CGContextSynchronize (my d_macGraphicsContext); // BUG: should not be needed
- [my d_macView unlockFocus];
- }
- }
- #endif
- /* End of file GraphicsScreen.cpp */
|