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 610