usp10: Handle an offset of the first glyph.
[wine] / dlls / winemac.drv / gdi.c
1 /*
2  * Mac graphics driver initialisation functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  * Copyright 2011, 2012 Ken Thomases for CodeWeavers, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include "macdrv.h"
25 #include "winreg.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
28
29
30 typedef struct
31 {
32     struct gdi_physdev  dev;
33 } MACDRV_PDEVICE;
34
35 static inline MACDRV_PDEVICE *get_macdrv_dev(PHYSDEV dev)
36 {
37     return (MACDRV_PDEVICE*)dev;
38 }
39
40
41 /* a few dynamic device caps */
42 static CGRect desktop_rect;     /* virtual desktop rectangle */
43 static int log_pixels_x;        /* pixels per logical inch in x direction */
44 static int log_pixels_y;        /* pixels per logical inch in y direction */
45 static int horz_size;           /* horz. size of screen in millimeters */
46 static int vert_size;           /* vert. size of screen in millimeters */
47 static int horz_res;            /* width in pixels of screen */
48 static int vert_res;            /* height in pixels of screen */
49 static int desktop_horz_res;    /* width in pixels of virtual desktop */
50 static int desktop_vert_res;    /* height in pixels of virtual desktop */
51 static int bits_per_pixel;      /* pixel depth of screen */
52 static int palette_size;        /* number of color entries in palette */
53 static int device_data_valid;   /* do the above variables have up-to-date values? */
54
55 static CRITICAL_SECTION device_data_section;
56 static CRITICAL_SECTION_DEBUG critsect_debug =
57 {
58     0, 0, &device_data_section,
59     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
60       0, 0, { (DWORD_PTR)(__FILE__ ": device_data_section") }
61 };
62 static CRITICAL_SECTION device_data_section = { &critsect_debug, -1, 0, 0, 0, 0 };
63
64
65 static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
66 static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};
67
68 static const struct gdi_dc_funcs macdrv_funcs;
69
70
71 /******************************************************************************
72  *              get_dpi
73  *
74  * get the dpi from the registry
75  */
76 static DWORD get_dpi(void)
77 {
78     DWORD dpi = 0;
79     HKEY hkey;
80
81     if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS)
82     {
83         DWORD type, size, new_dpi;
84
85         size = sizeof(new_dpi);
86         if (RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS)
87         {
88             if (type == REG_DWORD && new_dpi != 0)
89                 dpi = new_dpi;
90         }
91         RegCloseKey(hkey);
92     }
93     return dpi;
94 }
95
96
97 /***********************************************************************
98  *              macdrv_get_desktop_rect
99  *
100  * Returns the rectangle encompassing all the screens.
101  */
102 CGRect macdrv_get_desktop_rect(void)
103 {
104     CGRect ret;
105     CGDirectDisplayID displayIDs[32];
106     uint32_t count, i;
107
108     EnterCriticalSection(&device_data_section);
109
110     if (!device_data_valid)
111     {
112         desktop_rect = CGRectNull;
113         if (CGGetActiveDisplayList(sizeof(displayIDs)/sizeof(displayIDs[0]),
114                                    displayIDs, &count) != kCGErrorSuccess ||
115             !count)
116         {
117             displayIDs[0] = CGMainDisplayID();
118             count = 1;
119         }
120
121         for (i = 0; i < count; i++)
122             desktop_rect = CGRectUnion(desktop_rect, CGDisplayBounds(displayIDs[i]));
123     }
124
125     ret = desktop_rect;
126     LeaveCriticalSection(&device_data_section);
127
128     TRACE("%s\n", wine_dbgstr_cgrect(ret));
129
130     return ret;
131 }
132
133
134 /**********************************************************************
135  *              device_init
136  *
137  * Perform initializations needed upon creation of the first device.
138  */
139 static void device_init(void)
140 {
141     CGDirectDisplayID mainDisplay = CGMainDisplayID();
142     CGSize size_mm = CGDisplayScreenSize(mainDisplay);
143     CGDisplayModeRef mode = CGDisplayCopyDisplayMode(mainDisplay);
144     CGDirectPaletteRef palette;
145
146     /* Initialize device caps */
147     log_pixels_x = log_pixels_y = get_dpi();
148     if (!log_pixels_x)
149     {
150         size_t width = CGDisplayPixelsWide(mainDisplay);
151         size_t height = CGDisplayPixelsHigh(mainDisplay);
152         log_pixels_x = MulDiv(width, 254, size_mm.width * 10);
153         log_pixels_y = MulDiv(height, 254, size_mm.height * 10);
154     }
155
156     horz_size = size_mm.width;
157     vert_size = size_mm.height;
158
159     bits_per_pixel = 32;
160     if (mode)
161     {
162         CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(mode);
163
164         horz_res = CGDisplayModeGetWidth(mode);
165         vert_res = CGDisplayModeGetHeight(mode);
166
167         if (pixelEncoding)
168         {
169             if (CFEqual(pixelEncoding, CFSTR(IO32BitDirectPixels)))
170                 bits_per_pixel = 32;
171             else if (CFEqual(pixelEncoding, CFSTR(IO16BitDirectPixels)))
172                 bits_per_pixel = 16;
173             else if (CFEqual(pixelEncoding, CFSTR(IO8BitIndexedPixels)))
174                 bits_per_pixel = 8;
175             CFRelease(pixelEncoding);
176         }
177
178         CGDisplayModeRelease(mode);
179     }
180     else
181     {
182         horz_res = CGDisplayPixelsWide(mainDisplay);
183         vert_res = CGDisplayPixelsHigh(mainDisplay);
184     }
185
186     macdrv_get_desktop_rect();
187     desktop_horz_res = desktop_rect.size.width;
188     desktop_vert_res = desktop_rect.size.height;
189
190     palette = CGPaletteCreateWithDisplay(mainDisplay);
191     if (palette)
192     {
193         palette_size = CGPaletteGetNumberOfSamples(palette);
194         CGPaletteRelease(palette);
195     }
196     else
197         palette_size = 0;
198
199     device_data_valid = TRUE;
200 }
201
202
203 static MACDRV_PDEVICE *create_mac_physdev(void)
204 {
205     MACDRV_PDEVICE *physDev;
206
207     EnterCriticalSection(&device_data_section);
208     if (!device_data_valid) device_init();
209     LeaveCriticalSection(&device_data_section);
210
211     if (!(physDev = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*physDev)))) return NULL;
212
213     return physDev;
214 }
215
216
217 /**********************************************************************
218  *              CreateDC (MACDRV.@)
219  */
220 static BOOL macdrv_CreateDC(PHYSDEV *pdev, LPCWSTR driver, LPCWSTR device,
221                             LPCWSTR output, const DEVMODEW* initData)
222 {
223     MACDRV_PDEVICE *physDev = create_mac_physdev();
224
225     TRACE("pdev %p hdc %p driver %s device %s output %s initData %p\n", pdev,
226           (*pdev)->hdc, debugstr_w(driver),debugstr_w(device), debugstr_w(output),
227           initData);
228
229     if (!physDev) return FALSE;
230
231     push_dc_driver(pdev, &physDev->dev, &macdrv_funcs);
232     return TRUE;
233 }
234
235
236 /**********************************************************************
237  *              CreateCompatibleDC (MACDRV.@)
238  */
239 static BOOL macdrv_CreateCompatibleDC(PHYSDEV orig, PHYSDEV *pdev)
240 {
241     MACDRV_PDEVICE *physDev = create_mac_physdev();
242
243     TRACE("orig %p orig->hdc %p pdev %p pdev->hdc %p\n", orig, (orig ? orig->hdc : NULL), pdev,
244           ((pdev && *pdev) ? (*pdev)->hdc : NULL));
245
246     if (!physDev) return FALSE;
247
248     push_dc_driver(pdev, &physDev->dev, &macdrv_funcs);
249     return TRUE;
250 }
251
252
253 /**********************************************************************
254  *              DeleteDC (MACDRV.@)
255  */
256 static BOOL macdrv_DeleteDC(PHYSDEV dev)
257 {
258     MACDRV_PDEVICE *physDev = get_macdrv_dev(dev);
259
260     TRACE("hdc %p\n", dev->hdc);
261
262     HeapFree(GetProcessHeap(), 0, physDev);
263     return TRUE;
264 }
265
266
267 /***********************************************************************
268  *              GetDeviceCaps (MACDRV.@)
269  */
270 static INT macdrv_GetDeviceCaps(PHYSDEV dev, INT cap)
271 {
272     INT ret;
273
274     EnterCriticalSection(&device_data_section);
275
276     if (!device_data_valid) device_init();
277
278     switch(cap)
279     {
280     case DRIVERVERSION:
281         ret = 0x300;
282         break;
283     case TECHNOLOGY:
284         ret = DT_RASDISPLAY;
285         break;
286     case HORZSIZE:
287         ret = horz_size;
288         break;
289     case VERTSIZE:
290         ret = vert_size;
291         break;
292     case HORZRES:
293         ret = horz_res;
294         break;
295     case VERTRES:
296         ret = vert_res;
297         break;
298     case DESKTOPHORZRES:
299         ret = desktop_horz_res;
300         break;
301     case DESKTOPVERTRES:
302         ret = desktop_vert_res;
303         break;
304     case BITSPIXEL:
305         ret = bits_per_pixel;
306         break;
307     case PLANES:
308         ret = 1;
309         break;
310     case NUMBRUSHES:
311         ret = -1;
312         break;
313     case NUMPENS:
314         ret = -1;
315         break;
316     case NUMMARKERS:
317         ret = 0;
318         break;
319     case NUMFONTS:
320         ret = 0;
321         break;
322     case NUMCOLORS:
323         /* MSDN: Number of entries in the device's color table, if the device has
324          * a color depth of no more than 8 bits per pixel.For devices with greater
325          * color depths, -1 is returned. */
326         ret = (bits_per_pixel > 8) ? -1 : (1 << bits_per_pixel);
327         break;
328     case PDEVICESIZE:
329         ret = sizeof(MACDRV_PDEVICE);
330         break;
331     case CURVECAPS:
332         ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
333                CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
334         break;
335     case LINECAPS:
336         ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
337                LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
338         break;
339     case POLYGONALCAPS:
340         ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
341                PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
342         break;
343     case TEXTCAPS:
344         ret = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
345                TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER |
346                TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE);
347         break;
348     case CLIPCAPS:
349         ret = CP_REGION;
350         break;
351     case COLORRES:
352         /* The observed correspondence between BITSPIXEL and COLORRES is:
353          * BITSPIXEL: 8  -> COLORRES: 18
354          * BITSPIXEL: 16 -> COLORRES: 16
355          * BITSPIXEL: 24 -> COLORRES: 24
356          * (note that bits_per_pixel is never 24)
357          * BITSPIXEL: 32 -> COLORRES: 24 */
358         ret = (bits_per_pixel <= 8) ? 18 : (bits_per_pixel == 32) ? 24 : bits_per_pixel;
359         break;
360     case RASTERCAPS:
361         ret = (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP |
362                RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS |
363                (palette_size ? RC_PALETTE : 0));
364         break;
365     case SHADEBLENDCAPS:
366         ret = (SB_GRAD_RECT | SB_GRAD_TRI | SB_CONST_ALPHA | SB_PIXEL_ALPHA);
367         break;
368     case ASPECTX:
369     case ASPECTY:
370         ret = 36;
371         break;
372     case ASPECTXY:
373         ret = 51;
374         break;
375     case LOGPIXELSX:
376         ret = log_pixels_x;
377         break;
378     case LOGPIXELSY:
379         ret = log_pixels_y;
380         break;
381     case CAPS1:
382         FIXME("(%p): CAPS1 is unimplemented, will return 0\n", dev->hdc);
383         /* please see wingdi.h for the possible bit-flag values that need
384            to be returned. */
385         ret = 0;
386         break;
387     case SIZEPALETTE:
388         ret = palette_size;
389         break;
390     case NUMRESERVED:
391     case PHYSICALWIDTH:
392     case PHYSICALHEIGHT:
393     case PHYSICALOFFSETX:
394     case PHYSICALOFFSETY:
395     case SCALINGFACTORX:
396     case SCALINGFACTORY:
397     case VREFRESH:
398     case BLTALIGNMENT:
399         ret = 0;
400         break;
401     default:
402         FIXME("(%p): unsupported capability %d, will return 0\n", dev->hdc, cap);
403         ret = 0;
404         goto done;
405     }
406
407     TRACE("cap %d -> %d\n", cap, ret);
408
409 done:
410     LeaveCriticalSection(&device_data_section);
411     return ret;
412 }
413
414
415 static const struct gdi_dc_funcs macdrv_funcs =
416 {
417     NULL,                                   /* pAbortDoc */
418     NULL,                                   /* pAbortPath */
419     NULL,                                   /* pAlphaBlend */
420     NULL,                                   /* pAngleArc */
421     NULL,                                   /* pArc */
422     NULL,                                   /* pArcTo */
423     NULL,                                   /* pBeginPath */
424     NULL,                                   /* pBlendImage */
425     NULL,                                   /* pChord */
426     NULL,                                   /* pCloseFigure */
427     macdrv_CreateCompatibleDC,              /* pCreateCompatibleDC */
428     macdrv_CreateDC,                        /* pCreateDC */
429     macdrv_DeleteDC,                        /* pDeleteDC */
430     NULL,                                   /* pDeleteObject */
431     NULL,                                   /* pDeviceCapabilities */
432     NULL,                                   /* pEllipse */
433     NULL,                                   /* pEndDoc */
434     NULL,                                   /* pEndPage */
435     NULL,                                   /* pEndPath */
436     NULL,                                   /* pEnumFonts */
437     NULL,                                   /* pEnumICMProfiles */
438     NULL,                                   /* pExcludeClipRect */
439     NULL,                                   /* pExtDeviceMode */
440     NULL,                                   /* pExtEscape */
441     NULL,                                   /* pExtFloodFill */
442     NULL,                                   /* pExtSelectClipRgn */
443     NULL,                                   /* pExtTextOut */
444     NULL,                                   /* pFillPath */
445     NULL,                                   /* pFillRgn */
446     NULL,                                   /* pFlattenPath */
447     NULL,                                   /* pFontIsLinked */
448     NULL,                                   /* pFrameRgn */
449     NULL,                                   /* pGdiComment */
450     NULL,                                   /* pGdiRealizationInfo */
451     NULL,                                   /* pGetBoundsRect */
452     NULL,                                   /* pGetCharABCWidths */
453     NULL,                                   /* pGetCharABCWidthsI */
454     NULL,                                   /* pGetCharWidth */
455     macdrv_GetDeviceCaps,                   /* pGetDeviceCaps */
456     NULL,                                   /* pGetDeviceGammaRamp */
457     NULL,                                   /* pGetFontData */
458     NULL,                                   /* pGetFontUnicodeRanges */
459     NULL,                                   /* pGetGlyphIndices */
460     NULL,                                   /* pGetGlyphOutline */
461     NULL,                                   /* pGetICMProfile */
462     NULL,                                   /* pGetImage */
463     NULL,                                   /* pGetKerningPairs */
464     NULL,                                   /* pGetNearestColor */
465     NULL,                                   /* pGetOutlineTextMetrics */
466     NULL,                                   /* pGetPixel */
467     NULL,                                   /* pGetSystemPaletteEntries */
468     NULL,                                   /* pGetTextCharsetInfo */
469     NULL,                                   /* pGetTextExtentExPoint */
470     NULL,                                   /* pGetTextExtentExPointI */
471     NULL,                                   /* pGetTextFace */
472     NULL,                                   /* pGetTextMetrics */
473     NULL,                                   /* pGradientFill */
474     NULL,                                   /* pIntersectClipRect */
475     NULL,                                   /* pInvertRgn */
476     NULL,                                   /* pLineTo */
477     NULL,                                   /* pModifyWorldTransform */
478     NULL,                                   /* pMoveTo */
479     NULL,                                   /* pOffsetClipRgn */
480     NULL,                                   /* pOffsetViewportOrg */
481     NULL,                                   /* pOffsetWindowOrg */
482     NULL,                                   /* pPaintRgn */
483     NULL,                                   /* pPatBlt */
484     NULL,                                   /* pPie */
485     NULL,                                   /* pPolyBezier */
486     NULL,                                   /* pPolyBezierTo */
487     NULL,                                   /* pPolyDraw */
488     NULL,                                   /* pPolyPolygon */
489     NULL,                                   /* pPolyPolyline */
490     NULL,                                   /* pPolygon */
491     NULL,                                   /* pPolyline */
492     NULL,                                   /* pPolylineTo */
493     NULL,                                   /* pPutImage */
494     NULL,                                   /* pRealizeDefaultPalette */
495     NULL,                                   /* pRealizePalette */
496     NULL,                                   /* pRectangle */
497     NULL,                                   /* pResetDC */
498     NULL,                                   /* pRestoreDC */
499     NULL,                                   /* pRoundRect */
500     NULL,                                   /* pSaveDC */
501     NULL,                                   /* pScaleViewportExt */
502     NULL,                                   /* pScaleWindowExt */
503     NULL,                                   /* pSelectBitmap */
504     NULL,                                   /* pSelectBrush */
505     NULL,                                   /* pSelectClipPath */
506     NULL,                                   /* pSelectFont */
507     NULL,                                   /* pSelectPalette */
508     NULL,                                   /* pSelectPen */
509     NULL,                                   /* pSetArcDirection */
510     NULL,                                   /* pSetBkColor */
511     NULL,                                   /* pSetBkMode */
512     NULL,                                   /* pSetBoundsRect */
513     NULL,                                   /* pSetDCBrushColor */
514     NULL,                                   /* pSetDCPenColor */
515     NULL,                                   /* pSetDIBitsToDevice */
516     NULL,                                   /* pSetDeviceClipping */
517     NULL,                                   /* pSetDeviceGammaRamp */
518     NULL,                                   /* pSetLayout */
519     NULL,                                   /* pSetMapMode */
520     NULL,                                   /* pSetMapperFlags */
521     NULL,                                   /* pSetPixel */
522     NULL,                                   /* pSetPolyFillMode */
523     NULL,                                   /* pSetROP2 */
524     NULL,                                   /* pSetRelAbs */
525     NULL,                                   /* pSetStretchBltMode */
526     NULL,                                   /* pSetTextAlign */
527     NULL,                                   /* pSetTextCharacterExtra */
528     NULL,                                   /* pSetTextColor */
529     NULL,                                   /* pSetTextJustification */
530     NULL,                                   /* pSetViewportExt */
531     NULL,                                   /* pSetViewportOrg */
532     NULL,                                   /* pSetWindowExt */
533     NULL,                                   /* pSetWindowOrg */
534     NULL,                                   /* pSetWorldTransform */
535     NULL,                                   /* pStartDoc */
536     NULL,                                   /* pStartPage */
537     NULL,                                   /* pStretchBlt */
538     NULL,                                   /* pStretchDIBits */
539     NULL,                                   /* pStrokeAndFillPath */
540     NULL,                                   /* pStrokePath */
541     NULL,                                   /* pUnrealizePalette */
542     NULL,                                   /* pWidenPath */
543     NULL,                                   /* wine_get_wgl_driver */
544     GDI_PRIORITY_GRAPHICS_DRV               /* priority */
545 };
546
547
548 /******************************************************************************
549  *              macdrv_get_gdi_driver
550  */
551 const struct gdi_dc_funcs * CDECL macdrv_get_gdi_driver(unsigned int version)
552 {
553     if (version != WINE_GDI_DRIVER_VERSION)
554     {
555         ERR("version mismatch, gdi32 wants %u but winemac has %u\n", version, WINE_GDI_DRIVER_VERSION);
556         return NULL;
557     }
558     return &macdrv_funcs;
559 }