[GDIPLUS] Sync with Wine Staging 3.9. CORE-14656
[reactos.git] / dll / win32 / gdiplus / gdiplus_private.h
1 /*
2 * Copyright (C) 2007 Google (Evan Stade)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #ifndef __WINE_GP_PRIVATE_H_
20 #define __WINE_GP_PRIVATE_H_
21
22 #include <math.h>
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "wingdi.h"
27 #include "winbase.h"
28 #include "winuser.h"
29
30 #include "objbase.h"
31 #include "ocidl.h"
32 #include "wincodecsdk.h"
33 #include "wine/heap.h"
34 #include "wine/list.h"
35
36 #include "gdiplus.h"
37
38 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
39
40 #define GP_DEFAULT_PENSTYLE (PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_MITER)
41 #define MAX_ARC_PTS (13)
42 #define MAX_DASHLEN (16) /* this is a limitation of gdi */
43 #define INCH_HIMETRIC (2540)
44
45 #define VERSION_MAGIC 0xdbc01001
46 #define VERSION_MAGIC2 0xdbc01002
47 #define VALID_MAGIC(x) (((x) & 0xfffff000) == 0xdbc01000)
48 #define TENSION_CONST (0.3)
49
50 #define GIF_DISPOSE_UNSPECIFIED 0
51 #define GIF_DISPOSE_DO_NOT_DISPOSE 1
52 #define GIF_DISPOSE_RESTORE_TO_BKGND 2
53 #define GIF_DISPOSE_RESTORE_TO_PREV 3
54
55
56 COLORREF ARGB2COLORREF(ARGB color) DECLSPEC_HIDDEN;
57 HBITMAP ARGB2BMP(ARGB color) DECLSPEC_HIDDEN;
58 extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
59 REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN;
60 extern REAL gdiplus_atan2(REAL dy, REAL dx) DECLSPEC_HIDDEN;
61 extern GpStatus hresult_to_status(HRESULT res) DECLSPEC_HIDDEN;
62 extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
63 extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
64 extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
65
66 #define WineCoordinateSpaceGdiDevice ((GpCoordinateSpace)4)
67
68 extern GpStatus gdi_transform_acquire(GpGraphics *graphics);
69 extern GpStatus gdi_transform_release(GpGraphics *graphics);
70 extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space,
71 GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN;
72 extern GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace dst_space,
73 GpCoordinateSpace src_space, GpPointF *points, INT count) DECLSPEC_HIDDEN;
74
75 extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
76 extern GpStatus encode_image_png(GpImage *image, IStream* stream, GDIPCONST EncoderParameters* params) DECLSPEC_HIDDEN;
77
78 extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN;
79 extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN;
80 extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN;
81 extern GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN;
82 extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
83 GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
84 extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile,
85 REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN;
86 extern GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode) DECLSPEC_HIDDEN;
87 extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
88 extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN;
89 extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN;
90 extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) DECLSPEC_HIDDEN;
91 extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN;
92 extern GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN;
93 extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN;
94 extern GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect,
95 GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN;
96 extern GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
97 extern GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
98 extern GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
99 extern GpStatus METAFILE_RestoreGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN;
100 extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
101 extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *image,
102 GDIPCONST GpPointF *points, INT count, REAL srcx, REAL srcy, REAL srcwidth,
103 REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes,
104 DrawImageAbort callback, VOID *callbackData) DECLSPEC_HIDDEN;
105 extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN;
106 extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN;
107 extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN;
108 extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
109
110 extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
111 REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
112 extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
113 REAL tension, REAL *x, REAL *y) DECLSPEC_HIDDEN;
114
115 extern void free_installed_fonts(void) DECLSPEC_HIDDEN;
116
117 extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN;
118
119 extern DWORD write_region_data(const GpRegion *region, void *data) DECLSPEC_HIDDEN;
120 extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN;
121
122 extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
123
124 typedef struct region_element region_element;
125 extern void delete_element(region_element *element) DECLSPEC_HIDDEN;
126
127 extern GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN;
128
129 static inline INT gdip_round(REAL x)
130 {
131 return (INT) floorf(x + 0.5);
132 }
133
134 static inline INT ceilr(REAL x)
135 {
136 return (INT) ceilf(x);
137 }
138
139 static inline REAL deg2rad(REAL degrees)
140 {
141 return M_PI * degrees / 180.0;
142 }
143
144 static inline ARGB color_over(ARGB bg, ARGB fg)
145 {
146 BYTE b, g, r, a;
147 BYTE bg_alpha, fg_alpha;
148
149 fg_alpha = (fg>>24)&0xff;
150
151 if (fg_alpha == 0xff) return fg;
152
153 if (fg_alpha == 0) return bg;
154
155 bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff;
156
157 if (bg_alpha == 0) return fg;
158
159 a = bg_alpha + fg_alpha;
160 b = ((bg&0xff)*bg_alpha + (fg&0xff)*fg_alpha)/a;
161 g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*fg_alpha)/a;
162 r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*fg_alpha)/a;
163
164 return (a<<24)|(r<<16)|(g<<8)|b;
165 }
166
167 /* fg is premult, bg and return value are not */
168 static inline ARGB color_over_fgpremult(ARGB bg, ARGB fg)
169 {
170 BYTE b, g, r, a;
171 BYTE bg_alpha, fg_alpha;
172
173 fg_alpha = (fg>>24)&0xff;
174
175 if (fg_alpha == 0) return bg;
176
177 bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff;
178
179 a = bg_alpha + fg_alpha;
180 b = ((bg&0xff)*bg_alpha + (fg&0xff)*0xff)/a;
181 g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*0xff)/a;
182 r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*0xff)/a;
183
184 return (a<<24)|(r<<16)|(g<<8)|b;
185 }
186
187 extern const char *debugstr_rectf(const RectF* rc) DECLSPEC_HIDDEN;
188
189 extern const char *debugstr_pointf(const PointF* pt) DECLSPEC_HIDDEN;
190
191 extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height,
192 BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) DECLSPEC_HIDDEN;
193
194 extern GpStatus convert_pixels(INT width, INT height,
195 INT dst_stride, BYTE *dst_bits, PixelFormat dst_format,
196 INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN;
197
198 extern PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
199 UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt) DECLSPEC_HIDDEN;
200
201 struct GpMatrix{
202 REAL matrix[6];
203 };
204
205 struct GpPen{
206 UINT style;
207 GpUnit unit;
208 REAL width;
209 GpLineCap endcap;
210 GpLineCap startcap;
211 GpDashCap dashcap;
212 GpCustomLineCap *customstart;
213 GpCustomLineCap *customend;
214 GpLineJoin join;
215 REAL miterlimit;
216 GpDashStyle dash;
217 REAL *dashes;
218 INT numdashes;
219 REAL offset; /* dash offset */
220 GpBrush *brush;
221 GpPenAlignment align;
222 GpMatrix transform;
223 };
224
225 struct GpGraphics{
226 HDC hdc;
227 HWND hwnd;
228 BOOL owndc;
229 BOOL alpha_hdc;
230 GpImage *image;
231 ImageType image_type;
232 SmoothingMode smoothing;
233 CompositingQuality compqual;
234 InterpolationMode interpolation;
235 PixelOffsetMode pixeloffset;
236 CompositingMode compmode;
237 TextRenderingHint texthint;
238 GpUnit unit; /* page unit */
239 REAL scale; /* page scale */
240 REAL xres, yres;
241 GpMatrix worldtrans; /* world transform */
242 BOOL busy; /* hdc handle obtained by GdipGetDC */
243 GpRegion *clip; /* in device coords */
244 UINT textcontrast; /* not used yet. get/set only */
245 struct list containers;
246 GraphicsContainer contid; /* last-issued container ID */
247 INT origin_x, origin_y;
248 INT gdi_transform_acquire_count, gdi_transform_save;
249 GpMatrix gdi_transform;
250 HRGN gdi_clip;
251 /* For giving the caller an HDC when we technically can't: */
252 HBITMAP temp_hbitmap;
253 int temp_hbitmap_width;
254 int temp_hbitmap_height;
255 BYTE *temp_bits;
256 HDC temp_hdc;
257 };
258
259 struct GpBrush{
260 GpBrushType bt;
261 };
262
263 struct GpHatch{
264 GpBrush brush;
265 GpHatchStyle hatchstyle;
266 ARGB forecol;
267 ARGB backcol;
268 };
269
270 struct GpSolidFill{
271 GpBrush brush;
272 ARGB color;
273 };
274
275 struct GpPathGradient{
276 GpBrush brush;
277 GpPath* path;
278 ARGB centercolor;
279 GpWrapMode wrap;
280 BOOL gamma;
281 GpPointF center;
282 GpPointF focus;
283 REAL* blendfac; /* blend factors */
284 REAL* blendpos; /* blend positions */
285 INT blendcount;
286 ARGB *surroundcolors;
287 INT surroundcolorcount;
288 ARGB* pblendcolor; /* preset blend colors */
289 REAL* pblendpos; /* preset blend positions */
290 INT pblendcount;
291 GpMatrix transform;
292 };
293
294 struct GpLineGradient{
295 GpBrush brush;
296 GpPointF startpoint;
297 GpPointF endpoint;
298 ARGB startcolor;
299 ARGB endcolor;
300 RectF rect;
301 GpWrapMode wrap;
302 BOOL gamma;
303 REAL* blendfac; /* blend factors */
304 REAL* blendpos; /* blend positions */
305 INT blendcount;
306 ARGB* pblendcolor; /* preset blend colors */
307 REAL* pblendpos; /* preset blend positions */
308 INT pblendcount;
309 GpMatrix transform;
310 };
311
312 struct GpTexture{
313 GpBrush brush;
314 GpMatrix transform;
315 GpImage *image;
316 GpImageAttributes *imageattributes;
317 BYTE *bitmap_bits; /* image bits converted to ARGB and run through imageattributes */
318 };
319
320 struct GpPath{
321 GpFillMode fill;
322 GpPathData pathdata;
323 BOOL newfigure; /* whether the next drawing action starts a new figure */
324 INT datalen; /* size of the arrays in pathdata */
325 };
326
327 struct GpPathIterator{
328 GpPathData pathdata;
329 INT subpath_pos; /* for NextSubpath methods */
330 INT marker_pos; /* for NextMarker methods */
331 INT pathtype_pos; /* for NextPathType methods */
332 };
333
334 struct GpCustomLineCap{
335 CustomLineCapType type;
336 GpPathData pathdata;
337 BOOL fill; /* TRUE for fill, FALSE for stroke */
338 GpLineCap cap; /* as far as I can tell, this value is ignored */
339 REAL inset; /* how much to adjust the end of the line */
340 GpLineJoin join;
341 REAL scale;
342 };
343
344 struct GpAdjustableArrowCap{
345 GpCustomLineCap cap;
346 REAL middle_inset;
347 REAL height;
348 REAL width;
349 };
350
351 struct GpImage{
352 IWICBitmapDecoder *decoder;
353 ImageType type;
354 GUID format;
355 UINT flags;
356 UINT frame_count, current_frame;
357 ColorPalette *palette;
358 REAL xres, yres;
359 LONG busy;
360 };
361
362 #define EmfPlusObjectTableSize 64
363
364 typedef enum EmfPlusObjectType
365 {
366 ObjectTypeInvalid,
367 ObjectTypeBrush,
368 ObjectTypePen,
369 ObjectTypePath,
370 ObjectTypeRegion,
371 ObjectTypeImage,
372 ObjectTypeFont,
373 ObjectTypeStringFormat,
374 ObjectTypeImageAttributes,
375 ObjectTypeCustomLineCap,
376 ObjectTypeMax = ObjectTypeCustomLineCap,
377 } EmfPlusObjectType;
378
379 /* Deserialized EmfPlusObject record. */
380 struct emfplus_object {
381 EmfPlusObjectType type;
382 union {
383 GpBrush *brush;
384 GpPen *pen;
385 GpPath *path;
386 GpRegion *region;
387 GpImage *image;
388 GpFont *font;
389 GpImageAttributes *image_attributes;
390 void *object;
391 } u;
392 };
393
394 struct GpMetafile{
395 GpImage image;
396 GpRectF bounds;
397 GpUnit unit;
398 MetafileType metafile_type;
399 HENHMETAFILE hemf;
400 int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */
401
402 /* recording */
403 HDC record_dc;
404 GpGraphics *record_graphics;
405 BYTE *comment_data;
406 DWORD comment_data_size;
407 DWORD comment_data_length;
408 IStream *record_stream;
409 BOOL auto_frame; /* If true, determine the frame automatically */
410 GpPointF auto_frame_min, auto_frame_max;
411 DWORD next_object_id;
412
413 /* playback */
414 GpGraphics *playback_graphics;
415 HDC playback_dc;
416 GpPointF playback_points[3];
417 GpRectF src_rect;
418 HANDLETABLE *handle_table;
419 int handle_count;
420 XFORM gdiworldtransform;
421 GpMatrix *world_transform;
422 GpUnit page_unit;
423 REAL page_scale;
424 GpRegion *base_clip; /* clip region in device space for all metafile output */
425 GpRegion *clip; /* clip region within the metafile */
426 struct list containers;
427 struct emfplus_object objtable[EmfPlusObjectTableSize];
428 };
429
430 struct GpBitmap{
431 GpImage image;
432 INT width;
433 INT height;
434 PixelFormat format;
435 ImageLockMode lockmode;
436 BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */
437 HBITMAP hbitmap;
438 HDC hdc;
439 BYTE *bits; /* actual image bits if this is a DIB */
440 INT stride; /* stride of bits if this is a DIB */
441 BYTE *own_bits; /* image bits that need to be freed with this object */
442 INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */
443 IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */
444 UINT prop_count;
445 PropertyItem *prop_item; /* cached image properties */
446 };
447
448 struct GpCachedBitmap{
449 GpImage *image;
450 };
451
452 struct color_key{
453 BOOL enabled;
454 ARGB low;
455 ARGB high;
456 };
457
458 struct color_matrix{
459 BOOL enabled;
460 ColorMatrixFlags flags;
461 ColorMatrix colormatrix;
462 ColorMatrix graymatrix;
463 };
464
465 struct color_remap_table{
466 BOOL enabled;
467 INT mapsize;
468 ColorMap *colormap;
469 };
470
471 enum imageattr_noop{
472 IMAGEATTR_NOOP_UNDEFINED,
473 IMAGEATTR_NOOP_SET,
474 IMAGEATTR_NOOP_CLEAR,
475 };
476
477 struct GpImageAttributes{
478 WrapMode wrap;
479 ARGB outside_color;
480 BOOL clamp;
481 struct color_key colorkeys[ColorAdjustTypeCount];
482 struct color_matrix colormatrices[ColorAdjustTypeCount];
483 struct color_remap_table colorremaptables[ColorAdjustTypeCount];
484 BOOL gamma_enabled[ColorAdjustTypeCount];
485 REAL gamma[ColorAdjustTypeCount];
486 enum imageattr_noop noop[ColorAdjustTypeCount];
487 };
488
489 struct GpFont{
490 GpFontFamily *family;
491 OUTLINETEXTMETRICW otm;
492 REAL emSize; /* in font units */
493 Unit unit;
494 };
495
496 extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN;
497
498 struct GpStringFormat{
499 INT attr;
500 LANGID lang;
501 LANGID digitlang;
502 StringAlignment align;
503 StringTrimming trimming;
504 HotkeyPrefix hkprefix;
505 StringAlignment line_align;
506 StringDigitSubstitute digitsub;
507 INT tabcount;
508 REAL firsttab;
509 REAL *tabs;
510 CharacterRange *character_ranges;
511 INT range_count;
512 BOOL generic_typographic;
513 };
514
515 extern void init_generic_string_formats(void) DECLSPEC_HIDDEN;
516 extern void free_generic_string_formats(void) DECLSPEC_HIDDEN;
517
518 struct GpFontCollection{
519 GpFontFamily **FontFamilies;
520 INT count;
521 INT allocated;
522 };
523
524 struct GpFontFamily{
525 WCHAR FamilyName[LF_FACESIZE];
526 UINT16 em_height, ascent, descent, line_spacing; /* in font units */
527 int dpi;
528 };
529
530 /* internal use */
531 typedef enum RegionType
532 {
533 RegionDataRect = 0x10000000,
534 RegionDataPath = 0x10000001,
535 RegionDataEmptyRect = 0x10000002,
536 RegionDataInfiniteRect = 0x10000003,
537 } RegionType;
538
539 struct region_element
540 {
541 DWORD type; /* Rectangle, Path, SpecialRectangle, or CombineMode */
542 union
543 {
544 GpRectF rect;
545 GpPath *path;
546 struct
547 {
548 struct region_element *left; /* the original region */
549 struct region_element *right; /* what *left was combined with */
550 } combine;
551 } elementdata;
552 };
553
554 struct GpRegion{
555 DWORD num_children;
556 region_element node;
557 };
558
559 struct memory_buffer
560 {
561 const BYTE *buffer;
562 INT size, pos;
563 };
564
565 static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size)
566 {
567 mbuf->buffer = buffer;
568 mbuf->size = size;
569 mbuf->pos = 0;
570 }
571
572 static inline const void *buffer_read(struct memory_buffer *mbuf, INT size)
573 {
574 if (mbuf->size - mbuf->pos >= size)
575 {
576 const void *data = mbuf->buffer + mbuf->pos;
577 mbuf->pos += size;
578 return data;
579 }
580 return NULL;
581 }
582
583 typedef GpStatus (*gdip_format_string_callback)(HDC hdc,
584 GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font,
585 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
586 INT lineno, const RectF *bounds, INT *underlined_indexes,
587 INT underlined_index_count, void *user_data);
588
589 GpStatus gdip_format_string(HDC hdc,
590 GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font,
591 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip,
592 gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN;
593
594 void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN;
595
596 static inline BOOL image_lock(GpImage *image, BOOL *unlock)
597 {
598 LONG tid = GetCurrentThreadId(), owner_tid;
599 owner_tid = InterlockedCompareExchange(&image->busy, tid, 0);
600 *unlock = !owner_tid;
601 return !owner_tid || owner_tid==tid;
602 }
603
604 static inline void image_unlock(GpImage *image, BOOL unlock)
605 {
606 if (unlock) image->busy = 0;
607 }
608
609 #endif