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 GpPointF startpoint; 295 GpPointF endpoint; 296 ARGB startcolor; 297 ARGB endcolor; 298 RectF rect; 299 GpWrapMode wrap; 300 BOOL gamma; 301 REAL* blendfac; /* blend factors */ 302 REAL* blendpos; /* blend positions */ 303 INT blendcount; 304 ARGB* pblendcolor; /* preset blend colors */ 305 REAL* pblendpos; /* preset blend positions */ 306 INT pblendcount; 307 GpMatrix transform; 308 }; 309 310 struct GpTexture{ 311 GpBrush brush; 312 GpMatrix transform; 313 GpImage *image; 314 GpImageAttributes *imageattributes; 315 BYTE *bitmap_bits; /* image bits converted to ARGB and run through imageattributes */ 316 }; 317 318 struct GpPath{ 319 GpFillMode fill; 320 GpPathData pathdata; 321 BOOL newfigure; /* whether the next drawing action starts a new figure */ 322 INT datalen; /* size of the arrays in pathdata */ 323 }; 324 325 struct GpPathIterator{ 326 GpPathData pathdata; 327 INT subpath_pos; /* for NextSubpath methods */ 328 INT marker_pos; /* for NextMarker methods */ 329 INT pathtype_pos; /* for NextPathType methods */ 330 }; 331 332 struct GpCustomLineCap{ 333 CustomLineCapType type; 334 GpPathData pathdata; 335 BOOL fill; /* TRUE for fill, FALSE for stroke */ 336 GpLineCap cap; /* as far as I can tell, this value is ignored */ 337 REAL inset; /* how much to adjust the end of the line */ 338 GpLineJoin join; 339 REAL scale; 340 }; 341 342 struct GpAdjustableArrowCap{ 343 GpCustomLineCap cap; 344 }; 345 346 struct GpImage{ 347 IWICBitmapDecoder *decoder; 348 ImageType type; 349 GUID format; 350 UINT flags; 351 UINT frame_count, current_frame; 352 ColorPalette *palette; 353 REAL xres, yres; 354 LONG busy; 355 }; 356 357 #define EmfPlusObjectTableSize 64 358 359 typedef enum EmfPlusObjectType 360 { 361 ObjectTypeInvalid, 362 ObjectTypeBrush, 363 ObjectTypePen, 364 ObjectTypePath, 365 ObjectTypeRegion, 366 ObjectTypeImage, 367 ObjectTypeFont, 368 ObjectTypeStringFormat, 369 ObjectTypeImageAttributes, 370 ObjectTypeCustomLineCap, 371 ObjectTypeMax = ObjectTypeCustomLineCap, 372 } EmfPlusObjectType; 373 374 /* Deserialized EmfPlusObject record. */ 375 struct emfplus_object { 376 EmfPlusObjectType type; 377 union { 378 GpBrush *brush; 379 GpPen *pen; 380 GpPath *path; 381 GpRegion *region; 382 GpImage *image; 383 GpFont *font; 384 GpImageAttributes *image_attributes; 385 void *object; 386 } u; 387 }; 388 389 struct GpMetafile{ 390 GpImage image; 391 GpRectF bounds; 392 GpUnit unit; 393 MetafileType metafile_type; 394 HENHMETAFILE hemf; 395 int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */ 396 397 /* recording */ 398 HDC record_dc; 399 GpGraphics *record_graphics; 400 BYTE *comment_data; 401 DWORD comment_data_size; 402 DWORD comment_data_length; 403 IStream *record_stream; 404 BOOL auto_frame; /* If true, determine the frame automatically */ 405 GpPointF auto_frame_min, auto_frame_max; 406 DWORD next_object_id; 407 408 /* playback */ 409 GpGraphics *playback_graphics; 410 HDC playback_dc; 411 GpPointF playback_points[3]; 412 GpRectF src_rect; 413 HANDLETABLE *handle_table; 414 int handle_count; 415 XFORM gdiworldtransform; 416 GpMatrix *world_transform; 417 GpUnit page_unit; 418 REAL page_scale; 419 GpRegion *base_clip; /* clip region in device space for all metafile output */ 420 GpRegion *clip; /* clip region within the metafile */ 421 struct list containers; 422 struct emfplus_object objtable[EmfPlusObjectTableSize]; 423 }; 424 425 struct GpBitmap{ 426 GpImage image; 427 INT width; 428 INT height; 429 PixelFormat format; 430 ImageLockMode lockmode; 431 BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */ 432 HBITMAP hbitmap; 433 HDC hdc; 434 BYTE *bits; /* actual image bits if this is a DIB */ 435 INT stride; /* stride of bits if this is a DIB */ 436 BYTE *own_bits; /* image bits that need to be freed with this object */ 437 INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */ 438 IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */ 439 UINT prop_count; 440 PropertyItem *prop_item; /* cached image properties */ 441 }; 442 443 struct GpCachedBitmap{ 444 GpImage *image; 445 }; 446 447 struct color_key{ 448 BOOL enabled; 449 ARGB low; 450 ARGB high; 451 }; 452 453 struct color_matrix{ 454 BOOL enabled; 455 ColorMatrixFlags flags; 456 ColorMatrix colormatrix; 457 ColorMatrix graymatrix; 458 }; 459 460 struct color_remap_table{ 461 BOOL enabled; 462 INT mapsize; 463 ColorMap *colormap; 464 }; 465 466 enum imageattr_noop{ 467 IMAGEATTR_NOOP_UNDEFINED, 468 IMAGEATTR_NOOP_SET, 469 IMAGEATTR_NOOP_CLEAR, 470 }; 471 472 struct GpImageAttributes{ 473 WrapMode wrap; 474 ARGB outside_color; 475 BOOL clamp; 476 struct color_key colorkeys[ColorAdjustTypeCount]; 477 struct color_matrix colormatrices[ColorAdjustTypeCount]; 478 struct color_remap_table colorremaptables[ColorAdjustTypeCount]; 479 BOOL gamma_enabled[ColorAdjustTypeCount]; 480 REAL gamma[ColorAdjustTypeCount]; 481 enum imageattr_noop noop[ColorAdjustTypeCount]; 482 }; 483 484 struct GpFont{ 485 GpFontFamily *family; 486 OUTLINETEXTMETRICW otm; 487 REAL emSize; /* in font units */ 488 Unit unit; 489 }; 490 491 extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN; 492 493 struct GpStringFormat{ 494 INT attr; 495 LANGID lang; 496 LANGID digitlang; 497 StringAlignment align; 498 StringTrimming trimming; 499 HotkeyPrefix hkprefix; 500 StringAlignment line_align; 501 StringDigitSubstitute digitsub; 502 INT tabcount; 503 REAL firsttab; 504 REAL *tabs; 505 CharacterRange *character_ranges; 506 INT range_count; 507 BOOL generic_typographic; 508 }; 509 510 extern void init_generic_string_formats(void) DECLSPEC_HIDDEN; 511 extern void free_generic_string_formats(void) DECLSPEC_HIDDEN; 512 513 struct GpFontCollection{ 514 GpFontFamily **FontFamilies; 515 INT count; 516 INT allocated; 517 }; 518 519 struct GpFontFamily{ 520 WCHAR FamilyName[LF_FACESIZE]; 521 UINT16 em_height, ascent, descent, line_spacing; /* in font units */ 522 int dpi; 523 }; 524 525 /* internal use */ 526 typedef enum RegionType 527 { 528 RegionDataRect = 0x10000000, 529 RegionDataPath = 0x10000001, 530 RegionDataEmptyRect = 0x10000002, 531 RegionDataInfiniteRect = 0x10000003, 532 } RegionType; 533 534 struct region_element 535 { 536 DWORD type; /* Rectangle, Path, SpecialRectangle, or CombineMode */ 537 union 538 { 539 GpRectF rect; 540 GpPath *path; 541 struct 542 { 543 struct region_element *left; /* the original region */ 544 struct region_element *right; /* what *left was combined with */ 545 } combine; 546 } elementdata; 547 }; 548 549 struct GpRegion{ 550 DWORD num_children; 551 region_element node; 552 }; 553 554 struct memory_buffer 555 { 556 const BYTE *buffer; 557 INT size, pos; 558 }; 559 560 static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size) 561 { 562 mbuf->buffer = buffer; 563 mbuf->size = size; 564 mbuf->pos = 0; 565 } 566 567 static inline const void *buffer_read(struct memory_buffer *mbuf, INT size) 568 { 569 if (mbuf->size - mbuf->pos >= size) 570 { 571 const void *data = mbuf->buffer + mbuf->pos; 572 mbuf->pos += size; 573 return data; 574 } 575 return NULL; 576 } 577 578 typedef GpStatus (*gdip_format_string_callback)(HDC hdc, 579 GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, 580 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, 581 INT lineno, const RectF *bounds, INT *underlined_indexes, 582 INT underlined_index_count, void *user_data); 583 584 GpStatus gdip_format_string(HDC hdc, 585 GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, 586 GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip, 587 gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN; 588 589 void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN; 590 591 static inline BOOL image_lock(GpImage *image, BOOL *unlock) 592 { 593 LONG tid = GetCurrentThreadId(), owner_tid; 594 owner_tid = InterlockedCompareExchange(&image->busy, tid, 0); 595 *unlock = !owner_tid; 596 return !owner_tid || owner_tid==tid; 597 } 598 599 static inline void image_unlock(GpImage *image, BOOL unlock) 600 { 601 if (unlock) image->busy = 0; 602 } 603 604 #endif 605