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