/* * Copyright (C) 2007 Google (Evan Stade) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef __WINE_GP_PRIVATE_H_ #define __WINE_GP_PRIVATE_H_ #include <math.h> #include <stdarg.h> #include "windef.h" #include "wingdi.h" #include "winbase.h" #include "winuser.h" #include "objbase.h" #include "ocidl.h" #include "wincodecsdk.h" #include "wine/heap.h" #include "wine/list.h" #include "gdiplus.h" #define GP_DEFAULT_PENSTYLE (PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_MITER) #define MAX_ARC_PTS (13) #define MAX_DASHLEN (16) /* this is a limitation of gdi */ #define INCH_HIMETRIC (2540) #define VERSION_MAGIC 0xdbc01001 #define VERSION_MAGIC2 0xdbc01002 #define VALID_MAGIC(x) (((x) & 0xfffff000) == 0xdbc01000) #define TENSION_CONST (0.3) #define GIF_DISPOSE_UNSPECIFIED 0 #define GIF_DISPOSE_DO_NOT_DISPOSE 1 #define GIF_DISPOSE_RESTORE_TO_BKGND 2 #define GIF_DISPOSE_RESTORE_TO_PREV 3 COLORREF ARGB2COLORREF(ARGB color) DECLSPEC_HIDDEN; HBITMAP ARGB2BMP(ARGB color) DECLSPEC_HIDDEN; extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2, REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN; extern REAL gdiplus_atan2(REAL dy, REAL dx) DECLSPEC_HIDDEN; extern GpStatus hresult_to_status(HRESULT res) DECLSPEC_HIDDEN; extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN; extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN; extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN; #define WineCoordinateSpaceGdiDevice ((GpCoordinateSpace)4) extern GpStatus gdi_transform_acquire(GpGraphics *graphics); extern GpStatus gdi_transform_release(GpGraphics *graphics); extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN; extern GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count) DECLSPEC_HIDDEN; extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN; extern GpStatus encode_image_png(GpImage *image, IStream* stream, GDIPCONST EncoderParameters* params) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN; extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush, GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetClipRegion(GpMetafile* metafile, GpRegion* region, CombineMode mode) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN; extern GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_RestoreGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN; extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *image, GDIPCONST GpPointF *points, INT count, REAL srcx, REAL srcy, REAL srcwidth, REAL srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes* imageAttributes, DrawImageAbort callback, VOID *callbackData) DECLSPEC_HIDDEN; extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN; extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN; extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN; extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN; extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj, REAL tension, REAL *x, REAL *y) DECLSPEC_HIDDEN; extern void free_installed_fonts(void) DECLSPEC_HIDDEN; extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN; extern DWORD write_region_data(const GpRegion *region, void *data) DECLSPEC_HIDDEN; extern DWORD write_path_data(GpPath *path, void *data) DECLSPEC_HIDDEN; extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN; typedef struct region_element region_element; extern void delete_element(region_element *element) DECLSPEC_HIDDEN; extern GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN; static inline INT gdip_round(REAL x) { return (INT) floorf(x + 0.5); } static inline INT ceilr(REAL x) { return (INT) ceilf(x); } static inline REAL deg2rad(REAL degrees) { return M_PI * degrees / 180.0; } static inline ARGB color_over(ARGB bg, ARGB fg) { BYTE b, g, r, a; BYTE bg_alpha, fg_alpha; fg_alpha = (fg>>24)&0xff; if (fg_alpha == 0xff) return fg; if (fg_alpha == 0) return bg; bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff; if (bg_alpha == 0) return fg; a = bg_alpha + fg_alpha; b = ((bg&0xff)*bg_alpha + (fg&0xff)*fg_alpha)/a; g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*fg_alpha)/a; r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*fg_alpha)/a; return (a<<24)|(r<<16)|(g<<8)|b; } /* fg is premult, bg and return value are not */ static inline ARGB color_over_fgpremult(ARGB bg, ARGB fg) { BYTE b, g, r, a; BYTE bg_alpha, fg_alpha; fg_alpha = (fg>>24)&0xff; if (fg_alpha == 0) return bg; bg_alpha = (((bg>>24)&0xff) * (0xff-fg_alpha)) / 0xff; a = bg_alpha + fg_alpha; b = ((bg&0xff)*bg_alpha + (fg&0xff)*0xff)/a; g = (((bg>>8)&0xff)*bg_alpha + ((fg>>8)&0xff)*0xff)/a; r = (((bg>>16)&0xff)*bg_alpha + ((fg>>16)&0xff)*0xff)/a; return (a<<24)|(r<<16)|(g<<8)|b; } extern const char *debugstr_rectf(const RectF* rc) DECLSPEC_HIDDEN; extern const char *debugstr_pointf(const PointF* pt) DECLSPEC_HIDDEN; extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) DECLSPEC_HIDDEN; extern GpStatus convert_pixels(INT width, INT height, INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN; extern PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data, UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt) DECLSPEC_HIDDEN; struct GpMatrix{ REAL matrix[6]; }; struct GpPen{ UINT style; GpUnit unit; REAL width; GpLineCap endcap; GpLineCap startcap; GpDashCap dashcap; GpCustomLineCap *customstart; GpCustomLineCap *customend; GpLineJoin join; REAL miterlimit; GpDashStyle dash; REAL *dashes; INT numdashes; REAL offset; /* dash offset */ GpBrush *brush; GpPenAlignment align; GpMatrix transform; }; struct GpGraphics{ HDC hdc; HWND hwnd; BOOL owndc; BOOL alpha_hdc; GpImage *image; ImageType image_type; SmoothingMode smoothing; CompositingQuality compqual; InterpolationMode interpolation; PixelOffsetMode pixeloffset; CompositingMode compmode; TextRenderingHint texthint; GpUnit unit; /* page unit */ REAL scale; /* page scale */ REAL xres, yres; GpMatrix worldtrans; /* world transform */ BOOL busy; /* hdc handle obtained by GdipGetDC */ GpRegion *clip; /* in device coords */ UINT textcontrast; /* not used yet. get/set only */ struct list containers; GraphicsContainer contid; /* last-issued container ID */ INT origin_x, origin_y; INT gdi_transform_acquire_count, gdi_transform_save; GpMatrix gdi_transform; HRGN gdi_clip; /* For giving the caller an HDC when we technically can't: */ HBITMAP temp_hbitmap; int temp_hbitmap_width; int temp_hbitmap_height; BYTE *temp_bits; HDC temp_hdc; }; struct GpBrush{ GpBrushType bt; }; struct GpHatch{ GpBrush brush; GpHatchStyle hatchstyle; ARGB forecol; ARGB backcol; }; struct GpSolidFill{ GpBrush brush; ARGB color; }; struct GpPathGradient{ GpBrush brush; GpPath* path; ARGB centercolor; GpWrapMode wrap; BOOL gamma; GpPointF center; GpPointF focus; REAL* blendfac; /* blend factors */ REAL* blendpos; /* blend positions */ INT blendcount; ARGB *surroundcolors; INT surroundcolorcount; ARGB* pblendcolor; /* preset blend colors */ REAL* pblendpos; /* preset blend positions */ INT pblendcount; GpMatrix transform; }; struct GpLineGradient{ GpBrush brush; ARGB startcolor; ARGB endcolor; RectF rect; GpWrapMode wrap; BOOL gamma; REAL* blendfac; /* blend factors */ REAL* blendpos; /* blend positions */ INT blendcount; ARGB* pblendcolor; /* preset blend colors */ REAL* pblendpos; /* preset blend positions */ INT pblendcount; GpMatrix transform; }; struct GpTexture{ GpBrush brush; GpMatrix transform; GpImage *image; GpImageAttributes *imageattributes; BYTE *bitmap_bits; /* image bits converted to ARGB and run through imageattributes */ }; struct GpPath{ GpFillMode fill; GpPathData pathdata; BOOL newfigure; /* whether the next drawing action starts a new figure */ INT datalen; /* size of the arrays in pathdata */ }; struct GpPathIterator{ GpPathData pathdata; INT subpath_pos; /* for NextSubpath methods */ INT marker_pos; /* for NextMarker methods */ INT pathtype_pos; /* for NextPathType methods */ }; struct GpCustomLineCap{ CustomLineCapType type; GpPathData pathdata; BOOL fill; /* TRUE for fill, FALSE for stroke */ GpLineCap cap; /* as far as I can tell, this value is ignored */ REAL inset; /* how much to adjust the end of the line */ GpLineJoin join; REAL scale; }; struct GpAdjustableArrowCap{ GpCustomLineCap cap; REAL middle_inset; REAL height; REAL width; }; struct GpImage{ IWICBitmapDecoder *decoder; ImageType type; GUID format; UINT flags; UINT frame_count, current_frame; ColorPalette *palette; REAL xres, yres; LONG busy; }; #define EmfPlusObjectTableSize 64 typedef enum EmfPlusObjectType { ObjectTypeInvalid, ObjectTypeBrush, ObjectTypePen, ObjectTypePath, ObjectTypeRegion, ObjectTypeImage, ObjectTypeFont, ObjectTypeStringFormat, ObjectTypeImageAttributes, ObjectTypeCustomLineCap, ObjectTypeMax = ObjectTypeCustomLineCap, } EmfPlusObjectType; /* Deserialized EmfPlusObject record. */ struct emfplus_object { EmfPlusObjectType type; union { GpBrush *brush; GpPen *pen; GpPath *path; GpRegion *region; GpImage *image; GpFont *font; GpImageAttributes *image_attributes; void *object; } u; }; struct GpMetafile{ GpImage image; GpRectF bounds; GpUnit unit; MetafileType metafile_type; HENHMETAFILE hemf; int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */ /* recording */ HDC record_dc; GpGraphics *record_graphics; BYTE *comment_data; DWORD comment_data_size; DWORD comment_data_length; IStream *record_stream; BOOL auto_frame; /* If true, determine the frame automatically */ GpPointF auto_frame_min, auto_frame_max; DWORD next_object_id; /* playback */ GpGraphics *playback_graphics; HDC playback_dc; GpPointF playback_points[3]; GpRectF src_rect; HANDLETABLE *handle_table; int handle_count; XFORM gdiworldtransform; GpMatrix *world_transform; GpUnit page_unit; REAL page_scale; GpRegion *base_clip; /* clip region in device space for all metafile output */ GpRegion *clip; /* clip region within the metafile */ struct list containers; struct emfplus_object objtable[EmfPlusObjectTableSize]; }; struct GpBitmap{ GpImage image; INT width; INT height; PixelFormat format; ImageLockMode lockmode; BYTE *bitmapbits; /* pointer to the buffer we passed in BitmapLockBits */ HBITMAP hbitmap; HDC hdc; BYTE *bits; /* actual image bits if this is a DIB */ INT stride; /* stride of bits if this is a DIB */ BYTE *own_bits; /* image bits that need to be freed with this object */ INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */ IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */ UINT prop_count; PropertyItem *prop_item; /* cached image properties */ }; struct GpCachedBitmap{ GpImage *image; }; struct color_key{ BOOL enabled; ARGB low; ARGB high; }; struct color_matrix{ BOOL enabled; ColorMatrixFlags flags; ColorMatrix colormatrix; ColorMatrix graymatrix; }; struct color_remap_table{ BOOL enabled; INT mapsize; ColorMap *colormap; }; enum imageattr_noop{ IMAGEATTR_NOOP_UNDEFINED, IMAGEATTR_NOOP_SET, IMAGEATTR_NOOP_CLEAR, }; struct GpImageAttributes{ WrapMode wrap; ARGB outside_color; BOOL clamp; struct color_key colorkeys[ColorAdjustTypeCount]; struct color_matrix colormatrices[ColorAdjustTypeCount]; struct color_remap_table colorremaptables[ColorAdjustTypeCount]; BOOL gamma_enabled[ColorAdjustTypeCount]; REAL gamma[ColorAdjustTypeCount]; enum imageattr_noop noop[ColorAdjustTypeCount]; }; struct GpFont{ GpFontFamily *family; OUTLINETEXTMETRICW otm; REAL emSize; /* in font units */ Unit unit; }; extern const struct GpStringFormat default_drawstring_format DECLSPEC_HIDDEN; struct GpStringFormat{ INT attr; LANGID lang; LANGID digitlang; StringAlignment align; StringTrimming trimming; HotkeyPrefix hkprefix; StringAlignment line_align; StringDigitSubstitute digitsub; INT tabcount; REAL firsttab; REAL *tabs; CharacterRange *character_ranges; INT range_count; BOOL generic_typographic; }; extern void init_generic_string_formats(void) DECLSPEC_HIDDEN; extern void free_generic_string_formats(void) DECLSPEC_HIDDEN; struct GpFontCollection{ GpFontFamily **FontFamilies; INT count; INT allocated; }; struct GpFontFamily{ WCHAR FamilyName[LF_FACESIZE]; UINT16 em_height, ascent, descent, line_spacing; /* in font units */ int dpi; }; /* internal use */ typedef enum RegionType { RegionDataRect = 0x10000000, RegionDataPath = 0x10000001, RegionDataEmptyRect = 0x10000002, RegionDataInfiniteRect = 0x10000003, } RegionType; struct region_element { DWORD type; /* Rectangle, Path, SpecialRectangle, or CombineMode */ union { GpRectF rect; GpPath *path; struct { struct region_element *left; /* the original region */ struct region_element *right; /* what *left was combined with */ } combine; } elementdata; }; struct GpRegion{ DWORD num_children; region_element node; }; struct memory_buffer { const BYTE *buffer; INT size, pos; }; static inline void init_memory_buffer(struct memory_buffer *mbuf, const BYTE *buffer, INT size) { mbuf->buffer = buffer; mbuf->size = size; mbuf->pos = 0; } static inline const void *buffer_read(struct memory_buffer *mbuf, INT size) { if (mbuf->size - mbuf->pos >= size) { const void *data = mbuf->buffer + mbuf->pos; mbuf->pos += size; return data; } return NULL; } typedef GpStatus (*gdip_format_string_callback)(HDC hdc, GDIPCONST WCHAR *string, INT index, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, INT lineno, const RectF *bounds, INT *underlined_indexes, INT underlined_index_count, void *user_data); GpStatus gdip_format_string(HDC hdc, GDIPCONST WCHAR *string, INT length, GDIPCONST GpFont *font, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, int ignore_empty_clip, gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN; void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN; static inline BOOL image_lock(GpImage *image, BOOL *unlock) { LONG tid = GetCurrentThreadId(), owner_tid; owner_tid = InterlockedCompareExchange(&image->busy, tid, 0); *unlock = !owner_tid; return !owner_tid || owner_tid==tid; } static inline void image_unlock(GpImage *image, BOOL unlock) { if (unlock) image->busy = 0; } #endif