/** @file uwmf.c @brief Functions for manipulating WMF files and structures. [U_WMR*]_set all take data and return a pointer to memory holding the constructed record. If something goes wrong a NULL pointer is returned. [U_WMR*]_get takes a pointer to memory and returns the length of that record as well as the values from it (in the provided fields, passed by reference.) If something goes wrong, a size of 0 is returned. The _set material comes first, then all of the _get material. Compile with "U_VALGRIND" defined defined to enable code which lets valgrind check each record for uninitialized data. Compile with "SOL8" defined for Solaris 8 or 9 (Sparc). */ /* File: uwmf.c Version: 0.0.17 Date: 28-MAR-2015 Author: David Mathog, Biology Division, Caltech email: mathog@caltech.edu Copyright: 2014 David Mathog and California Institute of Technology (Caltech) */ #ifdef __cplusplus extern "C" { #endif #include #include #include /* for offsetof() */ #include #include #include #include #include #include // for INT_MAX, INT_MIN #include // for U_ROUND() #if 0 #include //Not actually used, looking for collisions #include //Not actually used, looking for collisions #include //Not actually used, looking for collisions #endif #include "uwmf.h" #include "uwmf_endian.h" #include "uemf_safe.h" /** \brief Look up the full numeric type of a WMR record by type. \return Full numeric value for this type of WMR record, Returns 0xFFFFFFFF if out of range. \param idx WMR record type. */ uint32_t U_wmr_values(int idx){ int ret; int U_WMR_VALUES[256]={ 0x0000, //!< U_WMR_EOF 0x0201, //!< U_WMR_SETBKCOLOR 0x0102, //!< U_WMR_SETBKMODE 0x0103, //!< U_WMR_SETMAPMODE 0x0104, //!< U_WMR_SETROP2 0x0105, //!< U_WMR_SETRELABS 0x0106, //!< U_WMR_SETPOLYFILLMODE 0x0107, //!< U_WMR_SETSTRETCHBLTMODE 0x0108, //!< U_WMR_SETTEXTCHAREXTRA 0x0209, //!< U_WMR_SETTEXTCOLOR 0x020A, //!< U_WMR_SETTEXTJUSTIFICATION 0x020B, //!< U_WMR_SETWINDOWORG 0x020C, //!< U_WMR_SETWINDOWEXT 0x020D, //!< U_WMR_SETVIEWPORTORG 0x020E, //!< U_WMR_SETVIEWPORTEXT 0x020F, //!< U_WMR_OFFSETWINDOWORG 0x0410, //!< U_WMR_SCALEWINDOWEXT 0x0211, //!< U_WMR_OFFSETVIEWPORTORG 0x0412, //!< U_WMR_SCALEVIEWPORTEXT 0x0213, //!< U_WMR_LINETO 0x0214, //!< U_WMR_MOVETO 0x0415, //!< U_WMR_EXCLUDECLIPRECT 0x0416, //!< U_WMR_INTERSECTCLIPRECT 0x0817, //!< U_WMR_ARC 0x0418, //!< U_WMR_ELLIPSE 0x0419, //!< U_WMR_FLOODFILL 0x081A, //!< U_WMR_PIE 0x041B, //!< U_WMR_RECTANGLE 0x061C, //!< U_WMR_ROUNDRECT 0x061D, //!< U_WMR_PATBLT 0x001E, //!< U_WMR_SAVEDC 0x041F, //!< U_WMR_SETPIXEL 0x0220, //!< U_WMR_OFFSETCLIPRGN 0x0521, //!< U_WMR_TEXTOUT 0x0922, //!< U_WMR_BITBLT 0x0B23, //!< U_WMR_STRETCHBLT 0x0324, //!< U_WMR_POLYGON 0x0325, //!< U_WMR_POLYLINE 0x0626, //!< U_WMR_ESCAPE 0x0127, //!< U_WMR_RESTOREDC 0x0228, //!< U_WMR_FILLREGION 0x0429, //!< U_WMR_FRAMEREGION 0x012A, //!< U_WMR_INVERTREGION 0x012B, //!< U_WMR_PAINTREGION 0x012C, //!< U_WMR_SELECTCLIPREGION 0x012D, //!< U_WMR_SELECTOBJECT 0x012E, //!< U_WMR_SETTEXTALIGN 0x062F, //!< U_WMR_DRAWTEXT 0x0830, //!< U_WMR_CHORD 0x0231, //!< U_WMR_SETMAPPERFLAGS 0x0A32, //!< U_WMR_EXTTEXTOUT 0x0D33, //!< U_WMR_SETDIBTODEV 0x0234, //!< U_WMR_SELECTPALETTE 0x0035, //!< U_WMR_REALIZEPALETTE 0x0436, //!< U_WMR_ANIMATEPALETTE 0x0037, //!< U_WMR_SETPALENTRIES 0x0538, //!< U_WMR_POLYPOLYGON 0x0139, //!< U_WMR_RESIZEPALETTE 0x003A, //!< U_WMR_3A 0x003B, //!< U_WMR_3B 0x003C, //!< U_WMR_3C 0x003D, //!< U_WMR_3D 0x003E, //!< U_WMR_3E 0x003F, //!< U_WMR_3F 0x0940, //!< U_WMR_DIBBITBLT 0x0B41, //!< U_WMR_DIBSTRETCHBLT 0x0142, //!< U_WMR_DIBCREATEPATTERNBRUSH 0x0F43, //!< U_WMR_STRETCHDIB 0x0044, //!< U_WMR_44 0x0045, //!< U_WMR_45 0x0046, //!< U_WMR_46 0x0047, //!< U_WMR_47 0x0548, //!< U_WMR_EXTFLOODFILL 0x0049, //!< U_WMR_49 0x004A, //!< U_WMR_4A 0x004B, //!< U_WMR_4B 0x014C, //!< U_WMR_4C 0x014D, //!< U_WMR_4D 0x004E, //!< U_WMR_4E 0x004F, //!< U_WMR_4F 0x0050, //!< U_WMR_50 0x0051, //!< U_WMR_51 0x0052, //!< U_WMR_52 0x0053, //!< U_WMR_53 0x0054, //!< U_WMR_54 0x0055, //!< U_WMR_55 0x0056, //!< U_WMR_56 0x0057, //!< U_WMR_57 0x0058, //!< U_WMR_58 0x0059, //!< U_WMR_59 0x005A, //!< U_WMR_5A 0x005B, //!< U_WMR_5B 0x005C, //!< U_WMR_5C 0x005D, //!< U_WMR_5D 0x005E, //!< U_WMR_5E 0x005F, //!< U_WMR_5F 0x0060, //!< U_WMR_60 0x0061, //!< U_WMR_61 0x0062, //!< U_WMR_62 0x0063, //!< U_WMR_63 0x0064, //!< U_WMR_64 0x0065, //!< U_WMR_65 0x0066, //!< U_WMR_66 0x0067, //!< U_WMR_67 0x0068, //!< U_WMR_68 0x0069, //!< U_WMR_69 0x006A, //!< U_WMR_6A 0x006B, //!< U_WMR_6B 0x006C, //!< U_WMR_6C 0x006D, //!< U_WMR_6D 0x006E, //!< U_WMR_6E 0x006F, //!< U_WMR_6F 0x0070, //!< U_WMR_70 0x0071, //!< U_WMR_71 0x0072, //!< U_WMR_72 0x0073, //!< U_WMR_73 0x0074, //!< U_WMR_74 0x0075, //!< U_WMR_75 0x0076, //!< U_WMR_76 0x0077, //!< U_WMR_77 0x0078, //!< U_WMR_78 0x0079, //!< U_WMR_79 0x007A, //!< U_WMR_7A 0x007B, //!< U_WMR_7B 0x007C, //!< U_WMR_7C 0x007D, //!< U_WMR_7D 0x007E, //!< U_WMR_7E 0x007F, //!< U_WMR_7F 0x0080, //!< U_WMR_80 0x0081, //!< U_WMR_81 0x0082, //!< U_WMR_82 0x0083, //!< U_WMR_83 0x0084, //!< U_WMR_84 0x0085, //!< U_WMR_85 0x0086, //!< U_WMR_86 0x0087, //!< U_WMR_87 0x0088, //!< U_WMR_88 0x0089, //!< U_WMR_89 0x008A, //!< U_WMR_8A 0x008B, //!< U_WMR_8B 0x008C, //!< U_WMR_8C 0x008D, //!< U_WMR_8D 0x008E, //!< U_WMR_8E 0x008F, //!< U_WMR_8F 0x0090, //!< U_WMR_90 0x0091, //!< U_WMR_91 0x0092, //!< U_WMR_92 0x0093, //!< U_WMR_93 0x0094, //!< U_WMR_94 0x0095, //!< U_WMR_95 0x0096, //!< U_WMR_96 0x0097, //!< U_WMR_97 0x0098, //!< U_WMR_98 0x0099, //!< U_WMR_99 0x009A, //!< U_WMR_9A 0x009B, //!< U_WMR_9B 0x009C, //!< U_WMR_9C 0x009D, //!< U_WMR_9D 0x009E, //!< U_WMR_9E 0x009F, //!< U_WMR_9F 0x00A0, //!< U_WMR_A0 0x00A1, //!< U_WMR_A1 0x00A2, //!< U_WMR_A2 0x00A3, //!< U_WMR_A3 0x00A4, //!< U_WMR_A4 0x00A5, //!< U_WMR_A5 0x00A6, //!< U_WMR_A6 0x00A7, //!< U_WMR_A7 0x00A8, //!< U_WMR_A8 0x00A9, //!< U_WMR_A9 0x00AA, //!< U_WMR_AA 0x00AB, //!< U_WMR_AB 0x00AC, //!< U_WMR_AC 0x00AD, //!< U_WMR_AD 0x00AE, //!< U_WMR_AE 0x00AF, //!< U_WMR_AF 0x00B0, //!< U_WMR_B0 0x00B1, //!< U_WMR_B1 0x00B2, //!< U_WMR_B2 0x00B3, //!< U_WMR_B3 0x00B4, //!< U_WMR_B4 0x00B5, //!< U_WMR_B5 0x00B6, //!< U_WMR_B6 0x00B7, //!< U_WMR_B7 0x00B8, //!< U_WMR_B8 0x00B9, //!< U_WMR_B9 0x00BA, //!< U_WMR_BA 0x00BB, //!< U_WMR_BB 0x00BC, //!< U_WMR_BC 0x00BD, //!< U_WMR_BD 0x00BE, //!< U_WMR_BE 0x00BF, //!< U_WMR_BF 0x00C0, //!< U_WMR_C0 0x00C1, //!< U_WMR_C1 0x00C2, //!< U_WMR_C2 0x00C3, //!< U_WMR_C3 0x00C4, //!< U_WMR_C4 0x00C5, //!< U_WMR_C5 0x00C6, //!< U_WMR_C6 0x00C7, //!< U_WMR_C7 0x00C8, //!< U_WMR_C8 0x00C9, //!< U_WMR_C9 0x00CA, //!< U_WMR_CA 0x00CB, //!< U_WMR_CB 0x00CC, //!< U_WMR_CC 0x00CD, //!< U_WMR_CD 0x00CE, //!< U_WMR_CE 0x00CF, //!< U_WMR_CF 0x00D0, //!< U_WMR_D0 0x00D1, //!< U_WMR_D1 0x00D2, //!< U_WMR_D2 0x00D3, //!< U_WMR_D3 0x00D4, //!< U_WMR_D4 0x00D5, //!< U_WMR_D5 0x00D6, //!< U_WMR_D6 0x00D7, //!< U_WMR_D7 0x00D8, //!< U_WMR_D8 0x00D9, //!< U_WMR_D9 0x00DA, //!< U_WMR_DA 0x00DB, //!< U_WMR_DB 0x00DC, //!< U_WMR_DC 0x00DD, //!< U_WMR_DD 0x00DE, //!< U_WMR_DE 0x00DF, //!< U_WMR_DF 0x00E0, //!< U_WMR_E0 0x00E1, //!< U_WMR_E1 0x00E2, //!< U_WMR_E2 0x00E3, //!< U_WMR_E3 0x00E4, //!< U_WMR_E4 0x00E5, //!< U_WMR_E5 0x00E6, //!< U_WMR_E6 0x00E7, //!< U_WMR_E7 0x00E8, //!< U_WMR_E8 0x00E9, //!< U_WMR_E9 0x00EA, //!< U_WMR_EA 0x00EB, //!< U_WMR_EB 0x00EC, //!< U_WMR_EC 0x00ED, //!< U_WMR_ED 0x00EE, //!< U_WMR_EE 0x00EF, //!< U_WMR_EF 0x01F0, //!< U_WMR_DELETEOBJECT 0x00F1, //!< U_WMR_F1 0x00F2, //!< U_WMR_F2 0x00F3, //!< U_WMR_F3 0x00F4, //!< U_WMR_F4 0x00F5, //!< U_WMR_F5 0x00F6, //!< U_WMR_F6 0x00F7, //!< U_WMR_CREATEPALETTE 0x00F8, //!< U_WMR_CREATEBRUSH 0x01F9, //!< U_WMR_CREATEPATTERNBRUSH 0x02FA, //!< U_WMR_CREATEPENINDIRECT 0x02FB, //!< U_WMR_CREATEFONTINDIRECT 0x02FC, //!< U_WMR_CREATEBRUSHINDIRECT 0x02FD, //!< U_WMR_CREATEBITMAPINDIRECT 0x06FE, //!< U_WMR_CREATEBITMAP 0x06FF //!< U_WMR_CREATEREGION }; if(idx U_WMR_MAX){ ret = 0xFFFFFFFF; } else { ret = U_WMR_VALUES[idx]; } return(ret); } /** \brief Look up the name of the WMR record by type. Returns U_WMR_INVALID if out of range. \return name of the WMR record, "U_WMR_INVALID" if out of range. \param idx WMR record type. */ const char *U_wmr_names(int idx){ int ret; static const char *U_WMR_NAMES[257]={ "U_WMR_EOF", "U_WMR_SETBKCOLOR", "U_WMR_SETBKMODE", "U_WMR_SETMAPMODE", "U_WMR_SETROP2", "U_WMR_SETRELABS", "U_WMR_SETPOLYFILLMODE", "U_WMR_SETSTRETCHBLTMODE", "U_WMR_SETTEXTCHAREXTRA", "U_WMR_SETTEXTCOLOR", "U_WMR_SETTEXTJUSTIFICATION", "U_WMR_SETWINDOWORG", "U_WMR_SETWINDOWEXT", "U_WMR_SETVIEWPORTORG", "U_WMR_SETVIEWPORTEXT", "U_WMR_OFFSETWINDOWORG", "U_WMR_SCALEWINDOWEXT", "U_WMR_OFFSETVIEWPORTORG", "U_WMR_SCALEVIEWPORTEXT", "U_WMR_LINETO", "U_WMR_MOVETO", "U_WMR_EXCLUDECLIPRECT", "U_WMR_INTERSECTCLIPRECT", "U_WMR_ARC", "U_WMR_ELLIPSE", "U_WMR_FLOODFILL", "U_WMR_PIE", "U_WMR_RECTANGLE", "U_WMR_ROUNDRECT", "U_WMR_PATBLT", "U_WMR_SAVEDC", "U_WMR_SETPIXEL", "U_WMR_OFFSETCLIPRGN", "U_WMR_TEXTOUT", "U_WMR_BITBLT", "U_WMR_STRETCHBLT", "U_WMR_POLYGON", "U_WMR_POLYLINE", "U_WMR_ESCAPE", "U_WMR_RESTOREDC", "U_WMR_FILLREGION", "U_WMR_FRAMEREGION", "U_WMR_INVERTREGION", "U_WMR_PAINTREGION", "U_WMR_SELECTCLIPREGION", "U_WMR_SELECTOBJECT", "U_WMR_SETTEXTALIGN", "U_WMR_DRAWTEXT", "U_WMR_CHORD", "U_WMR_SETMAPPERFLAGS", "U_WMR_EXTTEXTOUT", "U_WMR_SETDIBTODEV", "U_WMR_SELECTPALETTE", "U_WMR_REALIZEPALETTE", "U_WMR_ANIMATEPALETTE", "U_WMR_SETPALENTRIES", "U_WMR_POLYPOLYGON", "U_WMR_RESIZEPALETTE", "U_WMR_3A", "U_WMR_3B", "U_WMR_3C", "U_WMR_3D", "U_WMR_3E", "U_WMR_3F", "U_WMR_DIBBITBLT", "U_WMR_DIBSTRETCHBLT", "U_WMR_DIBCREATEPATTERNBRUSH", "U_WMR_STRETCHDIB", "U_WMR_44", "U_WMR_45", "U_WMR_46", "U_WMR_47", "U_WMR_EXTFLOODFILL", "U_WMR_49", "U_WMR_4A", "U_WMR_4B", "U_WMR_4C", "U_WMR_4D", "U_WMR_4E", "U_WMR_4F", "U_WMR_50", "U_WMR_51", "U_WMR_52", "U_WMR_53", "U_WMR_54", "U_WMR_55", "U_WMR_56", "U_WMR_57", "U_WMR_58", "U_WMR_59", "U_WMR_5A", "U_WMR_5B", "U_WMR_5C", "U_WMR_5D", "U_WMR_5E", "U_WMR_5F", "U_WMR_60", "U_WMR_61", "U_WMR_62", "U_WMR_63", "U_WMR_64", "U_WMR_65", "U_WMR_66", "U_WMR_67", "U_WMR_68", "U_WMR_69", "U_WMR_6A", "U_WMR_6B", "U_WMR_6C", "U_WMR_6D", "U_WMR_6E", "U_WMR_6F", "U_WMR_70", "U_WMR_71", "U_WMR_72", "U_WMR_73", "U_WMR_74", "U_WMR_75", "U_WMR_76", "U_WMR_77", "U_WMR_78", "U_WMR_79", "U_WMR_7A", "U_WMR_7B", "U_WMR_7C", "U_WMR_7D", "U_WMR_7E", "U_WMR_7F", "U_WMR_80", "U_WMR_81", "U_WMR_82", "U_WMR_83", "U_WMR_84", "U_WMR_85", "U_WMR_86", "U_WMR_87", "U_WMR_88", "U_WMR_89", "U_WMR_8A", "U_WMR_8B", "U_WMR_8C", "U_WMR_8D", "U_WMR_8E", "U_WMR_8F", "U_WMR_90", "U_WMR_91", "U_WMR_92", "U_WMR_93", "U_WMR_94", "U_WMR_95", "U_WMR_96", "U_WMR_97", "U_WMR_98", "U_WMR_99", "U_WMR_9A", "U_WMR_9B", "U_WMR_9C", "U_WMR_9D", "U_WMR_9E", "U_WMR_9F", "U_WMR_A0", "U_WMR_A1", "U_WMR_A2", "U_WMR_A3", "U_WMR_A4", "U_WMR_A5", "U_WMR_A6", "U_WMR_A7", "U_WMR_A8", "U_WMR_A9", "U_WMR_AA", "U_WMR_AB", "U_WMR_AC", "U_WMR_AD", "U_WMR_AE", "U_WMR_AF", "U_WMR_B0", "U_WMR_B1", "U_WMR_B2", "U_WMR_B3", "U_WMR_B4", "U_WMR_B5", "U_WMR_B6", "U_WMR_B7", "U_WMR_B8", "U_WMR_B9", "U_WMR_BA", "U_WMR_BB", "U_WMR_BC", "U_WMR_BD", "U_WMR_BE", "U_WMR_BF", "U_WMR_C0", "U_WMR_C1", "U_WMR_C2", "U_WMR_C3", "U_WMR_C4", "U_WMR_C5", "U_WMR_C6", "U_WMR_C7", "U_WMR_C8", "U_WMR_C9", "U_WMR_CA", "U_WMR_CB", "U_WMR_CC", "U_WMR_CD", "U_WMR_CE", "U_WMR_CF", "U_WMR_D0", "U_WMR_D1", "U_WMR_D2", "U_WMR_D3", "U_WMR_D4", "U_WMR_D5", "U_WMR_D6", "U_WMR_D7", "U_WMR_D8", "U_WMR_D9", "U_WMR_DA", "U_WMR_DB", "U_WMR_DC", "U_WMR_DD", "U_WMR_DE", "U_WMR_DF", "U_WMR_E0", "U_WMR_E1", "U_WMR_E2", "U_WMR_E3", "U_WMR_E4", "U_WMR_E5", "U_WMR_E6", "U_WMR_E7", "U_WMR_E8", "U_WMR_E9", "U_WMR_EA", "U_WMR_EB", "U_WMR_EC", "U_WMR_ED", "U_WMR_EE", "U_WMR_EF", "U_WMR_DELETEOBJECT", "U_WMR_F1", "U_WMR_F2", "U_WMR_F3", "U_WMR_F4", "U_WMR_F5", "U_WMR_F6", "U_WMR_CREATEPALETTE", "U_WMR_CREATEBRUSH", "U_WMR_CREATEPATTERNBRUSH", "U_WMR_CREATEPENINDIRECT", "U_WMR_CREATEFONTINDIRECT", "U_WMR_CREATEBRUSHINDIRECT", "U_WMR_CREATEBITMAPINDIRECT", "U_WMR_CREATEBITMAP", "U_WMR_CREATEREGION" }; if(idx U_WMR_MAX){ ret = 256; } else { ret = idx; } return(U_WMR_NAMES[ret]); } /** \brief Text description of Escape record type. \return name of the WMR record, "UNKNOWN_ESCAPE" if out of range. \param idx Escape record type. */ const char *U_wmr_escnames(int idx){ const char *name; if(idx>=1 && idx <= 0x0023){ switch(idx){ case 0x0001: name = "NEWFRAME"; break; case 0x0002: name = "ABORTDOC"; break; case 0x0003: name = "NEXTBAND"; break; case 0x0004: name = "SETCOLORTABLE"; break; case 0x0005: name = "GETCOLORTABLE"; break; case 0x0006: name = "FLUSHOUT"; break; case 0x0007: name = "DRAFTMODE"; break; case 0x0008: name = "QUERYESCSUPPORT"; break; case 0x0009: name = "SETABORTPROC"; break; case 0x000A: name = "STARTDOC"; break; case 0x000B: name = "ENDDOC"; break; case 0x000C: name = "GETPHYSPAGESIZE"; break; case 0x000D: name = "GETPRINTINGOFFSET"; break; case 0x000E: name = "GETSCALINGFACTOR"; break; case 0x000F: name = "META_ESCAPE_ENHANCED_METAFILE"; break; case 0x0010: name = "SETPENWIDTH"; break; case 0x0011: name = "SETCOPYCOUNT"; break; case 0x0012: name = "SETPAPERSOURCE"; break; case 0x0013: name = "PASSTHROUGH"; break; case 0x0014: name = "GETTECHNOLOGY"; break; case 0x0015: name = "SETLINECAP"; break; case 0x0016: name = "SETLINEJOIN"; break; case 0x0017: name = "SETMITERLIMIT"; break; case 0x0018: name = "BANDINFO"; break; case 0x0019: name = "DRAWPATTERNRECT"; break; case 0x001A: name = "GETVECTORPENSIZE"; break; case 0x001B: name = "GETVECTORBRUSHSIZE"; break; case 0x001C: name = "ENABLEDUPLEX"; break; case 0x001D: name = "GETSETPAPERBINS"; break; case 0x001E: name = "GETSETPRINTORIENT"; break; case 0x001F: name = "ENUMPAPERBINS"; break; case 0x0020: name = "SETDIBSCALING"; break; case 0x0021: name = "EPSPRINTING"; break; case 0x0022: name = "ENUMPAPERMETRICS"; break; case 0x0023: name = "GETSETPAPERMETRICS"; break; } } else if(idx == 0x0025){ name = "POSTSCRIPT_DATA"; } else if(idx == 0x0026){ name = "POSTSCRIPT_IGNORE"; } else if(idx == 0x002A){ name = "GETDEVICEUNITS"; } else if(idx == 0x0100){ name = "GETEXTENDEDTEXTMETRICS"; } else if(idx == 0x0102){ name = "GETPAIRKERNTABLE"; } else if(idx == 0x0200){ name = "EXTTEXTOUT"; } else if(idx == 0x0201){ name = "GETFACENAME"; } else if(idx == 0x0202){ name = "DOWNLOADFACE"; } else if(idx == 0x0801){ name = "METAFILE_DRIVER"; } else if(idx == 0x0C01){ name = "QUERYDIBSUPPORT"; } else if(idx == 0x1000){ name = "BEGIN_PATH"; } else if(idx == 0x1001){ name = "CLIP_TO_PATH"; } else if(idx == 0x1002){ name = "END_PATH"; } else if(idx == 0x100E){ name = "OPEN_CHANNEL"; } else if(idx == 0x100F){ name = "DOWNLOADHEADER"; } else if(idx == 0x1010){ name = "CLOSE_CHANNEL"; } else if(idx == 0x1013){ name = "POSTSCRIPT_PASSTHROUGH"; } else if(idx == 0x1014){ name = "ENCAPSULATED_POSTSCRIPT";} else if(idx == 0x1015){ name = "POSTSCRIPT_IDENTIFY"; } else if(idx == 0x1016){ name = "POSTSCRIPT_INJECTION"; } else if(idx == 0x1017){ name = "CHECKJPEGFORMAT"; } else if(idx == 0x1018){ name = "CHECKPNGFORMAT"; } else if(idx == 0x1019){ name = "GET_PS_FEATURESETTING"; } else if(idx == 0x101A){ name = "MXDC_ESCAPE"; } else if(idx == 0x11D8){ name = "SPCLPASSTHROUGH2"; } else { name = "UNKNOWN_ESCAPE"; } return(name); } //! \cond /* one prototype from uwmf_endian. Put it here because end user should never need to see it, so not in uemf.h or uwmf_endian.h */ void U_swap2(void *ul, unsigned int count); /** \brief Check that the bitmap in the specified packed DIB is compatible with the record size \return 1 on success, 0 on failure \param record EMF record that contains a DIB pixel array \param blimit one byte past the end of the record. This method can only test DIBs that hold Microsoft's various bitmap types. PNG or JPG is just a bag of bytes, and there is no possible way to derive from the known width and height how big it should be. This should not be called directly by end user code. */ int packed_DIB_safe( const char *record, const char *blimit ){ int dibparams = U_BI_UNKNOWN; // type of image not yet determined const char *px = NULL; // DIB pixels const U_RGBQUAD *ct = NULL; // DIB color table int bs; int usedbytes; if(!bitmapinfo_safe(record, blimit))return(0); // this DIB has issues with colors fitting into the record uint32_t numCt; // these values will be set in get_DIB_params int32_t width, height, colortype, invert; // these values will be set in get_DIB_params // next call returns pointers and values, but allocates no memory dibparams = wget_DIB_params(record, &px, (const U_RGBQUAD **) &ct, &numCt, &width, &height, &colortype, &invert); // sanity checking if(numCt && colortype >= U_BCBM_COLOR16)return(0); //color tables not used above 16 bit pixels if(!numCt && colortype < U_BCBM_COLOR16)return(0); //color tables mandatory for < 16 bit if(dibparams ==U_BI_RGB){ // this is the only DIB type where we can calculate how big it should be when stored in the WMF file bs = colortype/8; if(bs<1){ usedbytes = (width*colortype + 7)/8; // width of line in fully and partially occupied bytes } else { usedbytes = width*bs; } if(IS_MEM_UNSAFE(px, usedbytes, blimit))return(0); } return(1); } //! \endcond /** \brief Derive from bounding box and start and end arc, for WMF arc, chord, or pie records, the center, start, and end points, and the bounding rectangle. \return 0 on success, other values on errors. \param rclBox16 Bounding box of Arc \param ArcStart16 Coordinates for Start of Arc \param ArcEnd16 Coordinates for End of Arc \param f1 1 if rotation angle >= 180, else 0 \param f2 Rotation direction, 1 if counter clockwise, else 0 \param center Center coordinates \param start Start coordinates (point on the ellipse defined by rect) \param end End coordinates (point on the ellipse defined by rect) \param size W,H of the x,y axes of the bounding rectangle. */ int wmr_arc_points( U_RECT16 rclBox16, U_POINT16 ArcStart16, U_POINT16 ArcEnd16, int *f1, int f2, U_PAIRF *center, U_PAIRF *start, U_PAIRF *end, U_PAIRF *size ){ U_RECTL rclBox; U_POINTL ArcStart,ArcEnd; rclBox.left = rclBox16.left; rclBox.top = rclBox16.top; rclBox.right = rclBox16.right; rclBox.bottom = rclBox16.bottom; ArcStart.x = ArcStart16.x; ArcStart.y = ArcStart16.y; ArcEnd.x = ArcEnd16.x; ArcEnd.y = ArcEnd16.y; return emr_arc_points_common(&rclBox, &ArcStart, &ArcEnd, f1, f2, center, start, end, size); } /** \brief A U_RECT16 may have its values swapped, L<->R and T<->B, this extracts the leftmost as left, and so forth. \param rc U_RECT156 binary contents of an WMF file \param left the leftmost of rc.left and rc.right \param top the topmost of rc.top and rc.bottom \param right the rightmost of rc.left and rc.right \param bottom the bottommost of rc.top and rc.bottom */ void U_sanerect16(U_RECT16 rc, double *left, double *top, double *right, double *bottom){ if(rc.left < rc.right) { *left = rc.left; *right = rc.right; } else { *left = rc.right; *right = rc.left; } if(rc.top < rc.bottom){ *top = rc.top; *bottom = rc.bottom; } else{ *top = rc.bottom; *bottom = rc.top; } } /* ********************************************************************************************** These definitions are for code pieces that are used many times in the following implementation. These definitions are not needed in end user code, so they are here rather than in uwmf.h. *********************************************************************************************** */ /** \brief Get record size in bytes from U_WMR* record, which may not be aligned \return number of bytes in record. */ uint32_t U_wmr_size(const U_METARECORD *record){ uint32_t Size16; memcpy(&Size16,record, 4); return(2*Size16); } //! \cond should never be called directly #define SET_CB_FROM_PXBMI(A,B,C,D,E,F) /* A=Px, B=Bmi, C=cbImage, D=cbImage4, E=cbBmi, F=cbPx */ \ if(A){\ if(!B)return(NULL); /* size is derived from U_BITMAPINFO, but NOT from its size field, go figure*/ \ C = F;\ D = UP4(C); /* pixel array might not be a multiples of 4 bytes*/ \ E = U_SIZE_BITMAPINFOHEADER + 4 * get_real_color_count((char *)&(B->bmiHeader)); /* bmiheader + colortable*/ \ }\ else { C = 0; D = 0; E=0; } //! \endcond /** \brief Create and return a U_FONT structure. \return pointer to the created U_FONT structure. \param Height Height in Logical units \param Width Average Width in Logical units \param Escapement Angle in 0.1 degrees betweem escapement vector and X axis \param Orientation Angle in 0.1 degrees between baseline and X axis \param Weight LF_Weight Enumeration \param Italic LF_Italic Enumeration \param Underline LF_Underline Enumeration \param StrikeOut LF_StrikeOut Enumeration \param CharSet LF_CharSet Enumeration \param OutPrecision LF_OutPrecision Enumeration \param ClipPrecision LF_ClipPrecision Enumeration \param Quality LF_Quality Enumeration \param PitchAndFamily LF_PitchAndFamily Enumeration \param FaceName Name of font. ANSI Latin1, null terminated. */ U_FONT *U_FONT_set( int16_t Height, //!< Height in Logical units int16_t Width, //!< Average Width in Logical units int16_t Escapement, //!< Angle in 0.1 degrees betweem escapement vector and X axis int16_t Orientation, //!< Angle in 0.1 degrees between baseline and X axis int16_t Weight, //!< LF_Weight Enumeration uint8_t Italic, //!< LF_Italic Enumeration uint8_t Underline, //!< LF_Underline Enumeration uint8_t StrikeOut, //!< LF_StrikeOut Enumeration uint8_t CharSet, //!< LF_CharSet Enumeration uint8_t OutPrecision, //!< LF_OutPrecision Enumeration uint8_t ClipPrecision, //!< LF_ClipPrecision Enumeration uint8_t Quality, //!< LF_Quality Enumeration uint8_t PitchAndFamily, //!< LF_PitchAndFamily Enumeration char *FaceName //!< Name of font. ANSI Latin1, null terminated. ){ U_FONT *font; int slen = 1 + strlen(FaceName); /* include terminator */ if(slen & 1)slen++; /* storage length even */ font = (U_FONT *) calloc(1,slen + U_SIZE_FONT_CORE); /* use calloc to auto fill in terminating '\0'*/ if(font){ font->Height = Height; font->Width = Width; font->Escapement = Escapement; font->Orientation = Orientation; font->Weight = Weight; font->Italic = Italic; font->Underline = Underline; font->StrikeOut = StrikeOut; font->CharSet = CharSet; font->OutPrecision = OutPrecision; font->ClipPrecision = ClipPrecision; font->Quality = Quality; font->PitchAndFamily = PitchAndFamily; strcpy((char *)&font->FaceName, FaceName); } return(font); } /** \brief Create and return a U_PLTENTRY structure. \return the created U_PLTENTRY structure. \param Color Color for the U_PLTENTRY */ U_PLTNTRY U_PLTNTRY_set(U_COLORREF Color){ U_PLTNTRY pe; pe.Value = Color.Reserved; pe.Blue = Color.Blue; pe.Green = Color.Green; pe.Red = Color.Red; return(pe); } /** \brief Create and return a U_PALETTE structure. \return pointer to the created U_PALETTE structure. \param Start Either 0x0300 or an offset into the Palette table \param NumEntries Number of U_LOGPLTNTRY objects \param PalEntries Pointer to array of PaletteEntry Objects */ U_PALETTE *U_PLTENTRY_set( uint16_t Start, //!< Either 0x0300 or an offset into the Palette table uint16_t NumEntries, //!< Number of U_LOGPLTNTRY objects U_PLTNTRY *PalEntries //!< Pointer to array of PaletteEntry Objects ){ U_PALETTE *Palette = NULL; if(NumEntries){ Palette = malloc(4 + 4*NumEntries); if(Palette){ Palette->Start = Start; Palette->NumEntries = NumEntries; memcpy(&Palette->PalEntries, PalEntries, NumEntries*4); } } return(Palette); } /** \brief Create and return a U_PEN structure. \return the created U_PEN structure. \param Style PenStyle Enumeration \param Width Width of Pen \param Color Pen Color. */ U_PEN U_PEN_set( uint16_t Style, //!< PenStyle Enumeration uint16_t Width, //!< Width of Pen U_COLORREF Color //!< Pen Color. ){ U_PEN p; p.Style = Style; p.Widthw[0] = Width; p.Widthw[1] = 0; /* ignored */ p.Color.Red = Color.Red; p.Color.Green = Color.Green; p.Color.Blue = Color.Blue; p.Color.Reserved = Color.Reserved; return(p); } /** \brief Create and return a U_RECT16 structure from Upper Left and Lower Right corner points. \param ul upper left corner of rectangle \param lr lower right corner of rectangle */ U_RECT16 U_RECT16_set( U_POINT16 ul, U_POINT16 lr ){ U_RECT16 rect; rect.left = ul.x; rect.top = ul.y; rect.right = lr.x; rect.bottom = lr.y; return(rect); } /** \brief Create and return a U_BITMAP16 structure \return pointer to the U_BITMAP16 structure, or NULL on failure \param Type bitmap Type (not described at all in the WMF PDF) \param Width bitmap width in pixels. \param Height bitmap height in scan lines. \param LineN each array line in Bits is a multiple of this (4 for a DIB) \param BitsPixel number of adjacent color bits on each plane (R bits + G bits + B bits ????) \param Bits bitmap pixel data. Bytes contained = (((Width * BitsPixel + 15) >> 4) << 1) * Height */ U_BITMAP16 *U_BITMAP16_set( const int16_t Type, const int16_t Width, const int16_t Height, const int16_t LineN, const uint8_t BitsPixel, const char *Bits ){ U_BITMAP16 *bm16; uint32_t irecsize; int cbBits,iHeight; int usedbytes; int16_t WidthBytes; // total bytes per scan line (used and padding). usedbytes = (Width * BitsPixel + 7)/8; // width of line in fully and partially occupied bytes WidthBytes = (LineN * ((usedbytes + (LineN - 1) ) / LineN)); // Account for padding required by line alignment in the pixel array iHeight = (Height < 0 ? -Height : Height); /* DIB can use a negative height, but it does not look like a Bitmap16 object can */ cbBits = WidthBytes * iHeight; if(!Bits || cbBits<=0)return(NULL); irecsize = U_SIZE_BITMAP16 + cbBits; bm16 = (U_BITMAP16 *) malloc(irecsize); if(bm16){ bm16->Type = Type; bm16->Width = Width; bm16->Height = iHeight; bm16->WidthBytes = WidthBytes; bm16->Planes = 1; bm16->BitsPixel = BitsPixel; memcpy((char *)bm16 + U_SIZE_BITMAP16,Bits,cbBits); } return(bm16); } /** \brief Create and return a U_SCAN structure \return U_SCAN structure \param count Number of entries in the ScanLines array \param top Y coordinate of the top scanline \param bottom Y coordinate of the bottom scanline \param ScanLines Array of 16 bit left/right pairs, array has 2*count entries */ U_SCAN *U_SCAN_set( uint16_t count, //!< Number of entries in the ScanLines array uint16_t top, //!< Y coordinate of the top scanline uint16_t bottom, //!< Y coordinate of the bottom scanline uint16_t *ScanLines //!< Array of 16 bit left/right pairs, array has 2*count entries ){ U_SCAN *scan=NULL; int size = 6 + count*4; scan = malloc(size); if(scan){ scan->count = count; scan->top = top; scan->bottom = bottom; memcpy(&scan->ScanLines,ScanLines,4*count); } return(scan); } /** \brief Create and return a U_REGION structure \return pointer to created U_REGION structure or NULL on error \param Size aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?) \param sCount number of scan objects in region (docs say scanlines, but then no way to add sizes) \param sMax largest number of points in any scan \param sRect bounding rectangle \param aScans series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer. */ U_REGION *U_REGION_set( int16_t Size, //!< aScans in bytes + regions size in bytes (size of this header plus all U_SCAN objects?) int16_t sCount, //!< number of scan objects in region (docs say scanlines, but then no way to add sizes) int16_t sMax, //!< largest number of points in any scan U_RECT16 sRect, //!< bounding rectangle uint16_t *aScans //!< series of U_SCAN objects to append. This is also an array of uint16_t, but should be handled as a bunch of U_SCAN objects tightly packed into the buffer. ){ U_REGION *region=NULL; char *psc; int scansize,i,off; psc = (char *)aScans; for(scansize=i=0; icount); scansize += off; psc += off; } region = malloc(U_SIZE_REGION + scansize); if(region){ region->ignore1 = 0; region->Type = 0x0006; region->ignore2 = 0; region->Size = Size; region->sCount = sCount; region->sMax = sMax; region->sRect = sRect; memcpy(®ion->aScans,aScans,scansize); } return(region); } /** \brief Create and return a U_WLOGBRUSH structure. \return the created U_WLOGBRUSH structure. \param Style BrushStyle Enumeration \param Color Brush Color value \param Hatch HatchStyle Enumeration */ U_WLOGBRUSH U_WLOGBRUSH_set( uint16_t Style, //!< BrushStyle Enumeration U_COLORREF Color, //!< Brush Color value uint16_t Hatch //!< HatchStyle Enumeration ){ U_WLOGBRUSH lb; lb.Style = Style; lb.Color.Red = Color.Red; lb.Color.Green = Color.Green; lb.Color.Blue = Color.Blue; lb.Color.Reserved = Color.Reserved; lb.Hatch = Hatch; return(lb); } /** \brief Create and return a U_PAIRF structure. \return pointer to the created U_PAIRF structure. \param x x value \param y y value */ U_PAIRF *U_PAIRF_set( float x, //!< x value float y //!< y value ){ U_PAIRF *pf=malloc(U_SIZE_PAIRF); if(pf){ pf->x = x; pf->y = y; } return(pf); } /* ********************************************************************************************** These functions are used for Image conversions and other utility operations. Character type conversions are in uwmf_utf.c *********************************************************************************************** */ /** \brief Calculate the int16_t checksum of the buffer for the number of positions specified. This is XOR of all values. \return checksum \param buf array of uint16_t values \param count number of members in buf */ int16_t U_16_checksum(int16_t *buf, int count){ int16_t result=0; for(;count;count--){ result ^= *buf++; } return(result); } /** \brief Dump a WMFHANDLES structure. Not for use in production code. \param string Text to output before dumping eht structure \param handle Handle \param wht WMFHANDLES structure to dump */ void dumpwht( char *string, unsigned int *handle, WMFHANDLES *wht ){ uint32_t i; printf("%s\n",string); printf("lo: %d hi: %d peak: %d\n", wht->lolimit, wht->hilimit, wht->peak); if(handle){ printf("handle: %d \n",*handle); } for(i=0;i<=5;i++){ printf("table[%d]: %d\n",i,wht->table[i]); } } /** \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_set(), based on character height and weight. Take abs. value of character height, get width by multiplying by 0.6, and correct weight approximately, with formula (measured on screen for one text line of Arial). Caller is responsible for free() on the returned pointer. \return pointer to dx array \param height character height (absolute value will be used) \param weight LF_Weight Enumeration (character weight) \param members Number of entries to put into dx */ int16_t *dx16_set( int32_t height, uint32_t weight, uint32_t members ){ uint32_t i, width; int16_t *dx; dx = (int16_t *) malloc(members * sizeof(int16_t)); if(dx){ if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL; width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904)); for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); } } return(dx); } /** \brief Look up the properties (a bit map) of a type of WMR record. Bits that may be set are defined in "Draw Properties" in uemf.h, they are U_DRAW_NOTEMPTY, etc.. \return bitmap of WMR record properties, or U_WMR_INVALID on error or release of all memory. \param type WMR record type. If U_WMR_INVALID release memory. (There is no U_WMR_INVALID WMR record type) */ uint32_t U_wmr_properties(uint32_t type){ static uint32_t *table=NULL; uint32_t result = U_WMR_INVALID; // initialized to indicate an error (on a lookup) or nothing (on a memory release) if(type == U_WMR_INVALID){ if(table)free(table); table=NULL; } else if(type<=U_WMR_MAX){ // type is uint so always >=0, no need to test U_WMR_MIN, which is 0. if(!table){ table = (uint32_t *) malloc(sizeof(uint32_t)*(1 + U_WMR_MAX)); if(!table)return(result); // 0x200 0x100 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01 // properties (U_DRAW_*) TEXT ALTERS ONLYTO VISIBLE // NOFILL OBJECT PATH FORCE CLOSED NOTEMPTY // Record Type table[0x00] = 0x0A0; // U_WMREOF 0 0 1 0 1 0 0 0 0 0 Force out any pending draw table[0x01] = 0x020; // U_WMRSETBKCOLOR 0 0 0 0 1 0 0 0 0 0 table[0x02] = 0x020; // U_WMRSETBKMODE 0 0 0 0 1 0 0 0 0 0 table[0x03] = 0x0A0; // U_WMRSETMAPMODE 0 0 1 0 1 0 0 0 0 0 table[0x04] = 0x0A0; // U_WMRSETROP2 0 0 1 0 1 0 0 0 0 0 table[0x05] = 0x000; // U_WMRSETRELABS 0 0 0 0 0 0 0 0 0 0 No idea what this is supposed to do table[0x06] = 0x0A0; // U_WMRSETPOLYFILLMODE 0 0 1 0 1 0 0 0 0 0 table[0x07] = 0x0A0; // U_WMRSETSTRETCHBLTMODE 0 0 1 0 1 0 0 0 0 0 table[0x08] = 0x000; // U_WMRSETTEXTCHAREXTRA 0 0 0 0 0 0 0 0 0 0 table[0x09] = 0x020; // U_WMRSETTEXTCOLOR 0 0 0 0 1 0 0 0 0 0 table[0x0A] = 0x020; // U_WMRSETTEXTJUSTIFICATION 0 0 0 0 1 0 0 0 0 0 table[0x0B] = 0x0A0; // U_WMRSETWINDOWORG 0 0 1 0 1 0 0 0 0 0 table[0x0C] = 0x0A0; // U_WMRSETWINDOWEXT 0 0 1 0 1 0 0 0 0 0 table[0x0D] = 0x0A0; // U_WMRSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0 table[0x0E] = 0x0A0; // U_WMRSETVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0 table[0x0F] = 0x000; // U_WMROFFSETWINDOWORG 0 0 0 0 0 0 0 0 0 0 table[0x10] = 0x000; // U_WMRSCALEWINDOWEXT 0 0 0 0 0 0 0 0 0 0 table[0x11] = 0x0A0; // U_WMROFFSETVIEWPORTORG 0 0 1 0 1 0 0 0 0 0 table[0x12] = 0x0A0; // U_WMRSCALEVIEWPORTEXT 0 0 1 0 1 0 0 0 0 0 table[0x13] = 0x28B; // U_WMRLINETO 1 0 1 0 0 0 1 0 1 1 table[0x14] = 0x289; // U_WMRMOVETO 1 0 1 0 0 0 1 0 0 1 table[0x15] = 0x0A0; // U_WMREXCLUDECLIPRECT 0 0 1 0 1 0 0 0 0 0 table[0x16] = 0x0A0; // U_WMRINTERSECTCLIPRECT 0 0 1 0 1 0 0 0 0 0 table[0x17] = 0x283; // U_WMRARC 1 0 1 0 0 0 0 0 1 1 table[0x18] = 0x087; // U_WMRELLIPSE 0 0 1 0 0 0 0 1 1 1 table[0x19] = 0x082; // U_WMRFLOODFILL 0 0 1 0 0 0 0 0 1 0 table[0x1A] = 0x087; // U_WMRPIE 0 0 1 0 0 0 0 1 1 1 table[0x1B] = 0x087; // U_WMRRECTANGLE 0 0 1 0 0 0 0 1 1 1 table[0x1C] = 0x087; // U_WMRROUNDRECT 0 0 1 0 0 0 0 1 1 1 table[0x1D] = 0x000; // U_WMRPATBLT 0 0 1 0 0 0 0 1 1 1 table[0x1E] = 0x0A0; // U_WMRSAVEDC 0 0 1 0 1 0 0 0 0 0 table[0x1F] = 0x082; // U_WMRSETPIXEL 0 0 1 0 0 0 0 0 1 0 table[0x20] = 0x0A0; // U_WMROFFSETCLIPRGN 0 0 1 0 1 0 0 0 0 0 table[0x21] = 0x002; // U_WMRTEXTOUT 0 0 0 0 0 0 0 0 1 0 table[0x22] = 0x082; // U_WMRBITBLT 0 0 1 0 0 0 0 0 1 0 table[0x23] = 0x082; // U_WMRSTRETCHBLT 0 0 1 0 0 0 0 0 1 0 table[0x24] = 0x083; // U_WMRPOLYGON 0 0 1 0 0 0 0 0 1 1 table[0x25] = 0x283; // U_WMRPOLYLINE 1 0 1 0 0 0 0 0 1 1 table[0x26] = 0x0A0; // U_WMRESCAPE 0 0 1 0 1 0 0 0 0 0 table[0x27] = 0x0A0; // U_WMRRESTOREDC 0 0 1 0 1 0 0 0 0 0 table[0x28] = 0x082; // U_WMRFILLREGION 0 0 1 0 0 0 0 0 1 0 table[0x29] = 0x082; // U_WMRFRAMEREGION 0 0 1 0 0 0 0 0 1 0 table[0x2A] = 0x082; // U_WMRINVERTREGION 0 0 1 0 0 0 0 0 1 0 table[0x2B] = 0x082; // U_WMRPAINTREGION 0 0 1 0 0 0 0 0 1 0 table[0x2C] = 0x0A0; // U_WMRSELECTCLIPREGION 0 0 1 0 1 0 0 0 0 0 table[0x2D] = 0x020; // U_WMRSELECTOBJECT 0 0 0 0 1 0 0 0 0 0 table[0x2E] = 0x020; // U_WMRSETTEXTALIGN 0 0 0 0 1 0 0 0 0 0 table[0x2F] = 0x002; // U_WMRDRAWTEXT 0 0 0 0 0 0 0 0 1 0 no idea what this is supposed to do table[0x30] = 0x087; // U_WMRCHORD 0 0 1 0 0 0 0 1 1 1 table[0x31] = 0x0A0; // U_WMRSETMAPPERFLAGS 0 0 1 0 1 0 0 0 0 0 table[0x32] = 0x002; // U_WMREXTTEXTOUT 0 0 0 0 0 0 0 0 1 0 table[0x33] = 0x000; // U_WMRSETDIBTODEV 0 0 0 0 0 0 0 0 0 0 table[0x34] = 0x0A0; // U_WMRSELECTPALETTE 0 0 1 0 1 0 0 0 0 0 table[0x35] = 0x0A0; // U_WMRREALIZEPALETTE 0 0 1 0 1 0 0 0 0 0 table[0x36] = 0x0A0; // U_WMRANIMATEPALETTE 0 0 1 0 1 0 0 0 0 0 table[0x37] = 0x0A0; // U_WMRSETPALENTRIES 0 0 1 0 1 0 0 0 0 0 table[0x38] = 0x087; // U_WMRPOLYPOLYGON 0 0 1 0 0 0 0 1 1 1 table[0x39] = 0x0A0; // U_WMRRESIZEPALETTE 0 0 1 0 1 0 0 0 0 0 table[0x3A] = 0x000; // U_WMR3A 0 0 0 0 0 0 0 0 0 0 table[0x3B] = 0x000; // U_WMR3B 0 0 0 0 0 0 0 0 0 0 table[0x3C] = 0x000; // U_WMR3C 0 0 0 0 0 0 0 0 0 0 table[0x3D] = 0x000; // U_WMR3D 0 0 0 0 0 0 0 0 0 0 table[0x3E] = 0x000; // U_WMR3E 0 0 0 0 0 0 0 0 0 0 table[0x3F] = 0x000; // U_WMR3F 0 0 0 0 0 0 0 0 0 0 table[0x40] = 0x0A0; // U_WMRDIBBITBLT 0 0 1 0 1 0 0 0 0 0 table[0x41] = 0x0A0; // U_WMRDIBSTRETCHBLT 0 0 1 0 1 0 0 0 0 0 table[0x42] = 0x080; // U_WMRDIBCREATEPATTERNBRUSH 0 0 1 0 0 0 0 0 0 0 Not selected yet, so no change in drawing conditions table[0x43] = 0x0A0; // U_WMRSTRETCHDIB 0 0 1 0 1 0 0 0 0 0 table[0x44] = 0x000; // U_WMR44 0 0 0 0 0 0 0 0 0 0 table[0x45] = 0x000; // U_WMR45 0 0 0 0 0 0 0 0 0 0 table[0x46] = 0x000; // U_WMR46 0 0 0 0 0 0 0 0 0 0 table[0x47] = 0x000; // U_WMR47 0 0 0 0 0 0 0 0 0 0 table[0x48] = 0x082; // U_WMREXTFLOODFILL 0 0 1 0 0 0 0 0 1 0 table[0x49] = 0x000; // U_WMR49 0 0 0 0 0 0 0 0 0 0 table[0x4A] = 0x000; // U_WMR4A 0 0 0 0 0 0 0 0 0 0 table[0x4B] = 0x000; // U_WMR4B 0 0 0 0 0 0 0 0 0 0 table[0x4C] = 0x000; // U_WMR4C 0 0 0 0 0 0 0 0 0 0 table[0x4D] = 0x000; // U_WMR4D 0 0 0 0 0 0 0 0 0 0 table[0x4E] = 0x000; // U_WMR4E 0 0 0 0 0 0 0 0 0 0 table[0x4F] = 0x000; // U_WMR4F 0 0 0 0 0 0 0 0 0 0 table[0x50] = 0x000; // U_WMR50 0 0 0 0 0 0 0 0 0 0 table[0x51] = 0x000; // U_WMR51 0 0 0 0 0 0 0 0 0 0 table[0x52] = 0x000; // U_WMR52 0 0 0 0 0 0 0 0 0 0 table[0x53] = 0x000; // U_WMR53 0 0 0 0 0 0 0 0 0 0 table[0x54] = 0x000; // U_WMR54 0 0 0 0 0 0 0 0 0 0 table[0x55] = 0x000; // U_WMR55 0 0 0 0 0 0 0 0 0 0 table[0x56] = 0x000; // U_WMR56 0 0 0 0 0 0 0 0 0 0 table[0x57] = 0x000; // U_WMR57 0 0 0 0 0 0 0 0 0 0 table[0x58] = 0x000; // U_WMR58 0 0 0 0 0 0 0 0 0 0 table[0x59] = 0x000; // U_WMR59 0 0 0 0 0 0 0 0 0 0 table[0x5A] = 0x000; // U_WMR5A 0 0 0 0 0 0 0 0 0 0 table[0x5B] = 0x000; // U_WMR5B 0 0 0 0 0 0 0 0 0 0 table[0x5C] = 0x000; // U_WMR5C 0 0 0 0 0 0 0 0 0 0 table[0x5D] = 0x000; // U_WMR5D 0 0 0 0 0 0 0 0 0 0 table[0x5E] = 0x000; // U_WMR5E 0 0 0 0 0 0 0 0 0 0 table[0x5F] = 0x000; // U_WMR5F 0 0 0 0 0 0 0 0 0 0 table[0x60] = 0x000; // U_WMR60 0 0 0 0 0 0 0 0 0 0 table[0x61] = 0x000; // U_WMR61 0 0 0 0 0 0 0 0 0 0 table[0x62] = 0x000; // U_WMR62 0 0 0 0 0 0 0 0 0 0 table[0x63] = 0x000; // U_WMR63 0 0 0 0 0 0 0 0 0 0 table[0x64] = 0x000; // U_WMR64 0 0 0 0 0 0 0 0 0 0 table[0x65] = 0x000; // U_WMR65 0 0 0 0 0 0 0 0 0 0 table[0x66] = 0x000; // U_WMR66 0 0 0 0 0 0 0 0 0 0 table[0x67] = 0x000; // U_WMR67 0 0 0 0 0 0 0 0 0 0 table[0x68] = 0x000; // U_WMR68 0 0 0 0 0 0 0 0 0 0 table[0x69] = 0x000; // U_WMR69 0 0 0 0 0 0 0 0 0 0 table[0x6A] = 0x000; // U_WMR6A 0 0 0 0 0 0 0 0 0 0 table[0x6B] = 0x000; // U_WMR6B 0 0 0 0 0 0 0 0 0 0 table[0x6C] = 0x000; // U_WMR6C 0 0 0 0 0 0 0 0 0 0 table[0x6D] = 0x000; // U_WMR6D 0 0 0 0 0 0 0 0 0 0 table[0x6E] = 0x000; // U_WMR6E 0 0 0 0 0 0 0 0 0 0 table[0x6F] = 0x000; // U_WMR6F 0 0 0 0 0 0 0 0 0 0 table[0x70] = 0x000; // U_WMR70 0 0 0 0 0 0 0 0 0 0 table[0x71] = 0x000; // U_WMR71 0 0 0 0 0 0 0 0 0 0 table[0x72] = 0x000; // U_WMR72 0 0 0 0 0 0 0 0 0 0 table[0x73] = 0x000; // U_WMR73 0 0 0 0 0 0 0 0 0 0 table[0x74] = 0x000; // U_WMR74 0 0 0 0 0 0 0 0 0 0 table[0x75] = 0x000; // U_WMR75 0 0 0 0 0 0 0 0 0 0 table[0x76] = 0x000; // U_WMR76 0 0 0 0 0 0 0 0 0 0 table[0x77] = 0x000; // U_WMR77 0 0 0 0 0 0 0 0 0 0 table[0x78] = 0x000; // U_WMR78 0 0 0 0 0 0 0 0 0 0 table[0x79] = 0x000; // U_WMR79 0 0 0 0 0 0 0 0 0 0 table[0x7A] = 0x000; // U_WMR7A 0 0 0 0 0 0 0 0 0 0 table[0x7B] = 0x000; // U_WMR7B 0 0 0 0 0 0 0 0 0 0 table[0x7C] = 0x000; // U_WMR7C 0 0 0 0 0 0 0 0 0 0 table[0x7D] = 0x000; // U_WMR7D 0 0 0 0 0 0 0 0 0 0 table[0x7E] = 0x000; // U_WMR7E 0 0 0 0 0 0 0 0 0 0 table[0x7F] = 0x000; // U_WMR7F 0 0 0 0 0 0 0 0 0 0 table[0x80] = 0x000; // U_WMR80 0 0 0 0 0 0 0 0 0 0 table[0x81] = 0x000; // U_WMR81 0 0 0 0 0 0 0 0 0 0 table[0x82] = 0x000; // U_WMR82 0 0 0 0 0 0 0 0 0 0 table[0x83] = 0x000; // U_WMR83 0 0 0 0 0 0 0 0 0 0 table[0x84] = 0x000; // U_WMR84 0 0 0 0 0 0 0 0 0 0 table[0x85] = 0x000; // U_WMR85 0 0 0 0 0 0 0 0 0 0 table[0x86] = 0x000; // U_WMR86 0 0 0 0 0 0 0 0 0 0 table[0x87] = 0x000; // U_WMR87 0 0 0 0 0 0 0 0 0 0 table[0x88] = 0x000; // U_WMR88 0 0 0 0 0 0 0 0 0 0 table[0x89] = 0x000; // U_WMR89 0 0 0 0 0 0 0 0 0 0 table[0x8A] = 0x000; // U_WMR8A 0 0 0 0 0 0 0 0 0 0 table[0x8B] = 0x000; // U_WMR8B 0 0 0 0 0 0 0 0 0 0 table[0x8C] = 0x000; // U_WMR8C 0 0 0 0 0 0 0 0 0 0 table[0x8D] = 0x000; // U_WMR8D 0 0 0 0 0 0 0 0 0 0 table[0x8E] = 0x000; // U_WMR8E 0 0 0 0 0 0 0 0 0 0 table[0x8F] = 0x000; // U_WMR8F 0 0 0 0 0 0 0 0 0 0 table[0x90] = 0x000; // U_WMR90 0 0 0 0 0 0 0 0 0 0 table[0x91] = 0x000; // U_WMR91 0 0 0 0 0 0 0 0 0 0 table[0x92] = 0x000; // U_WMR92 0 0 0 0 0 0 0 0 0 0 table[0x93] = 0x000; // U_WMR93 0 0 0 0 0 0 0 0 0 0 table[0x94] = 0x000; // U_WMR94 0 0 0 0 0 0 0 0 0 0 table[0x95] = 0x000; // U_WMR95 0 0 0 0 0 0 0 0 0 0 table[0x96] = 0x000; // U_WMR96 0 0 0 0 0 0 0 0 0 0 table[0x97] = 0x000; // U_WMR97 0 0 0 0 0 0 0 0 0 0 table[0x98] = 0x000; // U_WMR98 0 0 0 0 0 0 0 0 0 0 table[0x99] = 0x000; // U_WMR99 0 0 0 0 0 0 0 0 0 0 table[0x9A] = 0x000; // U_WMR9A 0 0 0 0 0 0 0 0 0 0 table[0x9B] = 0x000; // U_WMR9B 0 0 0 0 0 0 0 0 0 0 table[0x9C] = 0x000; // U_WMR9C 0 0 0 0 0 0 0 0 0 0 table[0x9D] = 0x000; // U_WMR9D 0 0 0 0 0 0 0 0 0 0 table[0x9E] = 0x000; // U_WMR9E 0 0 0 0 0 0 0 0 0 0 table[0x9F] = 0x000; // U_WMR9F 0 0 0 0 0 0 0 0 0 0 table[0xA0] = 0x000; // U_WMRA0 0 0 0 0 0 0 0 0 0 0 table[0xA1] = 0x000; // U_WMRA1 0 0 0 0 0 0 0 0 0 0 table[0xA2] = 0x000; // U_WMRA2 0 0 0 0 0 0 0 0 0 0 table[0xA3] = 0x000; // U_WMRA3 0 0 0 0 0 0 0 0 0 0 table[0xA4] = 0x000; // U_WMRA4 0 0 0 0 0 0 0 0 0 0 table[0xA5] = 0x000; // U_WMRA5 0 0 0 0 0 0 0 0 0 0 table[0xA6] = 0x000; // U_WMRA6 0 0 0 0 0 0 0 0 0 0 table[0xA7] = 0x000; // U_WMRA7 0 0 0 0 0 0 0 0 0 0 table[0xA8] = 0x000; // U_WMRA8 0 0 0 0 0 0 0 0 0 0 table[0xA9] = 0x000; // U_WMRA9 0 0 0 0 0 0 0 0 0 0 table[0xAA] = 0x000; // U_WMRAA 0 0 0 0 0 0 0 0 0 0 table[0xAB] = 0x000; // U_WMRAB 0 0 0 0 0 0 0 0 0 0 table[0xAC] = 0x000; // U_WMRAC 0 0 0 0 0 0 0 0 0 0 table[0xAD] = 0x000; // U_WMRAD 0 0 0 0 0 0 0 0 0 0 table[0xAE] = 0x000; // U_WMRAE 0 0 0 0 0 0 0 0 0 0 table[0xAF] = 0x000; // U_WMRAF 0 0 0 0 0 0 0 0 0 0 table[0xB0] = 0x000; // U_WMRB0 0 0 0 0 0 0 0 0 0 0 table[0xB1] = 0x000; // U_WMRB1 0 0 0 0 0 0 0 0 0 0 table[0xB2] = 0x000; // U_WMRB2 0 0 0 0 0 0 0 0 0 0 table[0xB3] = 0x000; // U_WMRB3 0 0 0 0 0 0 0 0 0 0 table[0xB4] = 0x000; // U_WMRB4 0 0 0 0 0 0 0 0 0 0 table[0xB5] = 0x000; // U_WMRB5 0 0 0 0 0 0 0 0 0 0 table[0xB6] = 0x000; // U_WMRB6 0 0 0 0 0 0 0 0 0 0 table[0xB7] = 0x000; // U_WMRB7 0 0 0 0 0 0 0 0 0 0 table[0xB8] = 0x000; // U_WMRB8 0 0 0 0 0 0 0 0 0 0 table[0xB9] = 0x000; // U_WMRB9 0 0 0 0 0 0 0 0 0 0 table[0xBA] = 0x000; // U_WMRBA 0 0 0 0 0 0 0 0 0 0 table[0xBB] = 0x000; // U_WMRBB 0 0 0 0 0 0 0 0 0 0 table[0xBC] = 0x000; // U_WMRBC 0 0 0 0 0 0 0 0 0 0 table[0xBD] = 0x000; // U_WMRBD 0 0 0 0 0 0 0 0 0 0 table[0xBE] = 0x000; // U_WMRBE 0 0 0 0 0 0 0 0 0 0 table[0xBF] = 0x000; // U_WMRBF 0 0 0 0 0 0 0 0 0 0 table[0xC0] = 0x000; // U_WMRC0 0 0 0 0 0 0 0 0 0 0 table[0xC1] = 0x000; // U_WMRC1 0 0 0 0 0 0 0 0 0 0 table[0xC2] = 0x000; // U_WMRC2 0 0 0 0 0 0 0 0 0 0 table[0xC3] = 0x000; // U_WMRC3 0 0 0 0 0 0 0 0 0 0 table[0xC4] = 0x000; // U_WMRC4 0 0 0 0 0 0 0 0 0 0 table[0xC5] = 0x000; // U_WMRC5 0 0 0 0 0 0 0 0 0 0 table[0xC6] = 0x000; // U_WMRC6 0 0 0 0 0 0 0 0 0 0 table[0xC7] = 0x000; // U_WMRC7 0 0 0 0 0 0 0 0 0 0 table[0xC8] = 0x000; // U_WMRC8 0 0 0 0 0 0 0 0 0 0 table[0xC9] = 0x000; // U_WMRC9 0 0 0 0 0 0 0 0 0 0 table[0xCA] = 0x000; // U_WMRCA 0 0 0 0 0 0 0 0 0 0 table[0xCB] = 0x000; // U_WMRCB 0 0 0 0 0 0 0 0 0 0 table[0xCC] = 0x000; // U_WMRCC 0 0 0 0 0 0 0 0 0 0 table[0xCD] = 0x000; // U_WMRCD 0 0 0 0 0 0 0 0 0 0 table[0xCE] = 0x000; // U_WMRCE 0 0 0 0 0 0 0 0 0 0 table[0xCF] = 0x000; // U_WMRCF 0 0 0 0 0 0 0 0 0 0 table[0xD0] = 0x000; // U_WMRD0 0 0 0 0 0 0 0 0 0 0 table[0xD1] = 0x000; // U_WMRD1 0 0 0 0 0 0 0 0 0 0 table[0xD2] = 0x000; // U_WMRD2 0 0 0 0 0 0 0 0 0 0 table[0xD3] = 0x000; // U_WMRD3 0 0 0 0 0 0 0 0 0 0 table[0xD4] = 0x000; // U_WMRD4 0 0 0 0 0 0 0 0 0 0 table[0xD5] = 0x000; // U_WMRD5 0 0 0 0 0 0 0 0 0 0 table[0xD6] = 0x000; // U_WMRD6 0 0 0 0 0 0 0 0 0 0 table[0xD7] = 0x000; // U_WMRD7 0 0 0 0 0 0 0 0 0 0 table[0xD8] = 0x000; // U_WMRD8 0 0 0 0 0 0 0 0 0 0 table[0xD9] = 0x000; // U_WMRD9 0 0 0 0 0 0 0 0 0 0 table[0xDA] = 0x000; // U_WMRDA 0 0 0 0 0 0 0 0 0 0 table[0xDB] = 0x000; // U_WMRDB 0 0 0 0 0 0 0 0 0 0 table[0xDC] = 0x000; // U_WMRDC 0 0 0 0 0 0 0 0 0 0 table[0xDD] = 0x000; // U_WMRDD 0 0 0 0 0 0 0 0 0 0 table[0xDE] = 0x000; // U_WMRDE 0 0 0 0 0 0 0 0 0 0 table[0xDF] = 0x000; // U_WMRDF 0 0 0 0 0 0 0 0 0 0 table[0xE0] = 0x000; // U_WMRE0 0 0 0 0 0 0 0 0 0 0 table[0xE1] = 0x000; // U_WMRE1 0 0 0 0 0 0 0 0 0 0 table[0xE2] = 0x000; // U_WMRE2 0 0 0 0 0 0 0 0 0 0 table[0xE3] = 0x000; // U_WMRE3 0 0 0 0 0 0 0 0 0 0 table[0xE4] = 0x000; // U_WMRE4 0 0 0 0 0 0 0 0 0 0 table[0xE5] = 0x000; // U_WMRE5 0 0 0 0 0 0 0 0 0 0 table[0xE6] = 0x000; // U_WMRE6 0 0 0 0 0 0 0 0 0 0 table[0xE7] = 0x000; // U_WMRE7 0 0 0 0 0 0 0 0 0 0 table[0xE8] = 0x000; // U_WMRE8 0 0 0 0 0 0 0 0 0 0 table[0xE9] = 0x000; // U_WMRE9 0 0 0 0 0 0 0 0 0 0 table[0xEA] = 0x000; // U_WMREA 0 0 0 0 0 0 0 0 0 0 table[0xEB] = 0x000; // U_WMREB 0 0 0 0 0 0 0 0 0 0 table[0xEC] = 0x000; // U_WMREC 0 0 0 0 0 0 0 0 0 0 table[0xED] = 0x000; // U_WMRED 0 0 0 0 0 0 0 0 0 0 table[0xEE] = 0x000; // U_WMREE 0 0 0 0 0 0 0 0 0 0 table[0xEF] = 0x000; // U_WMREF 0 0 0 0 0 0 0 0 0 0 table[0xF0] = 0x020; // U_WMRDELETEOBJECT 0 0 0 0 1 0 0 0 0 0 table[0xF1] = 0x000; // U_WMRF1 0 0 0 0 0 0 0 0 0 0 table[0xF2] = 0x000; // U_WMRF2 0 0 0 0 0 0 0 0 0 0 table[0xF3] = 0x000; // U_WMRF3 0 0 0 0 0 0 0 0 0 0 table[0xF4] = 0x000; // U_WMRF4 0 0 0 0 0 0 0 0 0 0 table[0xF5] = 0x000; // U_WMRF5 0 0 0 0 0 0 0 0 0 0 table[0xF6] = 0x000; // U_WMRF6 0 0 0 0 0 0 0 0 0 0 table[0xF7] = 0x120; // U_WMRCREATEPALETTE 0 1 0 0 1 0 0 0 0 0 Not selected yet, so no change in drawing conditions table[0xF8] = 0x120; // U_WMRCREATEBRUSH 0 1 0 0 1 0 0 0 0 0 " table[0xF9] = 0x120; // U_WMRCREATEPATTERNBRUSH 0 1 0 0 1 0 0 0 0 0 " table[0xFA] = 0x120; // U_WMRCREATEPENINDIRECT 0 1 0 0 1 0 0 0 0 0 " table[0xFB] = 0x120; // U_WMRCREATEFONTINDIRECT 0 1 0 0 1 0 0 0 0 0 " table[0xFC] = 0x120; // U_WMRCREATEBRUSHINDIRECT 0 1 0 0 1 0 0 0 0 0 " table[0xFD] = 0x020; // U_WMRCREATEBITMAPINDIRECT 0 0 0 0 1 0 0 0 0 0 " table[0xFE] = 0x020; // U_WMRCREATEBITMAP 0 0 0 0 1 0 0 0 0 0 " table[0xFF] = 0x120; // U_WMRCREATEREGION 0 1 0 0 1 0 0 0 0 0 " } result = table[type]; } return(result); } /* ********************************************************************************************** These functions are for setting up, appending to, and then tearing down an WMF structure, including writing the final data structure out to a file. *********************************************************************************************** */ /** \brief Duplicate an WMR record. \param wmr record to duplicate */ char *wmr_dup( const char *wmr ){ char *dup; uint32_t irecsize; if(!wmr)return(NULL); memcpy(&irecsize,wmr,4); /* Size16_4 field is at offset 0 */ irecsize *= 2; dup=malloc(irecsize); if(dup){ memcpy(dup,wmr,irecsize); } return(dup); } /* some of these functions are identical to the emf ones, handled by defines in uemf.h,use the emf versions */ /** \brief Start constructing an wmf in memory. Supply the file name and initial size. \return 0 for success, >=0 for failure. \param name WMF filename (will be opened) \param initsize Initialize WMF in memory to hold this many bytes \param chunksize When needed increase WMF in memory by this number of bytes \param wt WMF in memory */ int wmf_start( const char *name, const uint32_t initsize, const uint32_t chunksize, WMFTRACK **wt ){ FILE *fp; WMFTRACK *wtl=NULL; if(initsize < 1)return(1); if(chunksize < 1)return(2); if(!name)return(3); wtl = (WMFTRACK *) malloc(sizeof(WMFTRACK)); if(!wtl)return(4); wtl->buf = malloc(initsize); // no need to zero the memory if(!wtl->buf){ free(wtl); return(5); } fp=wmf_fopen(name,U_WRITE); if(!fp){ free(wtl->buf); free(wtl); return(6); } wtl->fp = fp; wtl->allocated = initsize; wtl->used = 0; wtl->records = 0; wtl->PalEntries = 0; wtl->chunk = chunksize; wtl->largest = 0; /* only used by WMF */ wtl->sumObjects = 0; /* only used by WMF */ (void) wmf_highwater(U_HIGHWATER_CLEAR); *wt=wtl; return(0); } /** \brief Release memory for an wmf structure in memory. Call this after wmf_finish(). \return 0 on success, >=1 on failure \param wt WMF in memory Renamed to uwmf_free to avoid conflict with libwmf */ int uwmf_free( WMFTRACK **wt ){ WMFTRACK *wtl; if(!wt)return(1); wtl=*wt; if(!wtl)return(2); free(wtl->buf); free(wtl); *wt=NULL; (void)wmf_highwater(U_HIGHWATER_CLEAR); return(0); } /** \brief Finalize the emf in memory and write it to the file. \return 0 on success, >=1 on failure \param wt WMF in memory */ int wmf_finish( WMFTRACK *wt ){ char *record; int off; uint32_t tmp; uint16_t tmp16; if(!wt->fp)return(1); // This could happen if something stomps on memory, otherwise should be caught in wmf_start // Set the header fields which were unknown up until this point if(((U_WMRPLACEABLE *) wt->buf)->Key == 0x9AC6CDD7){ off = U_SIZE_WMRPLACEABLE; } else { off = 0; } record = (wt->buf + off); tmp = (wt->used)/2; memcpy(record + offsetof(U_WMRHEADER,Sizew), &tmp, 4); /* 16 bit words in file. not aligned */ tmp = (wt->largest)/2; memcpy(record + offsetof(U_WMRHEADER,maxSize), &tmp, 4); /* 16 bit words in largest record, not aligned */ uint32_t maxobj = wmf_highwater(U_HIGHWATER_READ); if(maxobj > UINT16_MAX)return(3); tmp16 = maxobj; memcpy(record + offsetof(U_WMRHEADER,nObjects), &tmp16, 2); /* Total number of brushes, pens, and other graphics objects defined in this file */ #if U_BYTE_SWAP //This is a Big Endian machine, WMF data must be Little Endian U_wmf_endian(wt->buf,wt->used,1,0); // BE to LE, entire file #endif (void) U_wmr_properties(U_WMR_INVALID); /* force the release of the lookup table memory, returned value is irrelevant */ if(1 != fwrite(wt->buf,wt->used,1,wt->fp))return(2); (void) fclose(wt->fp); wt->fp=NULL; return(0); } /** \brief Retrieve contents of an WMF file by name. \return 0 on success, >=1 on failure \param filename Name of file to open, including the path \param contents Contents of the file. Buffer must be free()'d by caller. \param length Number of bytes in Contents */ int wmf_readdata( const char *filename, char **contents, size_t *length ){ FILE *fp; int status=0; *contents=NULL; fp=wmf_fopen(filename,U_READ); if(!fp){ status = 1; } else { // read the entire file into memory fseek(fp, 0, SEEK_END); // move to end *length = ftell(fp); rewind(fp); *contents = (char *) malloc(*length); if(!*contents){ status = 2; } else { size_t inbytes = fread(*contents,*length,1,fp); if(inbytes != 1){ free(*contents); status = 3; } else { #if U_BYTE_SWAP //This is a Big Endian machine, WMF data is Little Endian U_wmf_endian(*contents,*length,0,0); // LE to BE, entire file #endif } } fclose(fp); } return(status); } /** \brief Append an WMF record to a wmf in memory. This may reallocate buf memory. \return 0 for success, >=1 for failure. \param rec Record to append to WMF in memory \param wt WMF in memory \param freerec If true, free rec after append */ int wmf_append( U_METARECORD *rec, WMFTRACK *wt, int freerec ){ size_t deficit; uint32_t wp; uint32_t size; size = U_wmr_size(rec); #ifdef U_VALGRIND printf("\nbefore \n"); printf(" probe %d\n",memprobe(rec, size)); printf("after \n"); #endif if(!rec)return(1); if(!wt)return(2); if(size + wt->used > wt->allocated){ deficit = size + wt->used - wt->allocated; if(deficit < wt->chunk)deficit = wt->chunk; wt->allocated += deficit; wt->buf = realloc(wt->buf,wt->allocated); if(!wt->buf)return(3); } memcpy(wt->buf + wt->used, rec, size); wt->used += size; wt->records++; if(wt->largest < size)wt->largest=size; /* does the record create an object: brush, font, palette, pen, or region ? Following EOF properties comes back as U_WMR_INVALID */ wp = U_wmr_properties(U_WMRTYPE(rec)); if((wp != U_WMR_INVALID) && (U_DRAW_OBJECT & wp))wt->sumObjects++; if(freerec){ free(rec); } return(0); } /** \brief Append an WMF header to a wmf in memory. This may reallocate buf memory. WMF header is not a normal record, method used to figure out its size is different. \return 0 for success, >=1 for failure. \param rec header to append to WMF in memory \param wt WMF in memory \param freerec If true, free rec after append */ int wmf_header_append( U_METARECORD *rec, WMFTRACK *wt, int freerec ){ size_t deficit; unsigned int hsize; hsize = (((U_WMRPLACEABLE *) rec)->Key == 0x9AC6CDD7 ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE: U_SIZE_WMRHEADER); #ifdef U_VALGRIND printf("\nbefore \n"); printf(" probe %d\n",memprobe(rec, hsize)); printf("after \n"); #endif if(!rec)return(1); if(!wt)return(2); if(U_wmr_size(rec) + wt->used > wt->allocated){ deficit = hsize + wt->used - wt->allocated; if(deficit < wt->chunk)deficit = wt->chunk; wt->allocated += deficit; wt->buf = realloc(wt->buf,wt->allocated); if(!wt->buf)return(3); } memcpy(wt->buf + wt->used, rec, hsize); wt->used += hsize; /* do NOT increment records count, this is not strictly a record */ if(wt->largest < hsize)wt->largest=hsize; if(freerec){ free(rec); } return(0); } /** \brief Keep track of the largest number used. \return The largest object number used. \param setval U_HIGHWATER_READ only return value, U_HIGHWATER_CLEAR also set value to 0, anything else, set to this if higher than stored. */ int wmf_highwater(uint32_t setval){ static uint32_t value=0; uint32_t retval; if(setval == U_HIGHWATER_READ){ retval = value; } else if(setval == U_HIGHWATER_CLEAR){ retval = value; value = 0; } else { if(setval > value)value = setval; retval = value; } return(retval); } /** \brief Create a handle table. Entries filled with 0 are empty, entries >0 hold a handle. \return 0 for success, >=1 for failure. \param initsize Initialize with space for this number of handles \param chunksize When needed increase space by this number of handles \param wht WMF handle table */ int wmf_htable_create( uint32_t initsize, uint32_t chunksize, WMFHANDLES **wht ){ WMFHANDLES *whtl; if(initsize<1)return(1); if(chunksize<1)return(2); whtl = (WMFHANDLES *) malloc(sizeof(WMFHANDLES)); if(!whtl)return(3); whtl->table = malloc(initsize * sizeof(uint32_t)); if(!whtl->table){ free(whtl); return(4); } memset(whtl->table , 0, initsize * sizeof(uint32_t)); // zero all slots in the table whtl->allocated = initsize; whtl->chunk = chunksize; whtl->table[0] = 0; // This slot isn't actually ever used whtl->lolimit = 1; // first available table entry whtl->hilimit = 0; // no entries in the table yet. whtl->peak = 0; // no entries in the table ever *wht = whtl; return(0); } /** \brief Delete an entry from the handle table. Move it back onto the stack. The specified slot is filled with a 0. \return 0 for success, >=1 for failure. \param ih handle \param wht WMF handle table */ int wmf_htable_delete( uint32_t *ih, WMFHANDLES *wht ){ if(!wht)return(1); if(!wht->table)return(2); if(*ih < 1)return(4); // invalid handle if(!wht->table[*ih])return(5); // requested table position was not in use wht->table[*ih]=0; // remove handle from table while(wht->hilimit>0 && !wht->table[wht->hilimit]){ // adjust hilimit wht->hilimit--; } if(*ih < wht->lolimit)wht->lolimit = *ih; // adjust lolimit *ih=0; // invalidate handle variable, so a second delete will of it is not possible return(0); } /** \brief Returns the index of the first free slot. Call realloc() if needed. The slot is set to handle (indicates occupied) and the peak value is adjusted. \return 0 for success, >=1 for failure. \param ih handle \param wht WMF handle table */ int wmf_htable_insert( uint32_t *ih, WMFHANDLES *wht ){ size_t newsize; if(!wht)return(1); if(!wht->table)return(2); if(!ih)return(4); if(wht->lolimit >= wht->allocated - 1){ // need to reallocate newsize=wht->allocated + wht->chunk; wht->table = realloc(wht->table,newsize * sizeof(uint32_t)); if(!wht->table)return(5); memset(&wht->table[wht->allocated] , 0, wht->chunk * sizeof(uint32_t)); // zero all NEW slots in the table wht->allocated = newsize; } *ih = wht->lolimit; // handle that is inserted in first available slot wht->table[*ih] = *ih; // handle goes into preexisting (but zero) slot in table, handle number is the same as the slot number if(*ih > wht->hilimit){ wht->hilimit = *ih; (void) wmf_highwater(wht->hilimit); } if(*ih > wht->peak){ wht->peak = *ih; } /* Find the next available slot, it will be at least one higher than the present position, and will have a zero in it. */ wht->lolimit++; while(wht->lolimit<= wht->hilimit && wht->table[wht->lolimit]){ wht->lolimit++; } return(0); } /** \brief Free all memory in an htable. Sets the pointer to NULL. \return 0 for success, >=1 for failure. \param wht WMF handle table */ int wmf_htable_free( WMFHANDLES **wht ){ WMFHANDLES *whtl; if(!wht)return(1); whtl = *wht; if(!whtl)return(2); if(!whtl->table)return(3); free(whtl->table); free(whtl); *wht=NULL; return(0); } /* ********************************************************************************************** These functions create standard structures used in the WMR records. *********************************************************************************************** */ // hide these from Doxygen //! \cond /* ********************************************************************************************** These functions contain shared code used by various U_WMR*_print functions. These should NEVER be called by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. *********************************************************************************************** */ /* These definitons only used here */ #define U_SIZE_WMR_NOARGS 6 #define U_SIZE_WMR_1ARG16 8 #define U_SIZE_WMR_2ARG16 10 #define U_SIZE_WMR_3ARG16 12 #define U_SIZE_WMR_4ARG16 14 #define U_SIZE_WMR_5ARG16 16 #define U_SIZE_WMR_6ARG16 18 #define U_SIZE_WMR_8ARG16 22 char *U_WMRCORENONE_set(char *string){ printf("unimplemented creator for:%s\n",string); return(NULL); } void U_WMRCORE_SETRECHEAD(char *record, uint32_t irecsize, int iType){ uint32_t Size16; Size16 = irecsize/2; memcpy(record,&Size16,4); /*Size16_4 is at offset 0 in the record */ ((U_METARECORD *) record)->iType = iType; ((U_METARECORD *) record)->xb = U_WMR_XB_FROM_TYPE(iType); } /* records that have no arguments */ char *U_WMRCORE_NOARGS_set( int iType ){ char *record=NULL; uint32_t irecsize; irecsize = U_SIZE_METARECORD; record = malloc(irecsize); if(record)U_WMRCORE_SETRECHEAD(record,irecsize,iType); return(record); } /* records like U_WMRFLOODFILL and others. all args are optional, Color is not */ char *U_WMRCORE_1U16_CRF_2U16_set( int iType, uint16_t *arg1, U_COLORREF Color, uint16_t *arg2, uint16_t *arg3 ){ char *record=NULL; uint32_t irecsize,off; irecsize = U_SIZE_METARECORD + U_SIZE_COLORREF; if(arg1)irecsize+=2; if(arg2)irecsize+=2; if(arg3)irecsize+=2; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; if(arg1){ memcpy(record + off, arg1, 2); off+=2; } memcpy(record + off, &Color, 4); off+=4; if(arg2){ memcpy(record + off, arg2, 2); off+=2; } if(arg3){ memcpy(record + off, arg3, 2); } } return(record); } /* records that have a single uint16_t argument like U_WMRSETMAPMODE May also be used with int16_t with appropriate casts */ char *U_WMRCORE_1U16_set( int iType, uint16_t arg1 ){ char *record=NULL; uint32_t irecsize,off; irecsize = U_SIZE_WMR_1ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); } return(record); } /* records that have two uint16_t arguments like U_WMRSETBKMODE May also be used with int16_t with appropriate casts */ char *U_WMRCORE_2U16_set( int iType, uint16_t arg1, uint16_t arg2 ){ char *record=NULL; uint32_t irecsize,off; irecsize = U_SIZE_WMR_2ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); off+=2; memcpy(record+off,&arg2,2); } return(record); } /* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT May also be used with int16_t with appropriate casts */ char *U_WMRCORE_4U16_set( int iType, uint16_t arg1, uint16_t arg2, uint16_t arg3, uint16_t arg4 ){ char *record=NULL; uint32_t irecsize, off; irecsize = U_SIZE_WMR_4ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); off+=2; memcpy(record+off,&arg2,2); off+=2; memcpy(record+off,&arg3,2); off+=2; memcpy(record+off,&arg4,2); } return(record); } /* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT May also be used with int16_t with appropriate casts */ char *U_WMRCORE_5U16_set( int iType, uint16_t arg1, uint16_t arg2, uint16_t arg3, uint16_t arg4, uint16_t arg5 ){ char *record=NULL; uint32_t irecsize, off; irecsize = U_SIZE_WMR_5ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); off+=2; memcpy(record+off,&arg2,2); off+=2; memcpy(record+off,&arg3,2); off+=2; memcpy(record+off,&arg4,2); off+=2; memcpy(record+off,&arg5,2); } return(record); } /* records that have size uint16_t arguments like U_ROUNDREC May also be used with int16_t with appropriate casts */ char *U_WMRCORE_6U16_set( int iType, uint16_t arg1, uint16_t arg2, uint16_t arg3, uint16_t arg4, uint16_t arg5, uint16_t arg6 ){ char *record=NULL; uint32_t irecsize, off; irecsize = U_SIZE_WMR_6ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); off+=2; memcpy(record+off,&arg2,2); off+=2; memcpy(record+off,&arg3,2); off+=2; memcpy(record+off,&arg4,2); off+=2; memcpy(record+off,&arg5,2); off+=2; memcpy(record+off,&arg6,2); } return(record); } /* records that have eight uint16_t arguments like U_WMRARC May also be used with int16_t with appropriate casts */ char *U_WMRCORE_8U16_set( int iType, uint16_t arg1, uint16_t arg2, uint16_t arg3, uint16_t arg4, uint16_t arg5, uint16_t arg6, uint16_t arg7, uint16_t arg8 ){ char *record=NULL; uint32_t irecsize, off; irecsize = U_SIZE_WMR_8ARG16; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off,&arg1,2); off+=2; memcpy(record+off,&arg2,2); off+=2; memcpy(record+off,&arg3,2); off+=2; memcpy(record+off,&arg4,2); off+=2; memcpy(record+off,&arg5,2); off+=2; memcpy(record+off,&arg6,2); off+=2; memcpy(record+off,&arg7,2); off+=2; memcpy(record+off,&arg8,2); } return(record); } /* records that have arg1 an (optional) (u)int16 arg2 an (optional( (u)int16 N16 number of (u)int16_t cells in array. may be zero array of N16 (u)int16_t cells (or any structure that is 2N bytes in size), should be NULL if N16 is 0. like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL */ char *U_WMRCORE_2U16_N16_set( int iType, const uint16_t *arg1, const uint16_t *arg2, const uint16_t N16, const void *array ){ char *record=NULL; uint32_t irecsize, off; irecsize = U_SIZE_METARECORD + N16*2; if(arg1)irecsize += 2; if(arg2)irecsize += 2; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; if(arg1){ memcpy(record+off,arg1,2); off+=2; } if(arg2){ memcpy(record+off,arg2,2); off+=2; } if(N16){ memcpy(record+off,array,2*N16); } } return(record); } /* records that set a U_PALETTE , then a count and then a uint16_t list like U_WMRANIMATEPALETTE May also be used with int16_t with appropriate casts */ char *U_WMRCORE_PALETTE_set( int iType, const U_PALETTE *Palette ){ char *record=NULL; uint32_t irecsize, off, nPE; nPE = 4*Palette->NumEntries; if(!nPE)return(NULL); /* What would it mean to load an empty palette??? */ irecsize = U_SIZE_METARECORD + 2 + 2 + nPE; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,iType); off = U_SIZE_METARECORD; memcpy(record+off, &Palette->Start, 2); off+=2; memcpy(record+off, &Palette->NumEntries, 2); off+=2; memcpy(record+off, &Palette->PalEntries, nPE); } return(record); } //! \endcond /* ********************************************************************************************** These functions are simpler or more convenient ways to generate the specified types of WMR records. Each should be called in preference to the underlying "base" WMR function. *********************************************************************************************** */ /** \brief Allocate and construct a U_WMRDELETEOBJECT record and also delete the requested object from the table. Use this function instead of calling U_WMRDELETEOBJECT_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRDELETEOBJECT record, or NULL on error. \param ihObject Pointer to handle to delete. This value is set to 0xFFFFFFFF if the function succeeds. \param wht WMF handle table Note that calling this function should always be conditional on the specifed object being defined. It is easy to write a program where deleteobject_set() is called in a sequence where, at the time, we know that ihObject is defined. Then a later modification, possibly quite far away in the code, causes it to be undefined. That distant change will result in a failure when this function reutrns. That problem cannot be handled here because the only values which may be returned are a valid U_WMRDELETEOBJECT record or a NULL, and other errors could result in the NULL. So the object must be checked before the call. */ char *wdeleteobject_set( uint32_t *ihObject, WMFHANDLES *wht ){ uint32_t saveObject=*ihObject; /* caller 0->N */ *ihObject += 1; /* caller 0->N --> 1->N+1 table*/ if(wmf_htable_delete(ihObject,wht))return(NULL); /* invalid handle or other problem, cannot be deleted */ *ihObject = 0xFFFFFFFF; /* EMF would have set to 0, but 0 is an allowed index in WMF */ return(U_WMRDELETEOBJECT_set(saveObject)); /* caller 0->N */ } /** \brief Allocate and construct a U_WMRSELECTOBJECT record, checks that the handle specified is one that can actually be selected. Use this function instead of calling U_WMRSELECTOBJECT_set() directly. Object Pointer in WMF (caller) is 0->N, so is record, so no correction to 1->N+1 needed here. \return pointer to the U_WMRSELECTOBJECT record, or NULL on error. \param ihObject handle to select \param wht WMF handle table */ char *wselectobject_set( uint32_t ihObject, WMFHANDLES *wht ){ /* WMF has no stock objects! */ if(ihObject > wht->hilimit)return(NULL); // handle this high is not in the table /* caller uses 0->N, table uses 1->N+1 */ if(!wht->table[ihObject+1])return(NULL); // handle is not in the table, so cannot be selected /* file uses 0->N */ return(U_WMRSELECTOBJECT_set(ihObject)); } /** \brief Allocate and construct a U_WMRCREATEPENINDIRECT record, create a handle and returns it Use this function instead of calling U_WMRCREATEPENINDIRECT_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error. \param ihPen handle to be used by new object \param wht WMF handle table \param pen Pen parameters (U_PEN) */ char *wcreatepenindirect_set( uint32_t *ihPen, WMFHANDLES *wht, U_PEN pen ){ if(wmf_htable_insert(ihPen, wht))return(NULL); *ihPen -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEPENINDIRECT_set(pen)); } /** \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record, create a handle and returns it Use this function instead of calling U_WMRCREATEBRUSHINDIRECT_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error. \param ihBrush handle to be used by new object \param wht WMF handle table \param lb Brush parameters */ char *wcreatebrushindirect_set( uint32_t *ihBrush, WMFHANDLES *wht, U_WLOGBRUSH lb ){ if(wmf_htable_insert(ihBrush, wht))return(NULL); *ihBrush -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEBRUSHINDIRECT_set(lb)); } /** \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a DIB. Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly. \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. \param ihBrush handle to be used by new object \param wht WMF handle table \param iUsage DIBColors enumeration \param Bmi Bitmap info \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row) \param Px (Optional) bitmapbuffer (pixel array section ) */ char *wcreatedibpatternbrush_srcdib_set( uint32_t *ihBrush, WMFHANDLES *wht, const uint32_t iUsage, const U_BITMAPINFO *Bmi, const uint32_t cbPx, const char *Px ){ if(wmf_htable_insert(ihBrush, wht))return(NULL); *ihBrush -= 1; /* 1->N+1 --> 0->N */ return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_DIBPATTERNPT, iUsage, Bmi, cbPx, Px,NULL)); } /** \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record from a U_BITMAP16 object. Use this function instead of calling U_WMRDIBCREATEPATTERNBRUSH_set() directly. \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. \param ihBrush handle to be used by new object \param wht WMF handle table \param iUsage DIBColors enumeration \param Bm16 Pointer to a Bitmap16 object */ char *wcreatedibpatternbrush_srcbm16_set( uint32_t *ihBrush, WMFHANDLES *wht, const uint32_t iUsage, const U_BITMAP16 *Bm16 ){ if(wmf_htable_insert(ihBrush, wht))return(NULL); *ihBrush -= 1; /* 1->N+1 --> 0->N */ return(U_WMRDIBCREATEPATTERNBRUSH_set(U_BS_PATTERN, iUsage, NULL, 0, NULL, Bm16)); } /** \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record, create a handle and returns it Use this function instead of calling U_WMRCREATEPATTERNBRUSH_set() directly. WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - use U_WMRDIBCREATEPATTERNBRUSH instead. \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error. \param ihBrush handle to be used by new object \param wht WMF handle table \param Bm16 Pointer to a Bitmap16 structure (only first 10 bytes are used). \param Pattern Pointer to a byte array described by Bm16. (Pattern may be a pointer to the BM16 Bits field.) */ char *wcreatepatternbrush_set( uint32_t *ihBrush, WMFHANDLES *wht, U_BITMAP16 *Bm16, char *Pattern ){ if(wmf_htable_insert(ihBrush, wht))return(NULL); *ihBrush -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEPATTERNBRUSH_set(Bm16, Pattern)); } /** \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record, create a handle and returns it Use this function instead of calling U_WMRCREATEFONTINDIRECT_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error. \param ihFont Font handle, will be created and returned \param wht Pointer to structure holding all WMF handles \param uf Pointer to Font parameters as U_FONT * */ char *wcreatefontindirect_set( uint32_t *ihFont, WMFHANDLES *wht, U_FONT *uf ){ if(wmf_htable_insert(ihFont, wht))return(NULL); *ihFont -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEFONTINDIRECT_set(uf)); } /** \brief Allocate and construct a U_WMRCREATEPALETTE record, create a handle and returns it Use this function instead of calling U_WMRCREATEPALETTE_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRCREATEPALETTE record, or NULL on error. \param ihPal Palette handle, will be created and returned \param wht Pointer to structure holding all WMF handles \param up Palette parameters */ char *wcreatepalette_set( uint32_t *ihPal, WMFHANDLES *wht, U_PALETTE *up ){ if(wmf_htable_insert(ihPal, wht))return(NULL); *ihPal -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEPALETTE_set(up)); } /** \brief Allocate and construct a U_WMRSETPALENTRIES record, create a handle and returns it Use this function instead of calling U_WMRSETPALENTRIES_set() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. \param ihPal Palette handle, will be created and returned \param wht Pointer to structure holding all WMF handles \param Palettes Values to set with */ char *wsetpaletteentries_set( uint32_t *ihPal, WMFHANDLES *wht, const U_PALETTE *Palettes ){ if(wmf_htable_insert(ihPal, wht))return(NULL); *ihPal -= 1; /* 1->N+1 --> 0->N */ return(U_WMRSETPALENTRIES_set(Palettes)); } /** \brief Allocate and construct a U_WMRCREATEREGION record, create a handle and returns it Use this function instead of calling U_WMRCREATEREGION() directly. Object Pointer in WMF (caller) is 0->N, but in htable it is 1->N+1, make that correction here. \return pointer to the U_REGIONS record, or NULL on error. \param ihReg Region handle, will be created and returned \param wht Pointer to structure holding all WMF handles \param Region Values to set with */ char *wcreateregion_set( uint32_t *ihReg, WMFHANDLES *wht, const U_REGION *Region ){ if(wmf_htable_insert(ihReg, wht))return(NULL); *ihReg -= 1; /* 1->N+1 --> 0->N */ return(U_WMRCREATEREGION_set(Region)); } /* A few escape functions are implemented, just those that set a state or a single value */ /** \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it Use this function instead of calling U_WMRESCAPE_set() directly. \return pointer to the U_WMRESCAPE structure, or NULL on error. */ char *wbegin_path_set(void){ return(U_WMRESCAPE_set(U_MFE_BEGIN_PATH,0,NULL)); } /** \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it Use this function instead of calling U_WMRESCAPE_set() directly. \return pointer to the U_WMRESCAPE structure, or NULL on error. */ char *wend_path_set(void){ return(U_WMRESCAPE_set(U_MFE_END_PATH,0,NULL)); } /** \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it Use this function instead of calling U_WMRESCAPE_set() directly. \return pointer to the U_WMRESCAPE structure, or NULL on error. \param Type PostScriptCap Enumeration, anything else is an error */ char *wlinecap_set( int32_t Type ){ char *record =NULL; if(Type == U_WPS_CAP_NOTSET || Type == U_WPS_CAP_FLAT || Type == U_WPS_CAP_ROUND || Type == U_WPS_CAP_SQUARE){ record = U_WMRESCAPE_set(U_MFE_SETLINECAP,4,&Type); } return(record); } /** \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it Use this function instead of calling U_WMRESCAPE_set() directly. \return pointer to the U_WMRESCAPE structure, or NULL on error. \param Type PostScriptCap Enumeration, anything else is an error */ char *wlinejoin_set( int32_t Type ){ char *record =NULL; if(Type == U_WPS_JOIN_NOTSET || Type == U_WPS_JOIN_MITER || Type == U_WPS_JOIN_ROUND || Type == U_WPS_JOIN_BEVEL){ record = U_WMRESCAPE_set(U_MFE_SETLINEJOIN,4,&Type); } return(record); } /** \brief Allocate and construct the specified U_WMRESCAPE structure, create a handle and returns it Use this function instead of calling U_WMRESCAPE_set() directly. \return pointer to the U_WMRESCAPE structure, or NULL on error. \param limit PostScriptCap Enumeration, anything else is an error */ char *wmiterlimit_set( int32_t limit ){ return(U_WMRESCAPE_set(U_MFE_SETMITERLIMIT,4,&limit)); } /* ********************************************************************************************** These are the core WMR functions, each creates a particular type of record. All return these records via a char* pointer, which is NULL if the call failed. They are listed in order by the corresponding U_WMR_* index number. *********************************************************************************************** */ /** \brief Set up fields for a (placeable) WMR_HEADER. Most of the fields are blank and are not set until all is written. Typically values are something like (8.5,11.0), 1440 (Letter paper, 1440 DPI). The scaled paper size must fit in the range 0<->32767 inclusive, because it must be represented by a signed 16bit number. If the size + dpi result in out of range values a failure will result. \return pointer to the WMF header record, or NULL on failure \param size Pointer to page size (if NULL, not a placeable header) in inches. Values must be positive and scaled \param dpi Logical units/inch. If 0 defaults to 1440. */ char *U_WMRHEADER_set( U_PAIRF *size, unsigned int dpi ){ char *record=NULL; uint32_t irecsize,off; double xmax,ymax; int16_t xm16,ym16; irecsize = (size ? U_SIZE_WMRHEADER + U_SIZE_WMRPLACEABLE : U_SIZE_WMRHEADER); record = calloc(1,irecsize); /* most will be zero*/ off = 0; if(record){ if(size){ /* placeable */ if(!dpi)dpi=1440; xmax = U_ROUND((double) size->x * (double) dpi); ymax = U_ROUND((double) size->y * (double) dpi); if(xmax < 0 || ymax < 0 || xmax > 32767 || ymax > 32767){ free(record); return(NULL); } xm16 = xmax; ym16 = ymax; ((U_WMRPLACEABLE *) record)->Key = 0x9AC6CDD7; ((U_WMRPLACEABLE *) record)->HWmf = 0; /* Manual says number of 16 bit words in record, but all WMF examples had it as 0 */ ((U_WMRPLACEABLE *) record)->Dst.left = 0; ((U_WMRPLACEABLE *) record)->Dst.top = 0; ((U_WMRPLACEABLE *) record)->Dst.right = xm16; ((U_WMRPLACEABLE *) record)->Dst.bottom = ym16; ((U_WMRPLACEABLE *) record)->Inch = dpi; ((U_WMRPLACEABLE *) record)->Reserved = 0; ((U_WMRPLACEABLE *) record)->Checksum = U_16_checksum((int16_t *)record,10); off = U_SIZE_WMRPLACEABLE; } ((U_WMRHEADER *) (record + off))->iType = 1; ((U_WMRHEADER *) (record + off))->version = U_METAVERSION300; ((U_WMRHEADER *) (record + off))->Size16w = U_SIZE_WMRHEADER/2; } return(record); } /** \brief Allocate and construct a U_WMREOF record \return pointer to the U_WMREOF record, or NULL on error. */ char *U_WMREOF_set(void){ return U_WMRCORE_NOARGS_set(U_WMR_EOF); } /** \brief Create and return a U_WMRSETBKCOLOR record \return pointer to the U_WMRSETBKCOLOR record, or NULL on error \param Color Background Color. */ char *U_WMRSETBKCOLOR_set(U_COLORREF Color){ return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETBKCOLOR,NULL,Color,NULL,NULL); } /** \brief Create and return a U_WMRSETBKMODE record \return pointer to the U_WMRSETBKMODE record, or NULL on error \param Mode MixMode Enumeration */ char *U_WMRSETBKMODE_set(uint16_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Mode, 0); } /** \brief Create and return a U_WMRSETMAPMODE record \return pointer to the U_WMRSETMAPMODE record, or NULL on error \param Mode MapMode Enumeration */ char *U_WMRSETMAPMODE_set(uint16_t Mode){ return U_WMRCORE_1U16_set(U_WMR_SETMAPMODE, Mode); } /** \brief Create and return a U_WMRSETROP2 record \return pointer to the U_WMRSETROP2 record, or NULL on error \param Mode Binary Raster Operation Enumeration */ char *U_WMRSETROP2_set(uint16_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETROP2, Mode, 0); } /** \brief Allocate and construct a U_WMRSETRELABS record \return pointer to the U_WMRSETRELABS record, or NULL on error. */ char *U_WMRSETRELABS_set(void){ return U_WMRCORE_NOARGS_set(U_WMR_SETRELABS); } /** \brief Create and return a U_WMRSETPOLYFILLMODE record \return pointer to the U_WMRSETPOLYFILLMODE record, or NULL on error \param Mode PolyFillMode Enumeration */ char *U_WMRSETPOLYFILLMODE_set(uint16_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETPOLYFILLMODE, Mode, 0); } /** \brief Create and return a U_WMRSETSTRETCHBLTMODE record \return pointer to the U_WMRSETSTRETCHBLTMODE record, or NULL on error \param Mode StretchMode Enumeration */ char *U_WMRSETSTRETCHBLTMODE_set(uint16_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETSTRETCHBLTMODE, Mode, 0); } /** \brief Create and return a U_WMRSETTEXTCHAREXTRA record \return pointer to the U_WMRSETTEXTCHAREXTRA record, or NULL on error \param Mode Extra space in logical units to add to each character */ char *U_WMRSETTEXTCHAREXTRA_set(uint16_t Mode){ return U_WMRCORE_1U16_set(U_WMR_SETTEXTCHAREXTRA, Mode); } /** \brief Create and return a U_WMRSETTEXTCOLOR record \return pointer to the U_WMRSETTEXTCOLOR record, or NULL on error \param Color Text Color. */ char *U_WMRSETTEXTCOLOR_set(U_COLORREF Color){ return U_WMRCORE_1U16_CRF_2U16_set(U_WMR_SETTEXTCOLOR,NULL,Color,NULL,NULL); } /** \brief Create and return a U_WMRSETTEXTJUSTIFICATION record \return pointer to the U_WMRSETTEXTJUSTIFICATION record, or NULL on error \param Count Number of space characters in the line. \param Extra Number of extra space characters to add to the line. */ char *U_WMRSETTEXTJUSTIFICATION_set(uint16_t Count, uint16_t Extra){ return U_WMRCORE_2U16_set(U_WMR_SETBKMODE, Count, Extra); } /** \brief Create and return a U_WMRSETWINDOWORG record \return pointer to the U_WMRSETWINDOWORG record, or NULL on error \param coord Window Origin. */ char *U_WMRSETWINDOWORG_set(U_POINT16 coord){ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWORG, U_U16(coord.y), U_U16(coord.x)); } /** \brief Create and return a U_WMRSETWINDOWEXT record \return pointer to the U_WMRSETWINDOWEXT record, or NULL on error \param extent Window Extent. */ char *U_WMRSETWINDOWEXT_set(U_POINT16 extent){ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x)); } /** \brief Create and return a U_WMRSETVIEWPORTORG record \return pointer to the U_WMRSETVIEWPORTORG record, or NULL on error \param coord Viewport Origin. */ char *U_WMRSETVIEWPORTORG_set(U_POINT16 coord){ return U_WMRCORE_2U16_set(U_WMR_SETVIEWPORTORG, U_U16(coord.y), U_U16(coord.x)); } /** \brief Create and return a U_WMRSETVIEWPORTEXT record \return pointer to the U_WMRSETVIEWPORTEXT record, or NULL on error \param extent Viewport Extent. */ char *U_WMRSETVIEWPORTEXT_set(U_POINT16 extent){ return U_WMRCORE_2U16_set(U_WMR_SETWINDOWEXT, U_U16(extent.y), U_U16(extent.x)); } /** \brief Create and return a U_WMROFFSETWINDOWORG record \return pointer to the U_WMROFFSETWINDOWORG record, or NULL on error \param offset Window offset in device units. */ char *U_WMROFFSETWINDOWORG_set(U_POINT16 offset){ return U_WMRCORE_2U16_set(U_WMR_OFFSETWINDOWORG, U_U16(offset.y), U_U16(offset.x)); } /** \brief Create and return a U_WMRSCALEWINDOWEXT record \return pointer to the U_WMRSCALEWINDOWEXT record, or NULL on error \param Denom {X,Y} denominators. \param Num {X,Y} numerators. */ char *U_WMRSCALEWINDOWEXT_set(U_POINT16 Denom, U_POINT16 Num){ return U_WMRCORE_4U16_set(U_WMR_SCALEWINDOWEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x)); } /** \brief Create and return a U_WMROFFSETVIEWPORTORG record \return pointer to the U_WMROFFSETVIEWPORTORG record, or NULL on error \param offset Viewport offset in device units. */ char *U_WMROFFSETVIEWPORTORG_set(U_POINT16 offset){ return U_WMRCORE_2U16_set(U_WMR_OFFSETVIEWPORTORG, U_U16(offset.y), U_U16(offset.x)); } /** \brief Create and return a U_WMRSCALEVIEWPORTEXT record \return pointer to the U_WMRSCALEVIEWPORTEXT record, or NULL on error \param Denom {X,Y} denominators. \param Num {X,Y} numerators. */ char *U_WMRSCALEVIEWPORTEXT_set(U_POINT16 Denom, U_POINT16 Num){ return U_WMRCORE_4U16_set(U_WMR_SCALEVIEWPORTEXT, U_U16(Denom.y), U_U16(Num.y), U_U16(Denom.x), U_U16(Num.x)); } /** \brief Create and return a U_WMRLINETO record \return pointer to the U_WMRLINETO record, or NULL on error \param coord Draw line to {X,Y}. */ char *U_WMRLINETO_set(U_POINT16 coord){ return U_WMRCORE_2U16_set(U_WMR_LINETO, U_U16(coord.y), U_U16(coord.x)); } /** \brief Create and return a U_WMRMOVETO record \return pointer to the U_WMRMOVETO record, or NULL on error \param coord Move to {X,Y}. */ char *U_WMRMOVETO_set(U_POINT16 coord){ return U_WMRCORE_2U16_set(U_WMR_MOVETO, U_U16(coord.y), U_U16(coord.x)); } /** \brief Create and return a U_WMREXCLUDECLIPRECT record \return pointer to the U_WMREXCLUDECLIPRECT record, or NULL on error \param rect Exclude rect from clipping region. */ char *U_WMREXCLUDECLIPRECT_set(U_RECT16 rect){ return U_WMRCORE_4U16_set( U_WMR_EXCLUDECLIPRECT, U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRINTERSECTCLIPRECT record \return pointer to the U_WMRINTERSECTCLIPRECT record, or NULL on error \param rect Clipping region is intersection of existing clipping region with rect. */ char *U_WMRINTERSECTCLIPRECT_set(U_RECT16 rect){ return U_WMRCORE_4U16_set( U_WMR_INTERSECTCLIPRECT, U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRARC record \return pointer to the U_WMRARC record, or NULL on error \param StartArc Start of Arc \param EndArc End of Arc \param rect Bounding rectangle. */ char *U_WMRARC_set(U_POINT16 StartArc, U_POINT16 EndArc, U_RECT16 rect){ return U_WMRCORE_8U16_set( U_WMR_ARC, U_U16(EndArc.y), U_U16(EndArc.x), U_U16(StartArc.y), U_U16(StartArc.x), U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRELLIPSE record \return pointer to the U_WMRELLIPSE record, or NULL on error \param rect Bounding rectangle for Ellipse. */ char *U_WMRELLIPSE_set(U_RECT16 rect){ return U_WMRCORE_4U16_set( U_WMR_ELLIPSE, U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRFLOODFILL record \return pointer to the U_WMRFLOODFILL record, or NULL on error \param Mode FloodFill Enumeration. \param Color Color to Fill with. \param coord Location to start fill. */ char *U_WMRFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){ return U_WMRCORE_1U16_CRF_2U16_set( U_WMR_FLOODFILL, &Mode, Color, U_P16(coord.y), U_P16(coord.x) ); } /** \brief Create and return a U_WMRPIE record \return pointer to the U_WMRPIE record, or NULL on error \param Radial1 Start of Pie \param Radial2 End of Pie \param rect Bounding rectangle. */ char *U_WMRPIE_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){ return U_WMRCORE_8U16_set( U_WMR_PIE, U_U16(Radial2.y), U_U16(Radial2.x), U_U16(Radial1.y), U_U16(Radial1.x), U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRRECTANGLE record \return pointer to the U_WMRRECTANGLE record, or NULL on error \param rect Boundaries. */ char *U_WMRRECTANGLE_set(U_RECT16 rect){ return U_WMRCORE_4U16_set( U_WMR_RECTANGLE, U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Create and return a U_WMRROUNDRECT record \return pointer to the U_WMRROUNDRECT record, or NULL on error \param Width Horizontal rounding length. \param Height Vertical rounding length. \param rect Boundaries. */ char *U_WMRROUNDRECT_set(int16_t Width, int16_t Height, U_RECT16 rect){ return U_WMRCORE_6U16_set( U_WMR_ROUNDRECT, U_U16(Height), U_U16(Width), U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Allocate and construct a U_WMRPATBLT record. \return pointer to the U_WMRPATBLT record, or NULL on error. \param Dst Destination UL corner in logical units \param cwh W & H for Dst and Src in logical units \param dwRop3 RasterOPeration Enumeration */ char *U_WMRPATBLT_set( U_POINT16 Dst, U_POINT16 cwh, uint32_t dwRop3 ){ char *record=NULL; uint32_t irecsize; U_WMRPATBLT *pmr; irecsize = U_SIZE_WMRPATBLT; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_PATBLT); pmr = (U_WMRPATBLT *) record; memcpy(pmr->rop3w, &dwRop3, 4); pmr->Height = cwh.y; pmr->Width = cwh.x; pmr->yDst = Dst.y; pmr->xDst = Dst.x; } return(record); } /** \brief Allocate and construct a U_WMRSAVEDC record \return pointer to the U_WMRSAVEDC record, or NULL on error. */ char *U_WMRSAVEDC_set(void){ return U_WMRCORE_NOARGS_set(U_WMR_SAVEDC); } /** \brief Allocate and construct a U_WMRSETPIXEL record \return pointer to the U_WMRSETPIXEL record, or NULL on error. \param Color U_COLORREF color of the pixel \param Coord U_POINT16 coordinates of the pixel */ char *U_WMRSETPIXEL_set(U_COLORREF Color, U_POINT16 Coord){ return U_WMRCORE_1U16_CRF_2U16_set( U_WMR_SETPIXEL, NULL, Color, U_P16(Coord.y), U_P16(Coord.x) ); } /** \brief Allocate and construct a U_WMROFFSETCLIPRGN record \return pointer to the U_WMROFFSETCLIPRGN record, or NULL on error. \param offset U_POINT16 x,y offset to apply to the clipping region. */ char *U_WMROFFSETCLIPRGN_set(U_POINT16 offset){ return U_WMRCORE_2U16_set(U_WMR_OFFSETCLIPRGN, U_U16(offset.y), U_U16(offset.x)); } /** \brief Allocate and construct a U_WMRTEXTOUT record. \return pointer to the U_WMRTEXTOUT record, or NULL on error. \param Dst Destinationin logical units \param string Null terminated string to write. The terminator is NOT placed in the record! */ char *U_WMRTEXTOUT_set(U_POINT16 Dst, char *string){ char *record=NULL; uint32_t irecsize,off; int L2; int16_t Length; irecsize = 2 + U_SIZE_METARECORD + 4; /* core + length + Dst */ Length = strlen(string); L2 = ( Length & 1 ? Length + 1 : Length); irecsize += L2; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_TEXTOUT); off = U_SIZE_METARECORD; memcpy(record+off,&Length,2); off+=2; memcpy(record+off,string,Length); off+=Length; if(Length!=L2){ memset(record+off,0,1); off+=1; } memcpy(record+off,&Dst.y,2); off+=2; memcpy(record+off,&Dst.x,2); } return(record); } /** \brief Allocate and construct a U_WMRBITBLT record. Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst rectangles must be the same size. \return pointer to the U_WMRBITBLT record, or NULL on error. \param Dst Destination UL corner in logical units \param cwh W & H for Dst and Src in logical units \param Src Source UL corner in logical units \param dwRop3 RasterOPeration Enumeration \param Bm16 (Optional) bitmap16 object */ char *U_WMRBITBLT_set( U_POINT16 Dst, U_POINT16 cwh, U_POINT16 Src, uint32_t dwRop3, const U_BITMAP16 *Bm16 ){ char *record=NULL; uint32_t irecsize; int cbBm16,cbBm164,off; U_WMRBITBLT_PX *pmr_px; U_WMRBITBLT_NOPX *pmr_nopx; if(Bm16){ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; cbBm164 = UP4(cbBm16); irecsize = U_SIZE_WMRBITBLT_PX + cbBm164; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT); pmr_px = (U_WMRBITBLT_PX *) record; memcpy(pmr_px->rop3w, &dwRop3, 4); pmr_px->ySrc = Src.y; pmr_px->xSrc = Src.x; pmr_px->Height = cwh.y; pmr_px->Width = cwh.x; pmr_px->yDst = Dst.y; pmr_px->xDst = Dst.x; off = U_SIZE_WMRBITBLT_PX; memcpy(record + off, Bm16, cbBm16); off += cbBm16; if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); } } else { irecsize = U_SIZE_WMRBITBLT_NOPX; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_BITBLT); pmr_nopx = (U_WMRBITBLT_NOPX *) record; memcpy(pmr_nopx->rop3w, &dwRop3, 4); pmr_nopx->ySrc = Src.y; pmr_nopx->xSrc = Src.x; pmr_nopx->Height = cwh.y; pmr_nopx->Width = cwh.x; pmr_nopx->ignore = 0; pmr_nopx->yDst = Dst.y; pmr_nopx->xDst = Dst.x; } } return(record); } /** \brief Allocate and construct a U_WMRSTRETCHBLT record. \return pointer to the U_WMRSTRETCHBLT record, or NULL on error. \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param dwRop3 RasterOPeration Enumeration \param Bm16 (Optional) bitmap16 object */ char *U_WMRSTRETCHBLT_set( U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src, U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAP16 *Bm16 ){ char *record=NULL; uint32_t irecsize; int cbBm16,cbBm164,off; U_WMRSTRETCHBLT_PX *pmr_px; U_WMRSTRETCHBLT_NOPX *pmr_nopx; if(Bm16){ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; cbBm164 = UP4(cbBm16); irecsize = U_SIZE_WMRSTRETCHBLT_PX + cbBm164; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT); pmr_px = (U_WMRSTRETCHBLT_PX *) record; memcpy(pmr_px->rop3w, &dwRop3, 4); pmr_px->hSrc = cSrc.y; pmr_px->wSrc = cSrc.x; pmr_px->ySrc = Src.y; pmr_px->xSrc = Src.x; pmr_px->hDst = cDst.y; pmr_px->wDst = cDst.x; pmr_px->yDst = Dst.y; pmr_px->xDst = Dst.x; off = U_SIZE_WMRSTRETCHBLT_PX; memcpy(record + off, Bm16, cbBm16); off += cbBm16; if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); } } else { irecsize = U_SIZE_WMRSTRETCHBLT_NOPX; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHBLT); pmr_nopx = (U_WMRSTRETCHBLT_NOPX *) record; memcpy(pmr_nopx->rop3w, &dwRop3, 4); pmr_nopx->hSrc = cSrc.y; pmr_nopx->wSrc = cSrc.x; pmr_nopx->ySrc = Src.y; pmr_nopx->xSrc = Src.x; pmr_nopx->ignore = 0; pmr_nopx->hDst = cDst.y; pmr_nopx->wDst = cDst.x; pmr_nopx->yDst = Dst.y; pmr_nopx->xDst = Dst.x; } } return(record); } /** \brief Allocate and construct a U_WMRPOLYGON record. \return pointer to the U_WMRPOLYGON record, or NULL on error. \param Length Number of points in the Polygon \param Data Array of Length points */ char *U_WMRPOLYGON_set(uint16_t Length, const U_POINT16 *Data){ return U_WMRCORE_2U16_N16_set(U_WMR_POLYGON, NULL, &Length, 2*Length, Data); } /** \brief Allocate and construct a U_WMRPOLYLINE record. \return pointer to the U_WMRPOLYLINE record, or NULL on error. \param Length Number of points in the Polyline \param Data Array of Length points */ char *U_WMRPOLYLINE_set(uint16_t Length, const U_POINT16 *Data){ return U_WMRCORE_2U16_N16_set(U_WMR_POLYLINE, NULL, &Length, 2*Length, Data); } /** \brief Allocate and construct a U_WMRESCAPE record. WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT. Even these should not be set here directly, instead use the wsetlinecap_set(), wsetlinejoin_set(), or wsetmiterlimit_set() functions. Escape records created with this function, with the exception of the three named above, will not have the byte orders in Data adjusted automatically. The user code must set Data to be little endian no matter what the endianness of the current platform where the user code is running. \return pointer to the U_WMRESCAPE record, or NULL on error. \param Escape Escape function \param Length Bytes in the Data \param Data Array of Length bytes */ char *U_WMRESCAPE_set(uint16_t Escape, uint16_t Length, const void *Data){ return U_WMRCORE_2U16_N16_set(U_WMR_ESCAPE, &Escape, &Length, Length/2, Data); } /** \brief Allocate and construct a U_WMRRESTOREDC record \return pointer to the U_WMRRESTOREDC record, or NULL on error. \param DC Drawing Context to restore. (negative is relative to current, positive is absolute) */ char *U_WMRRESTOREDC_set(int16_t DC){ return U_WMRCORE_1U16_set(U_WMR_RESTOREDC, DC); } /** \brief Allocate and construct a U_WMRFILLREGION record. \return pointer to the U_WMRFILLREGION record, or NULL on error. \param Region Region to fill \param Brush Brush to fill with */ char *U_WMRFILLREGION_set(uint16_t Region, uint16_t Brush){ return U_WMRCORE_2U16_set(U_WMR_FILLREGION, Region, Brush); } /** \brief Allocate and construct a U_WMRFRAMEREGION record. \return pointer to the U_WMRFRAMEREGION record, or NULL on error. \param Region Index of region to frame in object table \param Brush Index of brush to use in frame in object table \param Height in logical units (of frame) \param Width in logical units (of frame) */ char *U_WMRFRAMEREGION_set(uint16_t Region, uint16_t Brush, int16_t Height, int16_t Width){ return U_WMRCORE_4U16_set(U_WMR_FRAMEREGION, Region, Brush, U_U16(Height), U_U16(Width)); } /** \brief Allocate and construct a U_WMRINVERTREGION record. \return pointer to the U_WMRINVERTREGION record, or NULL on error. \param Region Index of region to invert. */ char *U_WMRINVERTREGION_set(uint16_t Region){ return U_WMRCORE_1U16_set(U_WMR_INVERTREGION, Region); } /** \brief Allocate and construct a U_WMRPAINTREGION record. \return pointer to the U_WMRPAINTREGION record, or NULL on error. \param Region Index of region to paint with the current Brush. */ char *U_WMRPAINTREGION_set(uint16_t Region){ return U_WMRCORE_1U16_set(U_WMR_PAINTREGION, Region); } /** \brief Allocate and construct a U_WMRSELECTCLIPREGION record. \return pointer to the U_WMRSELECTCLIPREGION record, or NULL on error. \param Region Index of region to become clipping region.. */ char *U_WMRSELECTCLIPREGION_set(uint16_t Region){ return U_WMRCORE_1U16_set(U_WMR_SELECTCLIPREGION, Region); } /** \brief Allocate and construct a U_WMRSELECTOBJECT record. \return pointer to the U_WMRSELECTOBJECT record, or NULL on error. \param object Index of object which is made active. */ char *U_WMRSELECTOBJECT_set(uint16_t object){ return U_WMRCORE_1U16_set(U_WMR_SELECTOBJECT, object); } /** \brief Allocate and construct a U_WMRSETTEXTALIGN record. \return pointer to the U_WMRSETTEXTALIGN record, or NULL on error. \param Mode TextAlignment Enumeration. */ char *U_WMRSETTEXTALIGN_set(uint16_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETTEXTALIGN, Mode, 0); } /** in GDI and Wine, not in WMF manual.. */ char *U_WMRDRAWTEXT_set(void){ return U_WMRCORENONE_set("U_WMRDRAWTEXT"); } /** \brief Create and return a U_WMRCHORD record \return pointer to the U_WMRCHORD record, or NULL on error \param Radial1 Start of Chord \param Radial2 End of Chord \param rect Bounding rectangle. */ char *U_WMRCHORD_set(U_POINT16 Radial1, U_POINT16 Radial2, U_RECT16 rect){ return U_WMRCORE_8U16_set( U_WMR_CHORD, U_U16(Radial2.y), U_U16(Radial2.x), U_U16(Radial1.y), U_U16(Radial1.x), U_U16(rect.bottom), U_U16(rect.right), U_U16(rect.top), U_U16(rect.left) ); } /** \brief Allocate and construct a U_WMRSETMAPPERFLAGS record. \return pointer to the U_WMRSETMAPPERFLAGS record, or NULL on error. \param Mode If 1 bit set font mapper selects only matching aspect fonts. */ char *U_WMRSETMAPPERFLAGS_set(uint32_t Mode){ return U_WMRCORE_2U16_set(U_WMR_SETMAPPERFLAGS, 0xFFFF & Mode, Mode>>16); } /** \brief Allocate and construct a U_WMREXTTEXTOUT record. \return pointer to the U_WMREXTTEXTOUT record, or NULL on error. \param Dst {X,Y} coordinates where the string is to be written. \param Length Stringlength in bytes \param Opts ExtTextOutOptions Flags \param string String to write (Latin1 encoding) \param dx Kerning information. Must have same number of entries as Length. \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts */ char *U_WMREXTTEXTOUT_set(U_POINT16 Dst, int16_t Length, uint16_t Opts, const char *string, int16_t *dx, U_RECT16 rect){ char *record=NULL; uint32_t irecsize,off; int slen; irecsize = U_SIZE_METARECORD + 8; /* 8 = y,x,Length,Opts*/ slen = ( Length & 1 ? Length + 1 : Length); irecsize += slen; if(dx)irecsize += 2*Length; if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ irecsize += U_SIZE_RECT16; } record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_EXTTEXTOUT); off = U_SIZE_METARECORD; memcpy(record+off,&Dst.y,2); off+=2; memcpy(record+off,&Dst.x,2); off+=2; memcpy(record+off,&Length,2); off+=2; memcpy(record+off,&Opts,2); off+=2; if(Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ memcpy(record+off,&rect.bottom,2); off+=2; memcpy(record+off,&rect.right, 2); off+=2; memcpy(record+off,&rect.top, 2); off+=2; memcpy(record+off,&rect.left, 2); off+=2; } memcpy(record+off,string,strlen(string)); off+=Length; if(Length!=slen){ memset(record+off,0,1); off+=1; } if(dx){ memcpy(record+off,dx,2*Length); } } return(record); } /** \brief Allocate and construct a U_WMRSETDIBTODEV record \return pointer to the U_WMRSETDIBTODEV record, or NULL on error. */ char *U_WMRSETDIBTODEV_set(void){ return U_WMRCORENONE_set("U_WMRSETDIBTODEV"); } /** \brief Allocate and construct a U_WMRSELECTPALETTE record \return pointer to the U_WMRSELECTPALETTE record, or NULL on error. \param Palette Index of Palette to make active. */ char *U_WMRSELECTPALETTE_set(uint16_t Palette){ return U_WMRCORE_1U16_set(U_WMR_SELECTPALETTE, Palette); } /** \brief Allocate and construct a U_WMRREALIZEPALETTE record \return pointer to the U_WMRREALIZEPALETTE record, or NULL on error. */ char *U_WMRREALIZEPALETTE_set(void){ return U_WMRCORE_NOARGS_set(U_WMR_REALIZEPALETTE); } /** \brief Allocate and construct a U_WMRSETPALENTRIES record \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. \param Palette Redefines a set of RGB values for the current active Palette. */ char *U_WMRANIMATEPALETTE_set(U_PALETTE *Palette){ return U_WMRCORE_PALETTE_set(U_WMR_ANIMATEPALETTE, Palette); } /** \brief Allocate and construct a U_WMRSETPALENTRIES record \return pointer to the U_WMRSETPALENTRIES record, or NULL on error. \param Palette Defines a set of RGB values for the current active Palette. */ char *U_WMRSETPALENTRIES_set(const U_PALETTE *Palette){ return U_WMRCORE_PALETTE_set(U_WMR_SETPALENTRIES, Palette); } /** \brief Allocate and construct a U_WMR_POLYPOLYGON record. \return pointer to the U_WMR_POLYPOLYGON record, or NULL on error. \param nPolys Number of elements in aPolyCounts \param aPolyCounts Number of points in each poly (sequential) \param Points array of points */ char *U_WMRPOLYPOLYGON_set( const uint16_t nPolys, const uint16_t *aPolyCounts, const U_POINT16 *Points ){ char *record; uint32_t irecsize; int i,cbPolys,cbPoints,off; cbPolys = sizeof(uint16_t)*nPolys; for(i=cbPoints=0; irop3w, &dwRop3, 4); pmr_px->ySrc = Src.y; pmr_px->xSrc = Src.x; pmr_px->Height = cwh.y; pmr_px->Width = cwh.x; pmr_px->yDst = Dst.y; pmr_px->xDst = Dst.x; off = U_SIZE_WMRDIBBITBLT_PX; memcpy(record + off, Bmi, cbBmi); off += cbBmi; memcpy(record + off, Px, cbPx); off += cbPx; if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); } } else if(!Px && !Bmi){ irecsize = U_SIZE_WMRDIBBITBLT_NOPX; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBBITBLT); pmr_nopx = (U_WMRDIBBITBLT_NOPX *) record; memcpy(pmr_nopx->rop3w, &dwRop3, 4); pmr_nopx->ySrc = Src.y; pmr_nopx->xSrc = Src.x; pmr_nopx->ignore = 0; pmr_nopx->Height = cwh.y; pmr_nopx->Width = cwh.x; pmr_nopx->yDst = Dst.y; pmr_nopx->xDst = Dst.x; } } return(record); } /** \brief Allocate and construct a U_WMRSTRETCHDIB record. \return pointer to the U_WMRSTRETCHDIB record, or NULL on error. \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param dwRop3 RasterOPeration Enumeration \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) \param Px (Optional) bitmapbuffer (pixel array section ) */ char *U_WMRDIBSTRETCHBLT_set( U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src, U_POINT16 cSrc, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px ){ char *record=NULL; uint32_t irecsize; int cbImage,cbImage4,cbBmi,off; U_WMRDIBSTRETCHBLT_PX *pmr_px; U_WMRDIBSTRETCHBLT_NOPX *pmr_nopx; if(Px && Bmi){ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); irecsize = U_SIZE_WMRDIBSTRETCHBLT_PX + cbBmi + cbImage4; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT); pmr_px = (U_WMRDIBSTRETCHBLT_PX *) record; memcpy(pmr_px->rop3w, &dwRop3, 4); pmr_px->hSrc = cSrc.y; pmr_px->wSrc = cSrc.x; pmr_px->ySrc = Src.y; pmr_px->xSrc = Src.x; pmr_px->hDst = cDst.y; pmr_px->wDst = cDst.x; pmr_px->yDst = Dst.y; pmr_px->xDst = Dst.x; off = U_SIZE_WMRDIBSTRETCHBLT_PX; memcpy(record + off, Bmi, cbBmi); off += cbBmi; memcpy(record + off, Px, cbPx); off += cbPx; if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); } } else if(!Px && !Bmi){ irecsize = U_SIZE_WMRDIBSTRETCHBLT_NOPX; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBSTRETCHBLT); pmr_nopx = (U_WMRDIBSTRETCHBLT_NOPX *) record; memcpy(pmr_nopx->rop3w, &dwRop3, 4); pmr_nopx->hSrc = cSrc.y; pmr_nopx->wSrc = cSrc.x; pmr_nopx->ySrc = Src.y; pmr_nopx->xSrc = Src.x; pmr_nopx->ignore = 0; pmr_nopx->hDst = cDst.y; pmr_nopx->wDst = cDst.x; pmr_nopx->yDst = Dst.y; pmr_nopx->xDst = Dst.x; } } return(record); } /** \brief Allocate and construct a U_WMRDIBCREATEPATTERNBRUSH record. Accepts an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined). \return pointer to the U_WMRDIBCREATEPATTERNBRUSH record, or NULL on error. \param Style BrushStyle Enumeration \param iUsage DIBcolors Enumeration \param Bm16 pointer to U_BITMAP16 object for Style U_BS_PATTERN only \param cbPx Size in bytes of pixel array (row stride * height, there may be some padding at the end of each row), for use with Bmi \param Px bitmap buffer, for use with Bmi \param Bmi pointer to U_BITMAPINFO for all Style OTHER than U_BS_PATTERN */ char *U_WMRDIBCREATEPATTERNBRUSH_set( const uint16_t Style, const uint16_t iUsage, const U_BITMAPINFO *Bmi, const uint32_t cbPx, const char *Px, const U_BITMAP16 *Bm16 ){ char *record=NULL; uint32_t irecsize; int cbImage,cbImage4,cbBmi,cbBm16,cbBm164,off; if(Style==U_BS_PATTERN && Bm16){ cbBm16 = U_SIZE_BITMAP16 + (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; cbBm164 = UP4(cbBm16); irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBm164; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH); off = U_SIZE_METARECORD; memcpy(record + off, &Style, 2); off+=2; memcpy(record + off, &iUsage, 2); off+=2; memcpy(record + off, Bm16, cbBm16); off += cbBm16; if(cbBm164 - cbBm16)memset(record+off,0,cbBm164 - cbBm16); } } else if(Bmi && Px){ SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); irecsize = U_SIZE_WMRDIBCREATEPATTERNBRUSH + cbBmi + cbImage4; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_DIBCREATEPATTERNBRUSH); off = U_SIZE_METARECORD; memcpy(record + off, &Style, 2); off+=2; memcpy(record + off, &iUsage, 2); off+=2; memcpy(record + off, Bmi, cbBmi); off += cbBmi; memcpy(record + off, Px, cbImage); off += cbImage; if(cbImage4 - cbImage)memset(record + off, 0, cbImage4 - cbImage); } } return(record); } /** \brief Allocate and construct a U_WMRSTRETCHDIB record. \return pointer to the U_WMRSTRETCHDIB record, or NULL on error. \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param cUsage DIBColors Enumeration \param dwRop3 RasterOPeration Enumeration \param Bmi (Optional) bitmapbuffer (U_BITMAPINFO section) \param cbPx Size in bytes of pixel array (row STRIDE * height, there may be some padding at the end of each row) \param Px (Optional) bitmapbuffer (pixel array section ) */ char *U_WMRSTRETCHDIB_set( U_POINT16 Dst, U_POINT16 cDst, U_POINT16 Src, U_POINT16 cSrc, uint16_t cUsage, uint32_t dwRop3, const U_BITMAPINFO *Bmi, uint32_t cbPx, const char *Px ){ char *record; uint32_t irecsize; int cbImage,cbImage4,cbBmi,off; U_WMRSTRETCHDIB *pmr; SET_CB_FROM_PXBMI(Px,Bmi,cbImage,cbImage4,cbBmi,cbPx); irecsize = U_SIZE_WMRSTRETCHDIB + cbBmi + cbImage4; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_STRETCHDIB); pmr = (U_WMRSTRETCHDIB *) record; memcpy(pmr->rop3w, &dwRop3, 4); pmr->cUsage = cUsage; pmr->hSrc = cSrc.y; pmr->wSrc = cSrc.x; pmr->ySrc = Src.y; pmr->xSrc = Src.x; pmr->hDst = cDst.y; pmr->wDst = cDst.x; pmr->yDst = Dst.y; pmr->xDst = Dst.x; off = U_SIZE_WMRSTRETCHDIB; if(cbBmi){ memcpy(record + off, Bmi, cbBmi); off += cbBmi; memcpy(record + off, Px, cbPx); off += cbPx; if(cbImage4 - cbImage)memset(record+off,0,cbImage4 - cbImage); } } return(record); } //! \cond char *U_WMR44_set(void){ return U_WMRCORENONE_set("U_WMR44"); } char *U_WMR45_set(void){ return U_WMRCORENONE_set("U_WMR45"); } char *U_WMR46_set(void){ return U_WMRCORENONE_set("U_WMR46"); } char *U_WMR47_set(void){ return U_WMRCORENONE_set("U_WMR47"); } //! \endcond /** \brief Create and return a U_WMREXTFLOODFILL record \return pointer to the U_WMREXTFLOODFILL record, or NULL on error \param Mode FloodFill Enumeration. \param Color Color to Fill with. \param coord Location to start fill. */ char *U_WMREXTFLOODFILL_set(uint16_t Mode, U_COLORREF Color, U_POINT16 coord){ return U_WMRCORE_1U16_CRF_2U16_set( U_WMR_EXTFLOODFILL, &Mode, Color, U_P16(coord.y), U_P16(coord.x) ); } //! \cond char *U_WMR49_set(void){ return U_WMRCORENONE_set("U_WMR49"); } char *U_WMR4A_set(void){ return U_WMRCORENONE_set("U_WMR4A"); } char *U_WMR4B_set(void){ return U_WMRCORENONE_set("U_WMR4B"); } char *U_WMR4C_set(void){ return U_WMRCORENONE_set("U_WMRRESETDOC"); } char *U_WMR4D_set(void){ return U_WMRCORENONE_set("U_WMRSTARTDOC"); } char *U_WMR4E_set(void){ return U_WMRCORENONE_set("U_WMR4E"); } char *U_WMR4F_set(void){ return U_WMRCORENONE_set("U_WMRSTARTPAGE"); } char *U_WMR50_set(void){ return U_WMRCORENONE_set("U_WMRENDPAGE"); } char *U_WMR51_set(void){ return U_WMRCORENONE_set("U_WMR51"); } char *U_WMRABORTDOC_set(void){ return U_WMRCORENONE_set("U_WMRABORTDOC"); } char *U_WMR53_set(void){ return U_WMRCORENONE_set("U_WMR53"); } char *U_WMR54_set(void){ return U_WMRCORENONE_set("U_WMR54"); } char *U_WMR55_set(void){ return U_WMRCORENONE_set("U_WMR55"); } char *U_WMR56_set(void){ return U_WMRCORENONE_set("U_WMR56"); } char *U_WMR57_set(void){ return U_WMRCORENONE_set("U_WMR57"); } char *U_WMR58_set(void){ return U_WMRCORENONE_set("U_WMR58"); } char *U_WMR59_set(void){ return U_WMRCORENONE_set("U_WMR59"); } char *U_WMR5A_set(void){ return U_WMRCORENONE_set("U_WMR5A"); } char *U_WMR5B_set(void){ return U_WMRCORENONE_set("U_WMR5B"); } char *U_WMR5C_set(void){ return U_WMRCORENONE_set("U_WMR5C"); } char *U_WMR5D_set(void){ return U_WMRCORENONE_set("U_WMR5D"); } char *U_WMR5E_set(void){ return U_WMRCORENONE_set("U_WMRENDDOC"); } char *U_WMR5F_set(void){ return U_WMRCORENONE_set("U_WMR5F"); } char *U_WMR60_set(void){ return U_WMRCORENONE_set("U_WMR60"); } char *U_WMR61_set(void){ return U_WMRCORENONE_set("U_WMR61"); } char *U_WMR62_set(void){ return U_WMRCORENONE_set("U_WMR62"); } char *U_WMR63_set(void){ return U_WMRCORENONE_set("U_WMR63"); } char *U_WMR64_set(void){ return U_WMRCORENONE_set("U_WMR64"); } char *U_WMR65_set(void){ return U_WMRCORENONE_set("U_WMR65"); } char *U_WMR66_set(void){ return U_WMRCORENONE_set("U_WMR66"); } char *U_WMR67_set(void){ return U_WMRCORENONE_set("U_WMR67"); } char *U_WMR68_set(void){ return U_WMRCORENONE_set("U_WMR68"); } char *U_WMR69_set(void){ return U_WMRCORENONE_set("U_WMR69"); } char *U_WMR6A_set(void){ return U_WMRCORENONE_set("U_WMR6A"); } char *U_WMR6B_set(void){ return U_WMRCORENONE_set("U_WMR6B"); } char *U_WMR6C_set(void){ return U_WMRCORENONE_set("U_WMR6C"); } char *U_WMR6D_set(void){ return U_WMRCORENONE_set("U_WMR6D"); } char *U_WMR6E_set(void){ return U_WMRCORENONE_set("U_WMR6E"); } char *U_WMR6F_set(void){ return U_WMRCORENONE_set("U_WMR6F"); } char *U_WMR70_set(void){ return U_WMRCORENONE_set("U_WMR70"); } char *U_WMR71_set(void){ return U_WMRCORENONE_set("U_WMR71"); } char *U_WMR72_set(void){ return U_WMRCORENONE_set("U_WMR72"); } char *U_WMR73_set(void){ return U_WMRCORENONE_set("U_WMR73"); } char *U_WMR74_set(void){ return U_WMRCORENONE_set("U_WMR74"); } char *U_WMR75_set(void){ return U_WMRCORENONE_set("U_WMR75"); } char *U_WMR76_set(void){ return U_WMRCORENONE_set("U_WMR76"); } char *U_WMR77_set(void){ return U_WMRCORENONE_set("U_WMR77"); } char *U_WMR78_set(void){ return U_WMRCORENONE_set("U_WMR78"); } char *U_WMR79_set(void){ return U_WMRCORENONE_set("U_WMR79"); } char *U_WMR7A_set(void){ return U_WMRCORENONE_set("U_WMR7A"); } char *U_WMR7B_set(void){ return U_WMRCORENONE_set("U_WMR7B"); } char *U_WMR7C_set(void){ return U_WMRCORENONE_set("U_WMR7C"); } char *U_WMR7D_set(void){ return U_WMRCORENONE_set("U_WMR7D"); } char *U_WMR7E_set(void){ return U_WMRCORENONE_set("U_WMR7E"); } char *U_WMR7F_set(void){ return U_WMRCORENONE_set("U_WMR7F"); } char *U_WMR80_set(void){ return U_WMRCORENONE_set("U_WMR80"); } char *U_WMR81_set(void){ return U_WMRCORENONE_set("U_WMR81"); } char *U_WMR82_set(void){ return U_WMRCORENONE_set("U_WMR82"); } char *U_WMR83_set(void){ return U_WMRCORENONE_set("U_WMR83"); } char *U_WMR84_set(void){ return U_WMRCORENONE_set("U_WMR84"); } char *U_WMR85_set(void){ return U_WMRCORENONE_set("U_WMR85"); } char *U_WMR86_set(void){ return U_WMRCORENONE_set("U_WMR86"); } char *U_WMR87_set(void){ return U_WMRCORENONE_set("U_WMR87"); } char *U_WMR88_set(void){ return U_WMRCORENONE_set("U_WMR88"); } char *U_WMR89_set(void){ return U_WMRCORENONE_set("U_WMR89"); } char *U_WMR8A_set(void){ return U_WMRCORENONE_set("U_WMR8A"); } char *U_WMR8B_set(void){ return U_WMRCORENONE_set("U_WMR8B"); } char *U_WMR8C_set(void){ return U_WMRCORENONE_set("U_WMR8C"); } char *U_WMR8D_set(void){ return U_WMRCORENONE_set("U_WMR8D"); } char *U_WMR8E_set(void){ return U_WMRCORENONE_set("U_WMR8E"); } char *U_WMR8F_set(void){ return U_WMRCORENONE_set("U_WMR8F"); } char *U_WMR90_set(void){ return U_WMRCORENONE_set("U_WMR90"); } char *U_WMR91_set(void){ return U_WMRCORENONE_set("U_WMR91"); } char *U_WMR92_set(void){ return U_WMRCORENONE_set("U_WMR92"); } char *U_WMR93_set(void){ return U_WMRCORENONE_set("U_WMR93"); } char *U_WMR94_set(void){ return U_WMRCORENONE_set("U_WMR94"); } char *U_WMR95_set(void){ return U_WMRCORENONE_set("U_WMR95"); } char *U_WMR96_set(void){ return U_WMRCORENONE_set("U_WMR96"); } char *U_WMR97_set(void){ return U_WMRCORENONE_set("U_WMR97"); } char *U_WMR98_set(void){ return U_WMRCORENONE_set("U_WMR98"); } char *U_WMR99_set(void){ return U_WMRCORENONE_set("U_WMR99"); } char *U_WMR9A_set(void){ return U_WMRCORENONE_set("U_WMR9A"); } char *U_WMR9B_set(void){ return U_WMRCORENONE_set("U_WMR9B"); } char *U_WMR9C_set(void){ return U_WMRCORENONE_set("U_WMR9C"); } char *U_WMR9D_set(void){ return U_WMRCORENONE_set("U_WMR9D"); } char *U_WMR9E_set(void){ return U_WMRCORENONE_set("U_WMR9E"); } char *U_WMR9F_set(void){ return U_WMRCORENONE_set("U_WMR9F"); } char *U_WMRA0_set(void){ return U_WMRCORENONE_set("U_WMRA0"); } char *U_WMRA1_set(void){ return U_WMRCORENONE_set("U_WMRA1"); } char *U_WMRA2_set(void){ return U_WMRCORENONE_set("U_WMRA2"); } char *U_WMRA3_set(void){ return U_WMRCORENONE_set("U_WMRA3"); } char *U_WMRA4_set(void){ return U_WMRCORENONE_set("U_WMRA4"); } char *U_WMRA5_set(void){ return U_WMRCORENONE_set("U_WMRA5"); } char *U_WMRA6_set(void){ return U_WMRCORENONE_set("U_WMRA6"); } char *U_WMRA7_set(void){ return U_WMRCORENONE_set("U_WMRA7"); } char *U_WMRA8_set(void){ return U_WMRCORENONE_set("U_WMRA8"); } char *U_WMRA9_set(void){ return U_WMRCORENONE_set("U_WMRA9"); } char *U_WMRAA_set(void){ return U_WMRCORENONE_set("U_WMRAA"); } char *U_WMRAB_set(void){ return U_WMRCORENONE_set("U_WMRAB"); } char *U_WMRAC_set(void){ return U_WMRCORENONE_set("U_WMRAC"); } char *U_WMRAD_set(void){ return U_WMRCORENONE_set("U_WMRAD"); } char *U_WMRAE_set(void){ return U_WMRCORENONE_set("U_WMRAE"); } char *U_WMRAF_set(void){ return U_WMRCORENONE_set("U_WMRAF"); } char *U_WMRB0_set(void){ return U_WMRCORENONE_set("U_WMRB0"); } char *U_WMRB1_set(void){ return U_WMRCORENONE_set("U_WMRB1"); } char *U_WMRB2_set(void){ return U_WMRCORENONE_set("U_WMRB2"); } char *U_WMRB3_set(void){ return U_WMRCORENONE_set("U_WMRB3"); } char *U_WMRB4_set(void){ return U_WMRCORENONE_set("U_WMRB4"); } char *U_WMRB5_set(void){ return U_WMRCORENONE_set("U_WMRB5"); } char *U_WMRB6_set(void){ return U_WMRCORENONE_set("U_WMRB6"); } char *U_WMRB7_set(void){ return U_WMRCORENONE_set("U_WMRB7"); } char *U_WMRB8_set(void){ return U_WMRCORENONE_set("U_WMRB8"); } char *U_WMRB9_set(void){ return U_WMRCORENONE_set("U_WMRB9"); } char *U_WMRBA_set(void){ return U_WMRCORENONE_set("U_WMRBA"); } char *U_WMRBB_set(void){ return U_WMRCORENONE_set("U_WMRBB"); } char *U_WMRBC_set(void){ return U_WMRCORENONE_set("U_WMRBC"); } char *U_WMRBD_set(void){ return U_WMRCORENONE_set("U_WMRBD"); } char *U_WMRBE_set(void){ return U_WMRCORENONE_set("U_WMRBE"); } char *U_WMRBF_set(void){ return U_WMRCORENONE_set("U_WMRBF"); } char *U_WMRC0_set(void){ return U_WMRCORENONE_set("U_WMRC0"); } char *U_WMRC1_set(void){ return U_WMRCORENONE_set("U_WMRC1"); } char *U_WMRC2_set(void){ return U_WMRCORENONE_set("U_WMRC2"); } char *U_WMRC3_set(void){ return U_WMRCORENONE_set("U_WMRC3"); } char *U_WMRC4_set(void){ return U_WMRCORENONE_set("U_WMRC4"); } char *U_WMRC5_set(void){ return U_WMRCORENONE_set("U_WMRC5"); } char *U_WMRC6_set(void){ return U_WMRCORENONE_set("U_WMRC6"); } char *U_WMRC7_set(void){ return U_WMRCORENONE_set("U_WMRC7"); } char *U_WMRC8_set(void){ return U_WMRCORENONE_set("U_WMRC8"); } char *U_WMRC9_set(void){ return U_WMRCORENONE_set("U_WMRC9"); } char *U_WMRCA_set(void){ return U_WMRCORENONE_set("U_WMRCA"); } char *U_WMRCB_set(void){ return U_WMRCORENONE_set("U_WMRCB"); } char *U_WMRCC_set(void){ return U_WMRCORENONE_set("U_WMRCC"); } char *U_WMRCD_set(void){ return U_WMRCORENONE_set("U_WMRCD"); } char *U_WMRCE_set(void){ return U_WMRCORENONE_set("U_WMRCE"); } char *U_WMRCF_set(void){ return U_WMRCORENONE_set("U_WMRCF"); } char *U_WMRD0_set(void){ return U_WMRCORENONE_set("U_WMRD0"); } char *U_WMRD1_set(void){ return U_WMRCORENONE_set("U_WMRD1"); } char *U_WMRD2_set(void){ return U_WMRCORENONE_set("U_WMRD2"); } char *U_WMRD3_set(void){ return U_WMRCORENONE_set("U_WMRD3"); } char *U_WMRD4_set(void){ return U_WMRCORENONE_set("U_WMRD4"); } char *U_WMRD5_set(void){ return U_WMRCORENONE_set("U_WMRD5"); } char *U_WMRD6_set(void){ return U_WMRCORENONE_set("U_WMRD6"); } char *U_WMRD7_set(void){ return U_WMRCORENONE_set("U_WMRD7"); } char *U_WMRD8_set(void){ return U_WMRCORENONE_set("U_WMRD8"); } char *U_WMRD9_set(void){ return U_WMRCORENONE_set("U_WMRD9"); } char *U_WMRDA_set(void){ return U_WMRCORENONE_set("U_WMRDA"); } char *U_WMRDB_set(void){ return U_WMRCORENONE_set("U_WMRDB"); } char *U_WMRDC_set(void){ return U_WMRCORENONE_set("U_WMRDC"); } char *U_WMRDD_set(void){ return U_WMRCORENONE_set("U_WMRDD"); } char *U_WMRDE_set(void){ return U_WMRCORENONE_set("U_WMRDE"); } char *U_WMRDF_set(void){ return U_WMRCORENONE_set("U_WMRDF"); } char *U_WMRE0_set(void){ return U_WMRCORENONE_set("U_WMRE0"); } char *U_WMRE1_set(void){ return U_WMRCORENONE_set("U_WMRE1"); } char *U_WMRE2_set(void){ return U_WMRCORENONE_set("U_WMRE2"); } char *U_WMRE3_set(void){ return U_WMRCORENONE_set("U_WMRE3"); } char *U_WMRE4_set(void){ return U_WMRCORENONE_set("U_WMRE4"); } char *U_WMRE5_set(void){ return U_WMRCORENONE_set("U_WMRE5"); } char *U_WMRE6_set(void){ return U_WMRCORENONE_set("U_WMRE6"); } char *U_WMRE7_set(void){ return U_WMRCORENONE_set("U_WMRE7"); } char *U_WMRE8_set(void){ return U_WMRCORENONE_set("U_WMRE8"); } char *U_WMRE9_set(void){ return U_WMRCORENONE_set("U_WMRE9"); } char *U_WMREA_set(void){ return U_WMRCORENONE_set("U_WMREA"); } char *U_WMREB_set(void){ return U_WMRCORENONE_set("U_WMREB"); } char *U_WMREC_set(void){ return U_WMRCORENONE_set("U_WMREC"); } char *U_WMRED_set(void){ return U_WMRCORENONE_set("U_WMRED"); } char *U_WMREE_set(void){ return U_WMRCORENONE_set("U_WMREE"); } char *U_WMREF_set(void){ return U_WMRCORENONE_set("U_WMREF"); } //! \endcond /** \brief Create and return a U_WMRDELETEOBJECT record \return pointer to the U_WMRDELETEOBJECT record, or NULL on error \param object Index of object to delete. */ char *U_WMRDELETEOBJECT_set(uint16_t object){ return U_WMRCORE_1U16_set(U_WMR_DELETEOBJECT, object); } //! \cond char *U_WMRF1_set(void){ return U_WMRCORENONE_set("U_WMRF1"); } char *U_WMRF2_set(void){ return U_WMRCORENONE_set("U_WMRF2"); } char *U_WMRF3_set(void){ return U_WMRCORENONE_set("U_WMRF3"); } char *U_WMRF4_set(void){ return U_WMRCORENONE_set("U_WMRF4"); } char *U_WMRF5_set(void){ return U_WMRCORENONE_set("U_WMRF5"); } char *U_WMRF6_set(void){ return U_WMRCORENONE_set("U_WMRF6"); } //! \endcond /** \brief Create and return a U_WMRCREATEPALETTE record \return pointer to the U_WMRCREATEPALETTE record, or NULL on error \param Palette Create a Palette object. */ char *U_WMRCREATEPALETTE_set(U_PALETTE *Palette){ return U_WMRCORE_PALETTE_set(U_WMR_CREATEPALETTE, Palette); } //! \cond char *U_WMRF8_set(void){ return U_WMRCORENONE_set("U_WMRF8"); } //! \endcond /** \brief Allocate and construct a U_WMRCREATEPATTERNBRUSH record. WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - use U_WMRDIBCREATEPATTERNBRUSH instead. \return pointer to the U_WMRCREATEPATTERNBRUSH record, or NULL on error. \param Bm16 Pointer to a Bitmap16 Object, only the first 10 bytes are used. \param Pattern byte array pattern, described by Bm16, for brush */ char *U_WMRCREATEPATTERNBRUSH_set( U_BITMAP16 *Bm16, char *Pattern ){ char *record; uint32_t irecsize,off,cbPat; if(!Bm16 || !Pattern)return(NULL); cbPat = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; irecsize = U_SIZE_METARECORD + 14 + 18 + cbPat; /* core WMR + truncated Bm16 + 18 spaces bytes + pattern */ record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEPATTERNBRUSH); off = U_SIZE_METARECORD; memcpy(record + off, Bm16, 14); off+=14; /* Truncated bitmap16 object, last 4 bytes are to be ignored*/ memset(record + off, 0, 18); off+=18; /* 18 bytes of zero, which are ignored */ memcpy(record + off, Pattern, cbPat); /* The pattern array */ } return(record); } /** \brief Allocate and construct a U_WMRCREATEPENINDIRECT record. \return pointer to the U_WMRCREATEPENINDIRECT record, or NULL on error. \param pen Parameters of the pen object to create. */ char *U_WMRCREATEPENINDIRECT_set(U_PEN pen){ return U_WMRCORE_2U16_N16_set(U_WMR_CREATEPENINDIRECT, NULL, NULL, U_SIZE_PEN/2, &pen); } /** \brief Allocate and construct a U_WMRCREATEFONTINDIRECT record. \return pointer to the U_WMRCREATEFONTINDIRECT record, or NULL on error. \param font Parameters of the font object to create. */ char *U_WMRCREATEFONTINDIRECT_set(U_FONT *font){ char *record=NULL; uint32_t irecsize,off,flen; flen = 1 + strlen((char *)font->FaceName); /* include the null terminator in the count */ if(flen & 1) flen++; /* make the allocation end line up at an even byte */ irecsize = U_SIZE_METARECORD + U_SIZE_FONT_CORE + flen; record = calloc(1,irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEFONTINDIRECT); off = U_SIZE_METARECORD; memcpy(record+off,font,U_SIZE_FONT_CORE + flen); } return(record); } /** \brief Allocate and construct a U_WMRCREATEBRUSHINDIRECT record. \return pointer to the U_WMRCREATEBRUSHINDIRECT record, or NULL on error. \param brush Parameters of the brush object to create. */ char *U_WMRCREATEBRUSHINDIRECT_set(U_WLOGBRUSH brush){ return U_WMRCORE_2U16_N16_set(U_WMR_CREATEBRUSHINDIRECT, NULL, NULL, U_SIZE_WLOGBRUSH/2, &brush); } /** in GDI and Wine, not in WMF manual. */ char *U_WMRCREATEBITMAPINDIRECT_set(void){ return U_WMRCORENONE_set("U_WMRCREATEBITMAPINDIRECT"); } /** in GDI and Wine, not in WMF manual. */ char *U_WMRCREATEBITMAP_set(void){ return U_WMRCORENONE_set("U_WMRCREATEBITMAP"); } /** \brief Allocate and construct a U_WMRCREATEREGION record. \return pointer to the U_WMRCREATEREGION record, or NULL on error. \param region Parameters of the region object to create. */ char *U_WMRCREATEREGION_set(const U_REGION *region){ char *record=NULL; uint32_t irecsize,off; irecsize = U_SIZE_METARECORD + region->Size; record = malloc(irecsize); if(record){ U_WMRCORE_SETRECHEAD(record,irecsize,U_WMR_CREATEREGION); off = U_SIZE_METARECORD; memcpy(record+off,region,region->Size); } return(record); } /* all of the *_set are above, all of the *_get are below */ /* ********************************************************************************************** These functions are used for Image conversions and other utility operations. Character type conversions are in uwmf_utf.c *********************************************************************************************** */ /** \brief Make up an approximate dx array to pass to U_WMREXTTEXTOUT_get(), based on character height and weight. Take abs. value of character height, get width by multiplying by 0.6, and correct weight approximately, with formula (measured on screen for one text line of Arial). Caller is responsible for free() on the returned pointer. \return pointer to dx array \param height character height (absolute value will be used) \param weight LF_Weight Enumeration (character weight) \param members Number of entries to put into dx */ int16_t *dx16_get( int32_t height, uint32_t weight, uint32_t members ){ uint32_t i, width; int16_t *dx; dx = (int16_t *) malloc(members * sizeof(int16_t)); if(dx){ if(U_FW_DONTCARE == weight)weight=U_FW_NORMAL; width = (uint32_t) U_ROUND(((float) (height > 0 ? height : -height)) * 0.6 * (0.00024*(float) weight + 0.904)); for ( i = 0; i < members; i++ ){ dx[i] = (width > INT16_MAX ? INT16_MAX : width); } } return(dx); } /** \brief Return the size of a WMF record, or 0 if it is found to be invalid. A valid record will have a size that does not cause it to extend beyond the end of data in memory. A valid record will not be smaller than the smallest possible WMF record. \return size of the record in bytes, 0 on failure \param contents record to extract data from \param blimit one byte past the last WMF record in memory. */ size_t U_WMRRECSAFE_get( const char *contents, const char *blimit ){ size_t size=0; uint32_t Size16; memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4), 4); size = 2*Size16; /* Record is not self consistent - described size past the end of WMF in memory */ if(size < U_SIZE_METARECORD || IS_MEM_UNSAFE(contents, size, blimit))size=0; return(size); } /* ********************************************************************************************** These functions create standard structures used in the WMR records. *********************************************************************************************** */ // hide these from Doxygen //! \cond /* ********************************************************************************************** These functions contain shared code used by various U_WMR*_get functions. These should NEVER be called by end user code and to further that end prototypes are NOT provided and they are hidden from Doxygen. *********************************************************************************************** */ int U_WMRCORENONE_get(char *string){ printf("unimplemented creator for:%s\n",string); return(0); } /* Returns the record size in bytes for a valid record, or 0 for an invalid record. A valid record's size is at least as large as the minimum size passed in through minsize. Use U_WMRRECSAFE_get() to check if the record extends too far in memory. */ int U_WMRCORE_RECSAFE_get( const char *contents, int minsize ){ int size=0; uint32_t Size16; memcpy(&Size16, contents + offsetof(U_METARECORD,Size16_4),4); size = 2*Size16; if(size < minsize)size=0; return(size); } /* records like U_WMRFLOODFILL and others. all args are optional, Color is not */ int U_WMRCORE_1U16_CRF_2U16_get( const char *contents, uint16_t *arg1, U_COLORREF *Color, uint16_t *arg2, uint16_t *arg3 ){ int size = 0; int off = U_SIZE_METARECORD; if(arg1){ memcpy(arg1, contents + off, 2); off+=2; size+=2;} memcpy(Color, contents + off, 4); off+=4; size+=4; if(arg2){ memcpy(arg2, contents + off, 2); off+=2; size+=2;} if(arg3){ memcpy(arg3, contents + off, 2); size+=2;} return(size); } /* records that have a single uint16_t argument like U_WMRSETMAPMODE May also be used with int16_t with appropriate casts */ int U_WMRCORE_1U16_get( const char *contents, int minsize, uint16_t *arg1 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); memcpy(arg1, contents + off, 2); return(size); } /* records that have two uint16_t arguments like U_WMRSETBKMODE May also be used with int16_t with appropriate casts */ int U_WMRCORE_2U16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; memcpy(arg1, contents + off, 2); off+=2; memcpy(arg2, contents + off, 2); return(size); } /* records that have four uint16_t arguments like U_WMRSCALEWINDOWEXT May also be used with int16_t with appropriate casts */ int U_WMRCORE_4U16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3, uint16_t *arg4 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); memcpy(arg1, contents + off, 2); off+=2; memcpy(arg2, contents + off, 2); off+=2; memcpy(arg3, contents + off, 2); off+=2; memcpy(arg4, contents + off, 2); return(size); } /* records that have five uint16_t arguments like U_WMRCREATEPENINDIRECT May also be used with int16_t with appropriate casts */ int U_WMRCORE_5U16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3, uint16_t *arg4, uint16_t *arg5 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); memcpy(arg1, contents + off, 2); off+=2; memcpy(arg2, contents + off, 2); off+=2; memcpy(arg3, contents + off, 2); off+=2; memcpy(arg4, contents + off, 2); off+=2; memcpy(arg5, contents + off, 2); return(size); } /* records that have six uint16_t arguments like U_ROUNDREC May also be used with int16_t with appropriate casts */ int U_WMRCORE_6U16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3, uint16_t *arg4, uint16_t *arg5, uint16_t *arg6 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); memcpy(arg1, contents + off, 2); off+=2; memcpy(arg2, contents + off, 2); off+=2; memcpy(arg3, contents + off, 2); off+=2; memcpy(arg4, contents + off, 2); off+=2; memcpy(arg5, contents + off, 2); off+=2; memcpy(arg6, contents + off, 2); return(size); } /* records that have eight uint16_t arguments like U_WMRARC May also be used with int16_t with appropriate casts */ int U_WMRCORE_8U16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3, uint16_t *arg4, uint16_t *arg5, uint16_t *arg6, uint16_t *arg7, uint16_t *arg8 ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); memcpy(arg1, contents + off, 2); off+=2; memcpy(arg2, contents + off, 2); off+=2; memcpy(arg3, contents + off, 2); off+=2; memcpy(arg4, contents + off, 2); off+=2; memcpy(arg5, contents + off, 2); off+=2; memcpy(arg6, contents + off, 2); off+=2; memcpy(arg7, contents + off, 2); off+=2; memcpy(arg8, contents + off, 2); return(size); } /* records that have arg1 an (optional) (u)int16 arg2 an (optional( (u)int16 array of data cells or just a bunch of data. Passed as a char because the structures in the WMF in memory may not be aligned properly for those structures. Caller has to take them apart - carefully. like U_WMRCREATEBRUSHINDIRECT with arg1=arg2=NULL */ int U_WMRCORE_2U16_N16_get( const char *contents, int minsize, uint16_t *arg1, uint16_t *arg2, const char **array ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); int off = U_SIZE_METARECORD; if(!size)return(0); if(arg1){ memcpy(arg1, contents + off, 2); off+=2; } if(arg2){ memcpy(arg2, contents + off, 2); off+=2; } *array = (contents + off); return(size); } /* records that get a U_PALETTE like U_WMRANIMATEPALETTE. Fills in the first two fields of U_PALETTE only, and returns returns a separateepointer to the PalEntries[] array. This pointer is most likely not aligned with the data. */ int U_WMRCORE_PALETTE_get( const char *contents, int minsize, U_PALETTE *Palette, const char **PalEntries ){ int size = U_WMRCORE_RECSAFE_get(contents, minsize); if(!size)return(0); contents += offsetof(U_WMRANIMATEPALETTE, Palette); memset(Palette, 0, (U_SIZE_PALETTE)); memcpy(Palette, contents, (U_SIZE_PALETTE)); *PalEntries = (contents + offsetof(U_PALETTE, PalEntries)); return(size); } //! \endcond /** \brief Return parameters from a bitmapcoreheader. All are returned as 32 bit integers, regardless of their internal representation. \param BmiCh char * pointer to a U_BITMAPCOREHEADER. Note, data may not be properly aligned. \param Size size of the coreheader in bytes \param Width; Width of pixel array \param Height; Height of pixel array \param BitCount Pixel Format (BitCount Enumeration) */ void U_BITMAPCOREHEADER_get( const char *BmiCh, uint32_t *Size, int32_t *Width, int32_t *Height, int32_t *BitCount ){ uint32_t utmp4; uint16_t utmp2; memcpy(&utmp4, BmiCh + offsetof(U_BITMAPCOREHEADER,Size_4), 4); *Size = utmp4; memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Width), 2); *Width = utmp2; memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,Height), 2); *Height = utmp2; memcpy(&utmp2, BmiCh + offsetof(U_BITMAPCOREHEADER,BitCount), 2); *BitCount = utmp2; } /** \brief Return parameters from a bitinfoheader. All are returned as 32 bit integers, regardless of their internal representation. \param Bmih char * pointer to a U_BITMAPINFOHEADER. Note, data may not be properly aligned. \param Size Structure size in bytes \param Width Bitmap width in pixels \param Height Bitmap height in pixels, may be negative. \param Planes Planes (must be 1) \param BitCount BitCount Enumeration (determines number of RBG colors) \param Compression BI_Compression Enumeration \param SizeImage Image size in bytes or 0 = "default size (calculated from geometry?)" \param XPelsPerMeter X Resolution in pixels/meter \param YPelsPerMeter Y Resolution in pixels/meter \param ClrUsed Number of bmciColors in U_BITMAPINFO/U_BITMAPCOREINFO that are used by the bitmap \param ClrImportant Number of bmciColors needed (0 means all). */ void U_BITMAPINFOHEADER_get( const char *Bmih, uint32_t *Size, int32_t *Width, int32_t *Height, uint32_t *Planes, uint32_t *BitCount, uint32_t *Compression, uint32_t *SizeImage, int32_t *XPelsPerMeter, int32_t *YPelsPerMeter, uint32_t *ClrUsed, uint32_t *ClrImportant ){ int32_t tmp4; uint32_t utmp4; uint16_t utmp2; memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSize ), 4); *Size = utmp4; memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biWidth ), 4); *Width = tmp4; memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biHeight ), 4); *Height = tmp4; memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biPlanes ), 2); *Planes = utmp2; memcpy(&utmp2, Bmih + offsetof(U_BITMAPINFOHEADER,biBitCount ), 2); *BitCount = utmp2; memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biCompression ), 4); *Compression = utmp4; memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biSizeImage ), 4); *SizeImage = utmp4; memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biXPelsPerMeter), 4); *XPelsPerMeter = tmp4; memcpy( &tmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biYPelsPerMeter), 4); *YPelsPerMeter = tmp4; memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrUsed ), 4); *ClrUsed = utmp4; memcpy(&utmp4, Bmih + offsetof(U_BITMAPINFOHEADER,biClrImportant ), 4); *ClrImportant = utmp4; } /** \brief Assume a packed DIB and get the parameters from it, use by DBI_to_RGBA() \return BI_Compression Enumeration. For anything other than U_BI_RGB values other than px may not be valid. \param dib pointer to the start of the DIB in the record \param px pointer to DIB pixel array \param ct pointer to DIB color table \param numCt DIB color table number of entries, for PNG or JPG returns the number of bytes in the image \param width Width of pixel array \param height Height of pixel array (always returned as a positive number) \param colortype DIB BitCount Enumeration \param invert If DIB rows are in opposite order from RGBA rows */ int wget_DIB_params( const char *dib, const char **px, const U_RGBQUAD **ct, uint32_t *numCt, int32_t *width, int32_t *height, int32_t *colortype, int32_t *invert ){ uint32_t bic; uint32_t Size; bic = U_BI_RGB; // this information is not in the coreheader; U_BITMAPCOREHEADER_get(dib, &Size, width, height, colortype); if(Size != 0xC ){ //BitmapCoreHeader /* if biCompression is not U_BI_RGB some or all of the following might not hold real values. Ignore most of the information returned from the bitmapinfoheader. */ uint32_t uig4; int32_t ig4; U_BITMAPINFOHEADER_get(dib, &uig4, width, height,&uig4, (uint32_t *) colortype, &bic, &uig4, &ig4, &ig4, &uig4, &uig4); } if(*height < 0){ *height = -*height; *invert = 1; } else { *invert = 0; } *px = dib + U_SIZE_BITMAPINFOHEADER; if(bic == U_BI_RGB){ *numCt = get_real_color_count(dib); if(*numCt){ *ct = (U_RGBQUAD *) (dib + U_SIZE_BITMAPINFOHEADER); *px += U_SIZE_COLORREF * (*numCt); } else { *ct = NULL; } } else { memcpy(numCt, dib + offsetof(U_BITMAPINFOHEADER,biSizeImage), 4); *ct = NULL; } return(bic); } /* ********************************************************************************************** These are the core WMR functions, each extracts data from a particular type of record. In general routines fill in structures which have been passed in by the caller, and zero them if that (optional) structure is not present. Because the WMF records may not be aligned they are generally copied into the supplied aligned structs, so that the caller may retrieve fields with the usual sorts of structure operations: Struct.field or (*Struct)->field. A few routines return pointers to data regions in the record. They are listed in order by the corresponding U_WMR_* index number. *********************************************************************************************** */ /** \brief Get data from a (placeable) WMR_HEADER. \return size of the record in bytes, 0 on failure \param contents record to extract data from \param blimit one byte past the last WMF record in memory. \param Placeable U_WMRPLACEABLE data, if any \param Header U_WMRHEADER data, if any */ int wmfheader_get( const char *contents, const char *blimit, U_WMRPLACEABLE *Placeable, U_WMRHEADER *Header ){ uint32_t Key; int size=0; if(!contents || !Placeable || !Header || !blimit)return(0); if(IS_MEM_UNSAFE(contents, 4, blimit))return(0); memcpy(&Key, contents + offsetof(U_WMRPLACEABLE,Key), 4); if(Key == 0x9AC6CDD7){ size += U_SIZE_WMRPLACEABLE; if(IS_MEM_UNSAFE(contents, size, blimit))return(0); memcpy(Placeable, contents, U_SIZE_WMRPLACEABLE); contents += U_SIZE_WMRPLACEABLE; } else { memset(Placeable, 0, U_SIZE_WMRPLACEABLE); } if(IS_MEM_UNSAFE(contents, size + U_SIZE_WMRHEADER, blimit))return(0); size += 2* (*(uint16_t *)(contents + offsetof(U_WMRHEADER,Size16w))); if(IS_MEM_UNSAFE(contents, size, blimit))return(0); memcpy(Header, contents, U_SIZE_WMRHEADER); return(size); } /** \brief Get data from a U_WMREOF record \return size of record in bytes, or 0 on error \param contents record to extract data from */ int U_WMREOF_get( const char *contents ){ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREOF))); } /** \brief Retrieve values from a U_WMRSETBKCOLOR record \return length of the U_WMRSETBKCOLOR record, or NULL on error \param contents record to extract data from \param Color Background Color. */ int U_WMRSETBKCOLOR_get( const char *contents, U_COLORREF *Color ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETBKCOLOR)); if(!size)return(0); memcpy(Color,contents + offsetof(U_WMRSETBKCOLOR,Color),U_SIZE_COLORREF); return(size); } /** \brief Retrieve values from a U_WMRSETBKMODE record \return length of the U_WMRSETBKMODE record, or NULL on error \param contents record to extract data from \param Mode MixMode Enumeration */ int U_WMRSETBKMODE_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETBKMODE), Mode)); } /** \brief Retrieve values from a U_WMRSETMAPMODE record \return length of the U_WMRSETMAPMODE record, or NULL on error \param contents record to extract data from \param Mode MapMode Enumeration */ int U_WMRSETMAPMODE_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETMAPMODE), Mode)); } /** \brief Retrieve values from a U_WMRSETROP2 record \return length of the U_WMRSETROP2 record, or NULL on error \param contents record to extract data from \param Mode Binary Raster Operation Enumeration */ int U_WMRSETROP2_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETROP2), Mode)); } /** \brief Get data from a U_WMRSETRELABS record \return length of the U_WMRSETRELABS record in bytes, or 0 on error \param contents record to extract data from */ int U_WMRSETRELABS_get( const char *contents ){ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETRELABS))); } /** \brief Retrieve values from a U_WMRSETPOLYFILLMODE record \return length of the U_WMRSETPOLYFILLMODE record, or NULL on error \param contents record to extract data from \param Mode PolyFillMode Enumeration */ int U_WMRSETPOLYFILLMODE_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETPOLYFILLMODE), Mode)); } /** \brief Retrieve values from a U_WMRSETSTRETCHBLTMODE record \return length of the U_WMRSETSTRETCHBLTMODE record, or NULL on error \param contents record to extract data from \param Mode StretchMode Enumeration */ int U_WMRSETSTRETCHBLTMODE_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETSTRETCHBLTMODE), Mode)); } /** \brief Retrieve values from a U_WMRSETTEXTCHAREXTRA record \return length of the U_WMRSETTEXTCHAREXTRA record, or NULL on error \param contents record to extract data from \param Mode Extra space in logical units to add to each character */ int U_WMRSETTEXTCHAREXTRA_get( const char *contents, uint16_t *Mode ){ return(U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTCHAREXTRA), Mode)); } /** \brief Retrieve values from a U_WMRSETTEXTCOLOR record \return length of the U_WMRSETTEXTCOLOR record, or NULL on error \param contents record to extract data from \param Color Text Color. */ int U_WMRSETTEXTCOLOR_get( const char *contents, U_COLORREF *Color ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETTEXTCOLOR)); if(!size)return(0); memcpy(Color,contents + offsetof(U_WMRSETTEXTCOLOR,Color),U_SIZE_COLORREF); return(size); } /** \brief Retrieve values from a U_WMRSETTEXTJUSTIFICATION record \return length of the U_WMRSETTEXTJUSTIFICATION record, or NULL on error \param contents record to extract data from \param Count Number of space characters in the line. \param Extra Number of extra space characters to add to the line. */ int U_WMRSETTEXTJUSTIFICATION_get( const char *contents, uint16_t *Count, uint16_t *Extra ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETTEXTJUSTIFICATION), Count, Extra)); } /** \brief Retrieve values from a U_WMRSETWINDOWORG record \return length of the U_WMRSETWINDOWORG record, or NULL on error \param contents record to extract data from \param coord Window Origin. */ int U_WMRSETWINDOWORG_get( const char *contents, U_POINT16 * coord ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWORG), U_P16(coord->y), U_P16(coord->x))); } /** \brief Retrieve values from a U_WMRSETWINDOWEXT record \return length of the U_WMRSETWINDOWEXT record, or NULL on error \param contents record to extract data from \param extent Window Extent. */ int U_WMRSETWINDOWEXT_get( const char *contents, U_POINT16 * extent ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETWINDOWEXT), U_P16(extent->y), U_P16(extent->x))); } /** \brief Retrieve values from a U_WMRSETVIEWPORTORG record \return length of the U_WMRSETVIEWPORTORG record, or NULL on error \param contents record to extract data from \param coord Viewport Origin. */ int U_WMRSETVIEWPORTORG_get( const char *contents, U_POINT16 * coord ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTORG), U_P16(coord->y), U_P16(coord->x))); } /** \brief Retrieve values from a U_WMRSETVIEWPORTEXT record \return length of the U_WMRSETVIEWPORTEXT record, or NULL on error \param contents record to extract data from \param extent Viewport Extent. */ int U_WMRSETVIEWPORTEXT_get( const char *contents, U_POINT16 * extent ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRSETVIEWPORTEXT), U_P16(extent->y), U_P16(extent->x))); } /** \brief Retrieve values from a U_WMROFFSETWINDOWORG record \return length of the U_WMROFFSETWINDOWORG record, or NULL on error \param contents record to extract data from \param offset Window offset in device units. */ int U_WMROFFSETWINDOWORG_get( const char *contents, U_POINT16 * offset ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETWINDOWORG), U_P16(offset->y), U_P16(offset->x))); } /** \brief Retrieve values from a U_WMRSCALEWINDOWEXT record \return length of the U_WMRSCALEWINDOWEXT record, or NULL on error \param contents record to extract data from \param Denom {X,Y} denominators. \param Num {X,Y} numerators. */ int U_WMRSCALEWINDOWEXT_get( const char *contents, U_POINT16 * Denom, U_POINT16 * Num ){ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEWINDOWEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x))); } /** \brief Retrieve values from a U_WMROFFSETVIEWPORTORG record \return length of the U_WMROFFSETVIEWPORTORG record, or NULL on error \param contents record to extract data from \param offset Viewport offset in device units. */ int U_WMROFFSETVIEWPORTORG_get( const char *contents, U_POINT16 * offset ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETVIEWPORTORG), U_P16(offset->y), U_P16(offset->x))); } /** \brief Retrieve values from a U_WMRSCALEVIEWPORTEXT record \return length of the U_WMRSCALEVIEWPORTEXT record, or NULL on error \param contents record to extract data from \param Denom {X,Y} denominators. \param Num {X,Y} numerators. */ int U_WMRSCALEVIEWPORTEXT_get( const char *contents, U_POINT16 * Denom, U_POINT16 * Num ){ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRSCALEVIEWPORTEXT), U_P16(Denom->y), U_P16(Denom->x), U_P16(Num->y), U_P16(Num->x))); } /** \brief Retrieve values from a U_WMRLINETO record \return length of the U_WMRLINETO record, or NULL on error \param contents record to extract data from \param coord Draw line to {X,Y}. */ int U_WMRLINETO_get( const char *contents, U_POINT16 * coord ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRLINETO), U_P16(coord->y), U_P16(coord->x))); } /** \brief Retrieve values from a U_WMRMOVETO record \return length of the U_WMRMOVETO record, or NULL on error \param contents record to extract data from \param coord Move to {X,Y}. */ int U_WMRMOVETO_get( const char *contents, U_POINT16 * coord ){ return(U_WMRCORE_2U16_get(contents, (U_SIZE_WMRMOVETO), U_P16(coord->y), U_P16(coord->x))); } /** \brief Retrieve values from a U_WMREXCLUDECLIPRECT record \return length of the U_WMREXCLUDECLIPRECT record, or NULL on error \param contents record to extract data from \param rect Exclude rect from clipping region. */ int U_WMREXCLUDECLIPRECT_get( const char *contents, U_RECT16 *rect ){ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMREXCLUDECLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left))); } /** \brief Retrieve values from a U_WMRINTERSECTCLIPRECT record \return length of the U_WMRINTERSECTCLIPRECT record, or NULL on error \param contents record to extract data from \param rect Clipping region is intersection of existing clipping region with rect. */ int U_WMRINTERSECTCLIPRECT_get( const char *contents, U_RECT16 *rect ){ return(U_WMRCORE_4U16_get(contents, (U_SIZE_WMRINTERSECTCLIPRECT), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left))); } /** \brief Retrieve values from a U_WMRARC record \return length of the U_WMRARC record, or NULL on error \param contents record to extract data from \param StartArc Start of Arc \param EndArc End of Arc \param rect Bounding rectangle. */ int U_WMRARC_get( const char *contents, U_POINT16 *StartArc, U_POINT16 *EndArc, U_RECT16 *rect ){ return U_WMRCORE_8U16_get( contents, (U_SIZE_WMRARC), U_P16(EndArc->y), U_P16(EndArc->x), U_P16(StartArc->y), U_P16(StartArc->x), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Retrieve values from a U_WMRELLIPSE record \return length of the U_WMRELLIPSE record, or NULL on error \param contents record to extract data from \param rect Bounding rectangle for Ellipse. */ int U_WMRELLIPSE_get( const char *contents, U_RECT16 *rect ){ return U_WMRCORE_4U16_get( contents, (U_SIZE_WMRELLIPSE), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Retrieve values from a U_WMRFLOODFILL record \return length of the U_WMRFLOODFILL record, or NULL on error \param contents record to extract data from \param Mode FloodFill Enumeration. \param Color Color to Fill with. \param coord Location to start fill. */ int U_WMRFLOODFILL_get( const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 *coord ){ return U_WMRCORE_1U16_CRF_2U16_get( contents, Mode, Color, U_P16(coord->y), U_P16(coord->x) ); } /** \brief Retrieve values from a U_WMRPIE record \return length of the U_WMRPIE record, or NULL on error \param contents record to extract data from \param Radial1 Start of Pie \param Radial2 End of Pie \param rect Bounding rectangle. */ int U_WMRPIE_get( const char *contents, U_POINT16 *Radial1, U_POINT16 *Radial2, U_RECT16 *rect ){ return U_WMRCORE_8U16_get( contents, (U_SIZE_WMRPIE), U_P16(Radial2->y), U_P16(Radial2->x), U_P16(Radial1->y), U_P16(Radial1->x), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Retrieve values from a U_WMRRECTANGLE record \return length of the U_WMRRECTANGLE record, or NULL on error \param contents record to extract data from \param rect Boundaries. */ int U_WMRRECTANGLE_get( const char *contents, U_RECT16 *rect ){ return U_WMRCORE_4U16_get( contents, (U_SIZE_WMRRECTANGLE), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Retrieve values from a U_WMRROUNDRECT record \return length of the U_WMRROUNDRECT record, or NULL on error \param contents record to extract data from \param Width Horizontal rounding length. \param Height Vertical rounding length. \param rect Boundaries. */ int U_WMRROUNDRECT_get( const char *contents, int16_t *Width, int16_t *Height, U_RECT16 *rect ){ return U_WMRCORE_6U16_get( contents, (U_SIZE_WMRROUNDRECT), U_PP16(Height), U_PP16(Width), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Get data from a U_WMRPATBLT record. \return length of the U_WMRPATBLT record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param cwh W & H for Dst and Src in logical units \param dwRop3 RasterOPeration Enumeration */ int U_WMRPATBLT_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, uint32_t *dwRop3 ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPATBLT)); if(!size)return(0); memcpy(dwRop3, ( contents + offsetof(U_WMRPATBLT, rop3w)), 4); cwh->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRPATBLT, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRPATBLT, xDst )); return(size); } /** \brief Get data from a U_WMRSAVEDC record \return length of the U_WMRSAVEDC record in bytes, or 0 on error \param contents record to extract data from */ int U_WMRSAVEDC_get( const char *contents ){ return(U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSAVEDC))); } /** \brief Get data from a U_WMRSETPIXEL record \return length of the U_WMRSETPIXEL record in bytes, or 0 on error \param contents record to extract data from \param Color pointer to a U_COLORREF variable where the color will be stored. \param Coord pointer to a U_POINT16 variable where the coordinates will be stored. */ int U_WMRSETPIXEL_get( const char *contents, U_COLORREF *Color, U_POINT16 *Coord){ return U_WMRCORE_1U16_CRF_2U16_get( contents, NULL, Color, U_P16(Coord->y), U_P16(Coord->x) ); } /** \brief Get data from a U_WMROFFSETCLIPRGN record \return length of the U_WMROFFSETCLIPRGN record in bytes, or 0 on error \param contents record to extract data from \param offset pointer to a U_POINT16 variable where the x,y offsets will be stored. */ int U_WMROFFSETCLIPRGN_get( const char *contents, U_POINT16 *offset ){ return U_WMRCORE_2U16_get(contents, (U_SIZE_WMROFFSETCLIPRGN), U_P16(offset->y), U_P16(offset->x)); } /** \brief Get data from a U_WMRTEXTOUT record \return length of the U_WMRTEXTOUT record in bytes, or 0 on error \param contents record to extract data from \param Dst coordinates where text will be written \param Length Number of characters in string. \param string Pointer to string in WMF buffer in memory. This text is generally NOT null terminated!!! */ int U_WMRTEXTOUT_get( const char *contents, U_POINT16 * Dst, int16_t *Length, const char **string ){ int16_t L2; int off; int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRTEXTOUT)); if(!size)return(0); *Length = *(int16_t *)(contents + offsetof(U_WMRTEXTOUT, Length)); *string = contents + offsetof(U_WMRTEXTOUT, String); /* May not be null terminated!!! */ L2 = *Length; if(L2 & 1)L2++; off = U_SIZE_METARECORD + 2 + L2; memcpy(&Dst->y, contents + off, 2); off+=2; memcpy(&Dst->x, contents + off, 2); return(size); } /** \brief Get data from a U_WMRBITBLT record. Note that unlike U_EMRBITBLT there is no scaling available - the Src and Dst rectangles must be the same size. \return length of the U_WMRBITBLT record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param cwh W & H for Dst and Src in logical units \param Src Source UL corner in logical units \param dwRop3 RasterOPeration Enumeration \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used) \param px pointer to bitmap in memory, or NULL if not used */ int U_WMRBITBLT_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px ){ uint8_t xb; uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRBITBLT_NOPX)); if(!size)return(0); xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_NOPX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xSrc )); cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_NOPX, xDst )); memset(Bm16, 0, U_SIZE_BITMAP16); *px = NULL; } else { /* yes bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRBITBLT_PX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xSrc )); cwh->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRBITBLT_PX, xDst )); memcpy(Bm16, ( contents + offsetof(U_WMRBITBLT_PX, bitmap)), U_SIZE_BITMAP16); *px = ( contents + offsetof(U_WMRBITBLT_PX, bitmap) + U_SIZE_BITMAP16); } return(size); } /** \brief Get data from a U_WMRSTRETCHBLT record. \return length of the U_WMRSTRETCHBLT record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param dwRop3 RasterOPeration Enumeration \param Bm16 bitmap16 object (fields in it are all 0 if no bitmap is used) \param px pointer to bitmap in memory, or NULL if not used */ int U_WMRSTRETCHBLT_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, U_BITMAP16 *Bm16, const char **px ){ uint8_t xb; uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHBLT_NOPX)); if(!size)return(0); xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_NOPX, rop3w)), 4); cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hSrc )); cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wSrc )); Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xSrc )); cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, hDst )); cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, wDst )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_NOPX, xDst )); memset(Bm16, 0, U_SIZE_BITMAP16); *px = NULL; } else { /* yes bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHBLT_PX, rop3w)), 4); cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hSrc )); cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wSrc )); Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xSrc )); cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, hDst )); cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, wDst )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHBLT_PX, xDst )); memcpy(Bm16, ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap)), U_SIZE_BITMAP16); *px = ( contents + offsetof(U_WMRSTRETCHBLT_PX, bitmap) + U_SIZE_BITMAP16); } return(size); } /** \brief Get data from a U_WMRPOLYGON record. \return length of the U_WMRPOLYGON record in bytes, or 0 on error \param contents record to extract data from \param Length Number of points in the Polygon \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures. */ int U_WMRPOLYGON_get( const char *contents, uint16_t *Length, const char **Data ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); if(size){ int iLength = (*Length)*sizeof(U_POINT16); if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } /** \brief Get data from a U_WMRPOLYLINE record. \return length of the U_WMRPOLYLINE record in bytes, or 0 on error \param contents record to extract data from \param Length Number of points in the Polyline \param Data pointer to array of U_POINT16 in memory. Pointer may not be aligned properly for structures. */ int U_WMRPOLYLINE_get( const char *contents, uint16_t *Length, const char **Data ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRPOLYGON), NULL, Length, Data); if(size){ int iLength = (*Length)*sizeof(U_POINT16); if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } /** \brief Get data from a U_WMRESCAPE record. WARNING! Only three Escape record types are fully supported: SETLINECAP, SETLINEJOIN, SETMITERLIMIT. Even these should not be set here directly, instead use the wsetlinecap_get(), wsetlinejoin_get(), or wsetmiterlimit_get() functions. Escape records created with this function, with the exception of the three named above, will not have the byte orders in Data adjusted automatically. The user code must set Data to be little endian no matter what the endianness of the current platform where the user code is running. \return length of the U_WMRESCAPE record in bytes, or 0 on error \param contents record to extract data from \param Escape Escape function \param Length Bytes in the Data \param Data Array of Length bytes */ int U_WMRESCAPE_get( const char *contents, uint16_t *Escape, uint16_t *Length, const char **Data ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRESCAPE), Escape, Length, Data); if(size){ int iLength=*Length; if(IS_MEM_UNSAFE(*Data, iLength, contents+size))return(0); } return size; } /** \brief Get data from a U_WMRRESTOREDC record \return length of the U_WMRRESTOREDC record in bytes, or 0 on error \param contents record to extract data from \param DC DC to restore (relative if negative, absolute if positive) */ int U_WMRRESTOREDC_get( const char *contents, int16_t *DC ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESTOREDC), (uint16_t *)DC); // signed, but it is just a memcpy, so this works } /** \brief Get data from a U_WMRFILLREGION record. \return length of the U_WMRFILLREGION record in bytes, or 0 on error \param contents record to extract data from \param Region Region to fill \param Brush Brush to fill with */ int U_WMRFILLREGION_get( const char *contents, uint16_t *Region, uint16_t *Brush ){ return U_WMRCORE_2U16_get(contents, (U_SIZE_WMRFILLREGION), Region, Brush); } /** \brief Get data from a U_WMRFRAMEREGION record. \return length of the U_WMRFRAMEREGION record in bytes, or 0 on error \param contents record to extract data from \param Region Index of region to frame in object table \param Brush Index of brush to use in frame in object table \param Height in logical units (of frame) \param Width in logical units (of frame) */ int U_WMRFRAMEREGION_get( const char *contents, uint16_t *Region, uint16_t *Brush, int16_t *Height, int16_t *Width ){ return U_WMRCORE_4U16_get(contents, (U_SIZE_WMRFRAMEREGION), Region, Brush, U_PP16(Height), U_PP16(Width)); } /** \brief Get data from a U_WMRINVERTREGION record. \return length of the U_WMRINVERTREGION record in bytes, or 0 on error \param contents record to extract data from \param Region Index of region to invert. */ int U_WMRINVERTREGION_get( const char *contents, uint16_t *Region ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRINVERTREGION), Region); } /** \brief Get data from a U_WMRPAINTREGION record. \return length of the U_WMRPAINTREGION record in bytes, or 0 on error \param contents record to extract data from \param Region Index of region to paint with the current Brush. */ int U_WMRPAINTREGION_get( const char *contents, uint16_t *Region ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRPAINTREGION), Region); } /** \brief Get data from a U_WMRSELECTCLIPREGION record. \return length of the U_WMRSELECTCLIPREGION record in bytes, or 0 on error \param contents record to extract data from \param Region Index of region to become clipping region.. */ int U_WMRSELECTCLIPREGION_get( const char *contents, uint16_t *Region ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTCLIPREGION), Region); } /** \brief Get data from a U_WMRSELECTOBJECT record. \return length of the U_WMRSELECTOBJECT record in bytes, or 0 on error \param contents record to extract data from \param Object Index of object which is made active. */ int U_WMRSELECTOBJECT_get( const char *contents, uint16_t *Object ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTOBJECT), Object); } /** \brief Get data from a U_WMRSETTEXTALIGN record. \return length of the U_WMRSETTEXTALIGN record in bytes, or 0 on error \param contents record to extract data from \param Mode TextAlignment Enumeration. */ int U_WMRSETTEXTALIGN_get( const char *contents, uint16_t *Mode ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSETTEXTALIGN), Mode); } /** in GDI and Wine, not in WMF manual. */ int U_WMRDRAWTEXT_get(void){ /* in Wine, not in WMF PDF. */ return U_WMRCORENONE_get("U_WMRDRAWTEXT"); } /** \brief Retrieve values from a U_WMRCHORD record \return length of the U_WMRCHORD record, or NULL on error \param contents record to extract data from \param Radial1 Start of Chord \param Radial2 End of Chord \param rect Bounding rectangle. */ int U_WMRCHORD_get( const char *contents, U_POINT16 *Radial1, U_POINT16 *Radial2, U_RECT16 *rect ){ return U_WMRCORE_8U16_get( contents, (U_SIZE_WMRCHORD), U_P16(Radial2->y), U_P16(Radial2->x), U_P16(Radial1->y), U_P16(Radial1->x), U_P16(rect->bottom), U_P16(rect->right), U_P16(rect->top), U_P16(rect->left) ); } /** \brief Get data from a U_WMRSETMAPPERFLAGS record. \return length of the U_WMRSETMAPPERFLAGS record in bytes, or 0 on error \param contents record to extract data from \param Mode If 1 bit set font mapper selects only matching aspect fonts. */ int U_WMRSETMAPPERFLAGS_get( const char *contents, uint32_t *Mode ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETMAPPERFLAGS)); if(!size)return(0); memcpy(Mode, contents + U_SIZE_METARECORD, 4); return(size); } /** \brief Get data from a U_WMREXTTEXTOUT record. \return length of the U_WMREXTTEXTOUT record in bytes, or 0 on error \param contents record to extract data from \param Dst {X,Y} coordinates where the string is to be written. \param Length Stringlength in bytes \param Opts ExtTextOutOptions Flags \param string String to write (Latin1 encoding) \param dx Kerning information. Must have same number of entries as Length. \param rect Used when when U_ETO_OPAQUE or U_ETO_CLIPPED bits are set in Opts */ int U_WMREXTTEXTOUT_get( const char *contents, U_POINT16 * Dst, int16_t *Length, uint16_t *Opts, const char **string, const int16_t **dx, U_RECT16 *rect ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMREXTTEXTOUT)); int off = U_SIZE_METARECORD; if(!size)return(0); Dst->y = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, y )); Dst->x = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, x )); *Length = *(int16_t *)( contents + offsetof(U_WMREXTTEXTOUT, Length )); *Opts = *(uint16_t *)(contents + offsetof(U_WMREXTTEXTOUT, Opts )); off = U_SIZE_WMREXTTEXTOUT; if(*Opts & (U_ETO_OPAQUE | U_ETO_CLIPPED)){ memcpy(rect, (contents + off), U_SIZE_RECT16); off += U_SIZE_RECT16; } else { memset(rect, 0, U_SIZE_RECT16); } *string = (contents + off); off += 2*((*Length +1)/2); if(*Length){ *dx = (int16_t *)(contents + off); } else { *dx = NULL; } return(size); } /** \brief Get data from a U_WMRSETDIBTODEV record \return length of the U_WMRSETDIBTODEV record in bytes, or 0 on error \param contents record to extract data from \param Dst UL corner of Dst rect in logical units \param cwh Width and Height in logical units \param Src UL corner of Src rect in logical units \param cUsage ColorUsage enumeration \param ScanCount Number of scan lines in Src \param StartScan First Scan line in Src \param dib DeviceIndependentBitmap object */ int U_WMRSETDIBTODEV_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint16_t *cUsage, uint16_t *ScanCount, uint16_t *StartScan, const char **dib ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSETDIBTODEV)); if(!size)return(0); *cUsage = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, cUsage )); *ScanCount = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, ScanCount )); *StartScan = *(uint16_t *)(contents + offsetof(U_WMRSETDIBTODEV, StartScan )); Src->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xSrc )); cwh->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRSETDIBTODEV, xDst )); *dib = ( contents + offsetof(U_WMRSETDIBTODEV, dib )); if(!packed_DIB_safe(*dib, *dib+size))return(0); return(size); } /** \brief Get data from a U_WMRSELECTPALETTE record \return length of the U_WMRSELECTPALETTE record in bytes, or 0 on error \param contents record to extract data from \param Palette Index of Palette to make active. */ int U_WMRSELECTPALETTE_get( const char *contents, uint16_t *Palette ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRSELECTPALETTE), Palette); } /** \brief Get data from a U_WMRREALIZEPALETTE record \return length of the U_WMRREALIZEPALETTE record in bytes, or 0 on error \param contents record to extract data from */ int U_WMRREALIZEPALETTE_get( const char *contents ){ return U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRREALIZEPALETTE)); } /** \brief Get data from a U_WMRSETPALENTRIES record \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error \param contents record to extract data from \param Palette Redefines a set of RGB values for the current active Palette. \param PalEntries Array of Palette Entries */ int U_WMRANIMATEPALETTE_get( const char *contents, U_PALETTE *Palette, const char **PalEntries ){ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRANIMATEPALETTE), Palette, PalEntries); } /** \brief Get data from a U_WMRSETPALENTRIES record \return length of the U_WMRSETPALENTRIES record in bytes, or 0 on error \param contents record to extract data from \param Palette Defines a set of RGB values for the current active Palette. \param PalEntries Array of Palette Entries */ int U_WMRSETPALENTRIES_get( const char *contents, U_PALETTE *Palette, const char **PalEntries ){ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRSETPALENTRIES), Palette, PalEntries); } /** \brief Get data from a U_WMR_POLYPOLYGON record. \return length of the U_WMR_POLYPOLYGON record in bytes, or 0 on error \param contents record to extract data from \param nPolys Number of elements in aPolyCounts \param aPolyCounts Number of points in each poly (sequential) \param Points pointer to array of U_POINT16 in memory. Probably not aligned. */ int U_WMRPOLYPOLYGON_get( const char *contents, uint16_t *nPolys, const uint16_t **aPolyCounts, const char **Points ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRPOLYPOLYGON)); if(!size)return(0); contents += offsetof(U_WMRPOLYPOLYGON, PPolygon); memcpy(nPolys, contents + offsetof(U_POLYPOLYGON, nPolys), 2); *aPolyCounts = (uint16_t *)(contents + offsetof(U_POLYPOLYGON, aPolyCounts)); *Points = (contents + offsetof(U_POLYPOLYGON, aPolyCounts) + *nPolys*2); return(size); } /** \brief Get data from a U_WMRRESIZEPALETTE record \return length of the U_WMRRESIZEPALETTE record in bytes, or 0 on error \param contents record to extract data from \param Palette Changes the size of the currently active Palette. */ int U_WMRRESIZEPALETTE_get( const char *contents, uint16_t *Palette ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRRESIZEPALETTE), Palette); } //! \cond int U_WMR3A_get(void){ return U_WMRCORENONE_get("U_WMR3A"); } int U_WMR3B_get(void){ return U_WMRCORENONE_get("U_WMR3B"); } int U_WMR3C_get(void){ return U_WMRCORENONE_get("U_WMR3C"); } int U_WMR3D_get(void){ return U_WMRCORENONE_get("U_WMR3D"); } int U_WMR3E_get(void){ return U_WMRCORENONE_get("U_WMR3E"); } int U_WMR3F_get(void){ return U_WMRCORENONE_get("U_WMR3F"); } //! \endcond // U_WMRDIBBITBLT_get /** \brief Get data from a U_WMRDIBITBLT record. \return length of the U_WMRDIBITBLT record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param Src Source UL corner in logical units \param cwh W & H in logical units of Src and Dst \param dwRop3 RasterOPeration Enumeration \param dib pointer to dib in WMF in memory. Most likely not aligned. */ int U_WMRDIBBITBLT_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cwh, U_POINT16 * Src, uint32_t *dwRop3, const char **dib ){ uint8_t xb; uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBBITBLT_NOPX)); if(!size)return(0); xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_NOPX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xSrc )); cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_NOPX, xDst )); *dib = NULL; } else { /* yes bitmap */ memcpy(dwRop3, ( contents + offsetof(U_WMRDIBBITBLT_PX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xSrc )); cwh->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Height )); cwh->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, Width )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBBITBLT_PX, xDst )); *dib = ( contents + offsetof(U_WMRDIBBITBLT_PX, dib )); if(!packed_DIB_safe(*dib, *dib+size))return(0); } return(size); } /** \brief Get data from a U_WMRSTRETCHDIB record. \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param dwRop3 RasterOPeration Enumeration \param dib pointer to dib in WMF in memory. Most likely not aligned. */ int U_WMRDIBSTRETCHBLT_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint32_t *dwRop3, const char **dib ){ uint8_t xb; uint32_t size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBSTRETCHBLT_NOPX)); if(!size)return(0); xb = *(uint8_t *)( contents + offsetof(U_METARECORD, xb)); if(U_TEST_NOPXB(size,xb)){ /* no bitmap */ memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xSrc )); cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hSrc )); cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wSrc )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, xDst )); cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, hDst )); cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_NOPX, wDst )); *dib = NULL; } else { /* yes bitmap */ memcpy(dwRop3 , ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, rop3w)), 4); Src->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xSrc )); cSrc->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hSrc )); cSrc->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wSrc )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, xDst )); cDst->y = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, hDst )); cDst->x = *(int16_t *)( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, wDst )); *dib = ( contents + offsetof(U_WMRDIBSTRETCHBLT_PX, dib )); if(!packed_DIB_safe(*dib, *dib+size))return(0); } return(size); } /** \brief Get data from a U_WMRDIBCREATEPATTERNBRUSH record. Returns an image as either a DIB (Bmi/CbPx/Px defined) or a Bitmap16 (Bm16 defined). WARNING - U_WMRCREATEPATTERNBRUSH has been declared obsolete and application support is spotty - this function is still valid though, for those instances where old WMF input files are encountered. \return length of the U_WMRDIBCREATEPATTERNBRUSH record in bytes, or 0 on error \param contents record to extract data from \param Style BrushStyle Enumeration \param cUsage DIBcolors Enumeration \param Bm16 pointer to a U_BITMAP16 in WMF in memory. Most likely not aligned. NULL if dib is used instead. \param dib pointer to a dib in WMF in memory. Most likely not aligned. NULL if Bm16 is used instead. */ int U_WMRDIBCREATEPATTERNBRUSH_get( const char *contents, uint16_t *Style, uint16_t *cUsage, const char **Bm16, const char **dib ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRDIBCREATEPATTERNBRUSH)); if(!size)return(0); *Style = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Style )); *cUsage = *(uint16_t *)(contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, cUsage )); if(*Style == U_BS_PATTERN){ *Bm16 = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); *dib = NULL; /* The WMF spec says that Style == U_BS_PATTERN _SHOULD_ be a bitmap16. However there are instances when it is actually a DIB. U_WMRDIBCREATEPATTERNBRUSH_get tries to detect this by looking for bogus values when the BM16 is interpreted as such, and if it finds them, then it returns a dib instead. */ U_BITMAP16 TmpBm16; memcpy(&TmpBm16, *Bm16, U_SIZE_BITMAP16); if(TmpBm16.Width <= 0 || TmpBm16.Height <= 0 || TmpBm16.Planes != 1 || TmpBm16.BitsPixel == 0){ *Bm16 = NULL; *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); if(!packed_DIB_safe(*dib, *dib+size))return(0); } } else { /* from DIB */ *Bm16 = NULL; *dib = (contents + offsetof(U_WMRDIBCREATEPATTERNBRUSH, Src)); if(!packed_DIB_safe(*dib, *dib+size))return(0); } return(size); } /** \brief Get data from a U_WMRSTRETCHDIB record. \return length of the U_WMRSTRETCHDIB record in bytes, or 0 on error \param contents record to extract data from \param Dst Destination UL corner in logical units \param cDst Destination W & H in logical units \param Src Source UL corner in logical units \param cSrc Source W & H in logical units \param cUsage DIBColors Enumeration \param dwRop3 RasterOPeration Enumeration \param dib (Optional) device independent bitmap */ int U_WMRSTRETCHDIB_get( const char *contents, U_POINT16 * Dst, U_POINT16 * cDst, U_POINT16 * Src, U_POINT16 * cSrc, uint16_t *cUsage, uint32_t *dwRop3, const char **dib ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRSTRETCHDIB)); if(!size)return(0); memcpy(dwRop3, ( contents + offsetof(U_WMRSTRETCHDIB, rop3w)), 4); *cUsage = *(uint16_t *)( contents + offsetof(U_WMRSTRETCHDIB, cUsage )); cSrc->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hSrc )); cSrc->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wSrc )); Src->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, ySrc )); Src->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xSrc )); cDst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, hDst )); cDst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, wDst )); Dst->y = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, yDst )); Dst->x = *(int16_t *)( contents + offsetof(U_WMRSTRETCHDIB, xDst )); *dib = ( contents + offsetof(U_WMRSTRETCHDIB, dib )); if(!packed_DIB_safe(*dib, *dib+size))return(0); return(size); } //! \cond int U_WMR44_get(void){ return U_WMRCORENONE_get("U_WMR44"); } int U_WMR45_get(void){ return U_WMRCORENONE_get("U_WMR45"); } int U_WMR46_get(void){ return U_WMRCORENONE_get("U_WMR46"); } int U_WMR47_get(void){ return U_WMRCORENONE_get("U_WMR47"); } //! \endcond /** \brief Retrieve values from a U_WMREXTFLOODFILL record \return length of the U_WMREXTFLOODFILL record, or NULL on error \param contents record to extract data from \param Mode FloodFill Enumeration. \param Color Color to Fill with. \param coord Location to start fill. */ int U_WMREXTFLOODFILL_get( const char *contents, uint16_t *Mode, U_COLORREF *Color, U_POINT16 * coord ){ return U_WMRCORE_1U16_CRF_2U16_get( contents, Mode, Color, U_P16(coord->y), U_P16(coord->x) ); } //! \cond int U_WMR49_get(void){ return U_WMRCORENONE_get("U_WMR49"); } int U_WMR4A_get(void){ return U_WMRCORENONE_get("U_WMR4A"); } int U_WMR4B_get(void){ return U_WMRCORENONE_get("U_WMR4B"); } int U_WMR4C_get(void){ return U_WMRCORENONE_get("U_WMRRESETDOC"); } int U_WMR4D_get(void){ return U_WMRCORENONE_get("U_WMRSTARTDOC"); } int U_WMR4E_get(void){ return U_WMRCORENONE_get("U_WMR4E"); } int U_WMR4F_get(void){ return U_WMRCORENONE_get("U_WMRSTARTPAGE"); } int U_WMR50_get(void){ return U_WMRCORENONE_get("U_WMRENDPAGE"); } int U_WMR51_get(void){ return U_WMRCORENONE_get("U_WMR51"); } int U_WMRABORTDOC_get(void){ return U_WMRCORENONE_get("U_WMRABORTDOC"); } int U_WMR53_get(void){ return U_WMRCORENONE_get("U_WMR53"); } int U_WMR54_get(void){ return U_WMRCORENONE_get("U_WMR54"); } int U_WMR55_get(void){ return U_WMRCORENONE_get("U_WMR55"); } int U_WMR56_get(void){ return U_WMRCORENONE_get("U_WMR56"); } int U_WMR57_get(void){ return U_WMRCORENONE_get("U_WMR57"); } int U_WMR58_get(void){ return U_WMRCORENONE_get("U_WMR58"); } int U_WMR59_get(void){ return U_WMRCORENONE_get("U_WMR59"); } int U_WMR5A_get(void){ return U_WMRCORENONE_get("U_WMR5A"); } int U_WMR5B_get(void){ return U_WMRCORENONE_get("U_WMR5B"); } int U_WMR5C_get(void){ return U_WMRCORENONE_get("U_WMR5C"); } int U_WMR5D_get(void){ return U_WMRCORENONE_get("U_WMR5D"); } int U_WMR5E_get(void){ return U_WMRCORENONE_get("U_WMRENDDOC"); } int U_WMR5F_get(void){ return U_WMRCORENONE_get("U_WMR5F"); } int U_WMR60_get(void){ return U_WMRCORENONE_get("U_WMR60"); } int U_WMR61_get(void){ return U_WMRCORENONE_get("U_WMR61"); } int U_WMR62_get(void){ return U_WMRCORENONE_get("U_WMR62"); } int U_WMR63_get(void){ return U_WMRCORENONE_get("U_WMR63"); } int U_WMR64_get(void){ return U_WMRCORENONE_get("U_WMR64"); } int U_WMR65_get(void){ return U_WMRCORENONE_get("U_WMR65"); } int U_WMR66_get(void){ return U_WMRCORENONE_get("U_WMR66"); } int U_WMR67_get(void){ return U_WMRCORENONE_get("U_WMR67"); } int U_WMR68_get(void){ return U_WMRCORENONE_get("U_WMR68"); } int U_WMR69_get(void){ return U_WMRCORENONE_get("U_WMR69"); } int U_WMR6A_get(void){ return U_WMRCORENONE_get("U_WMR6A"); } int U_WMR6B_get(void){ return U_WMRCORENONE_get("U_WMR6B"); } int U_WMR6C_get(void){ return U_WMRCORENONE_get("U_WMR6C"); } int U_WMR6D_get(void){ return U_WMRCORENONE_get("U_WMR6D"); } int U_WMR6E_get(void){ return U_WMRCORENONE_get("U_WMR6E"); } int U_WMR6F_get(void){ return U_WMRCORENONE_get("U_WMR6F"); } int U_WMR70_get(void){ return U_WMRCORENONE_get("U_WMR70"); } int U_WMR71_get(void){ return U_WMRCORENONE_get("U_WMR71"); } int U_WMR72_get(void){ return U_WMRCORENONE_get("U_WMR72"); } int U_WMR73_get(void){ return U_WMRCORENONE_get("U_WMR73"); } int U_WMR74_get(void){ return U_WMRCORENONE_get("U_WMR74"); } int U_WMR75_get(void){ return U_WMRCORENONE_get("U_WMR75"); } int U_WMR76_get(void){ return U_WMRCORENONE_get("U_WMR76"); } int U_WMR77_get(void){ return U_WMRCORENONE_get("U_WMR77"); } int U_WMR78_get(void){ return U_WMRCORENONE_get("U_WMR78"); } int U_WMR79_get(void){ return U_WMRCORENONE_get("U_WMR79"); } int U_WMR7A_get(void){ return U_WMRCORENONE_get("U_WMR7A"); } int U_WMR7B_get(void){ return U_WMRCORENONE_get("U_WMR7B"); } int U_WMR7C_get(void){ return U_WMRCORENONE_get("U_WMR7C"); } int U_WMR7D_get(void){ return U_WMRCORENONE_get("U_WMR7D"); } int U_WMR7E_get(void){ return U_WMRCORENONE_get("U_WMR7E"); } int U_WMR7F_get(void){ return U_WMRCORENONE_get("U_WMR7F"); } int U_WMR80_get(void){ return U_WMRCORENONE_get("U_WMR80"); } int U_WMR81_get(void){ return U_WMRCORENONE_get("U_WMR81"); } int U_WMR82_get(void){ return U_WMRCORENONE_get("U_WMR82"); } int U_WMR83_get(void){ return U_WMRCORENONE_get("U_WMR83"); } int U_WMR84_get(void){ return U_WMRCORENONE_get("U_WMR84"); } int U_WMR85_get(void){ return U_WMRCORENONE_get("U_WMR85"); } int U_WMR86_get(void){ return U_WMRCORENONE_get("U_WMR86"); } int U_WMR87_get(void){ return U_WMRCORENONE_get("U_WMR87"); } int U_WMR88_get(void){ return U_WMRCORENONE_get("U_WMR88"); } int U_WMR89_get(void){ return U_WMRCORENONE_get("U_WMR89"); } int U_WMR8A_get(void){ return U_WMRCORENONE_get("U_WMR8A"); } int U_WMR8B_get(void){ return U_WMRCORENONE_get("U_WMR8B"); } int U_WMR8C_get(void){ return U_WMRCORENONE_get("U_WMR8C"); } int U_WMR8D_get(void){ return U_WMRCORENONE_get("U_WMR8D"); } int U_WMR8E_get(void){ return U_WMRCORENONE_get("U_WMR8E"); } int U_WMR8F_get(void){ return U_WMRCORENONE_get("U_WMR8F"); } int U_WMR90_get(void){ return U_WMRCORENONE_get("U_WMR90"); } int U_WMR91_get(void){ return U_WMRCORENONE_get("U_WMR91"); } int U_WMR92_get(void){ return U_WMRCORENONE_get("U_WMR92"); } int U_WMR93_get(void){ return U_WMRCORENONE_get("U_WMR93"); } int U_WMR94_get(void){ return U_WMRCORENONE_get("U_WMR94"); } int U_WMR95_get(void){ return U_WMRCORENONE_get("U_WMR95"); } int U_WMR96_get(void){ return U_WMRCORENONE_get("U_WMR96"); } int U_WMR97_get(void){ return U_WMRCORENONE_get("U_WMR97"); } int U_WMR98_get(void){ return U_WMRCORENONE_get("U_WMR98"); } int U_WMR99_get(void){ return U_WMRCORENONE_get("U_WMR99"); } int U_WMR9A_get(void){ return U_WMRCORENONE_get("U_WMR9A"); } int U_WMR9B_get(void){ return U_WMRCORENONE_get("U_WMR9B"); } int U_WMR9C_get(void){ return U_WMRCORENONE_get("U_WMR9C"); } int U_WMR9D_get(void){ return U_WMRCORENONE_get("U_WMR9D"); } int U_WMR9E_get(void){ return U_WMRCORENONE_get("U_WMR9E"); } int U_WMR9F_get(void){ return U_WMRCORENONE_get("U_WMR9F"); } int U_WMRA0_get(void){ return U_WMRCORENONE_get("U_WMRA0"); } int U_WMRA1_get(void){ return U_WMRCORENONE_get("U_WMRA1"); } int U_WMRA2_get(void){ return U_WMRCORENONE_get("U_WMRA2"); } int U_WMRA3_get(void){ return U_WMRCORENONE_get("U_WMRA3"); } int U_WMRA4_get(void){ return U_WMRCORENONE_get("U_WMRA4"); } int U_WMRA5_get(void){ return U_WMRCORENONE_get("U_WMRA5"); } int U_WMRA6_get(void){ return U_WMRCORENONE_get("U_WMRA6"); } int U_WMRA7_get(void){ return U_WMRCORENONE_get("U_WMRA7"); } int U_WMRA8_get(void){ return U_WMRCORENONE_get("U_WMRA8"); } int U_WMRA9_get(void){ return U_WMRCORENONE_get("U_WMRA9"); } int U_WMRAA_get(void){ return U_WMRCORENONE_get("U_WMRAA"); } int U_WMRAB_get(void){ return U_WMRCORENONE_get("U_WMRAB"); } int U_WMRAC_get(void){ return U_WMRCORENONE_get("U_WMRAC"); } int U_WMRAD_get(void){ return U_WMRCORENONE_get("U_WMRAD"); } int U_WMRAE_get(void){ return U_WMRCORENONE_get("U_WMRAE"); } int U_WMRAF_get(void){ return U_WMRCORENONE_get("U_WMRAF"); } int U_WMRB0_get(void){ return U_WMRCORENONE_get("U_WMRB0"); } int U_WMRB1_get(void){ return U_WMRCORENONE_get("U_WMRB1"); } int U_WMRB2_get(void){ return U_WMRCORENONE_get("U_WMRB2"); } int U_WMRB3_get(void){ return U_WMRCORENONE_get("U_WMRB3"); } int U_WMRB4_get(void){ return U_WMRCORENONE_get("U_WMRB4"); } int U_WMRB5_get(void){ return U_WMRCORENONE_get("U_WMRB5"); } int U_WMRB6_get(void){ return U_WMRCORENONE_get("U_WMRB6"); } int U_WMRB7_get(void){ return U_WMRCORENONE_get("U_WMRB7"); } int U_WMRB8_get(void){ return U_WMRCORENONE_get("U_WMRB8"); } int U_WMRB9_get(void){ return U_WMRCORENONE_get("U_WMRB9"); } int U_WMRBA_get(void){ return U_WMRCORENONE_get("U_WMRBA"); } int U_WMRBB_get(void){ return U_WMRCORENONE_get("U_WMRBB"); } int U_WMRBC_get(void){ return U_WMRCORENONE_get("U_WMRBC"); } int U_WMRBD_get(void){ return U_WMRCORENONE_get("U_WMRBD"); } int U_WMRBE_get(void){ return U_WMRCORENONE_get("U_WMRBE"); } int U_WMRBF_get(void){ return U_WMRCORENONE_get("U_WMRBF"); } int U_WMRC0_get(void){ return U_WMRCORENONE_get("U_WMRC0"); } int U_WMRC1_get(void){ return U_WMRCORENONE_get("U_WMRC1"); } int U_WMRC2_get(void){ return U_WMRCORENONE_get("U_WMRC2"); } int U_WMRC3_get(void){ return U_WMRCORENONE_get("U_WMRC3"); } int U_WMRC4_get(void){ return U_WMRCORENONE_get("U_WMRC4"); } int U_WMRC5_get(void){ return U_WMRCORENONE_get("U_WMRC5"); } int U_WMRC6_get(void){ return U_WMRCORENONE_get("U_WMRC6"); } int U_WMRC7_get(void){ return U_WMRCORENONE_get("U_WMRC7"); } int U_WMRC8_get(void){ return U_WMRCORENONE_get("U_WMRC8"); } int U_WMRC9_get(void){ return U_WMRCORENONE_get("U_WMRC9"); } int U_WMRCA_get(void){ return U_WMRCORENONE_get("U_WMRCA"); } int U_WMRCB_get(void){ return U_WMRCORENONE_get("U_WMRCB"); } int U_WMRCC_get(void){ return U_WMRCORENONE_get("U_WMRCC"); } int U_WMRCD_get(void){ return U_WMRCORENONE_get("U_WMRCD"); } int U_WMRCE_get(void){ return U_WMRCORENONE_get("U_WMRCE"); } int U_WMRCF_get(void){ return U_WMRCORENONE_get("U_WMRCF"); } int U_WMRD0_get(void){ return U_WMRCORENONE_get("U_WMRD0"); } int U_WMRD1_get(void){ return U_WMRCORENONE_get("U_WMRD1"); } int U_WMRD2_get(void){ return U_WMRCORENONE_get("U_WMRD2"); } int U_WMRD3_get(void){ return U_WMRCORENONE_get("U_WMRD3"); } int U_WMRD4_get(void){ return U_WMRCORENONE_get("U_WMRD4"); } int U_WMRD5_get(void){ return U_WMRCORENONE_get("U_WMRD5"); } int U_WMRD6_get(void){ return U_WMRCORENONE_get("U_WMRD6"); } int U_WMRD7_get(void){ return U_WMRCORENONE_get("U_WMRD7"); } int U_WMRD8_get(void){ return U_WMRCORENONE_get("U_WMRD8"); } int U_WMRD9_get(void){ return U_WMRCORENONE_get("U_WMRD9"); } int U_WMRDA_get(void){ return U_WMRCORENONE_get("U_WMRDA"); } int U_WMRDB_get(void){ return U_WMRCORENONE_get("U_WMRDB"); } int U_WMRDC_get(void){ return U_WMRCORENONE_get("U_WMRDC"); } int U_WMRDD_get(void){ return U_WMRCORENONE_get("U_WMRDD"); } int U_WMRDE_get(void){ return U_WMRCORENONE_get("U_WMRDE"); } int U_WMRDF_get(void){ return U_WMRCORENONE_get("U_WMRDF"); } int U_WMRE0_get(void){ return U_WMRCORENONE_get("U_WMRE0"); } int U_WMRE1_get(void){ return U_WMRCORENONE_get("U_WMRE1"); } int U_WMRE2_get(void){ return U_WMRCORENONE_get("U_WMRE2"); } int U_WMRE3_get(void){ return U_WMRCORENONE_get("U_WMRE3"); } int U_WMRE4_get(void){ return U_WMRCORENONE_get("U_WMRE4"); } int U_WMRE5_get(void){ return U_WMRCORENONE_get("U_WMRE5"); } int U_WMRE6_get(void){ return U_WMRCORENONE_get("U_WMRE6"); } int U_WMRE7_get(void){ return U_WMRCORENONE_get("U_WMRE7"); } int U_WMRE8_get(void){ return U_WMRCORENONE_get("U_WMRE8"); } int U_WMRE9_get(void){ return U_WMRCORENONE_get("U_WMRE9"); } int U_WMREA_get(void){ return U_WMRCORENONE_get("U_WMREA"); } int U_WMREB_get(void){ return U_WMRCORENONE_get("U_WMREB"); } int U_WMREC_get(void){ return U_WMRCORENONE_get("U_WMREC"); } int U_WMRED_get(void){ return U_WMRCORENONE_get("U_WMRED"); } int U_WMREE_get(void){ return U_WMRCORENONE_get("U_WMREE"); } int U_WMREF_get(void){ return U_WMRCORENONE_get("U_WMREF"); } //! \endcond /** \brief Get data from a U_WMRDELETEOBJECT record. \return length of the U_WMRDELETEOBJECT record in bytes, or 0 on error \param contents record to extract data from \param Object Index of object which is made active. */ int U_WMRDELETEOBJECT_get( const char *contents, uint16_t *Object ){ return U_WMRCORE_1U16_get(contents, (U_SIZE_WMRDELETEOBJECT), Object); } //! \cond int U_WMRF1_get(void){ return U_WMRCORENONE_get("U_WMRF1"); } int U_WMRF2_get(void){ return U_WMRCORENONE_get("U_WMRF2"); } int U_WMRF3_get(void){ return U_WMRCORENONE_get("U_WMRF3"); } int U_WMRF4_get(void){ return U_WMRCORENONE_get("U_WMRF4"); } int U_WMRF5_get(void){ return U_WMRCORENONE_get("U_WMRF5"); } int U_WMRF6_get(void){ return U_WMRCORENONE_get("U_WMRF6"); } //! \endcond /** \brief Retrieve values from a U_WMRCREATEPALETTE record \return length of the U_WMRCREATEPALETTE record, or NULL on error \param contents record to extract data from \param Palette Create a Palette object. \param PalEntries Array of Palette Entries */ int U_WMRCREATEPALETTE_get( const char *contents, U_PALETTE *Palette, const char **PalEntries ){ return U_WMRCORE_PALETTE_get(contents, (U_SIZE_WMRCREATEPALETTE), Palette, PalEntries); } //! \cond int U_WMRF8_get(void){ return U_WMRCORENONE_get("U_WMRF8"); } //! \endcond /** \brief Get data from a U_WMRCREATEPATTERNBRUSH record. Warning - application support for U_WMRCREATEPATTERNBRUSH is spotty, better to use U_WMRDIBCREATEPATTERNBRUSH. \return length of the U_WMRCREATEPATTERNBRUSH record in bytes, or 0 on error \param contents record to extract data from \param Bm16 truncated Bitmap16 structure from record, only tge first 14 bytes hold data. \param pasize Number of bytes in Pattern \param Pattern byte array pattern, described by Bm16, for brush */ int U_WMRCREATEPATTERNBRUSH_get( const char *contents, U_BITMAP16 *Bm16, int *pasize, const char **Pattern ){ int off = U_SIZE_METARECORD; /* size in next one is 6 (core header) + 14 (truncated bitmap16) + 18 bytes reserved + 2 bytes (at least) for data */ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_METARECORD + 14 + 18 + 2)); if(!size)return(0); memset(Bm16, 0, U_SIZE_BITMAP16); /* BM16 is truncated in this record type to 14 bytes, last 4 bytes must be ignored, so they are not even copied */ memcpy(Bm16, contents + off, 10); *pasize = (((Bm16->Width * Bm16->BitsPixel + 15) >> 4) << 1) * Bm16->Height; off += 32; /* skip [14 bytes of truncated bitmap16 object and 18 bytes of reserved */ *Pattern = (contents + off); return(size); } /** \brief Get data from a U_WMRCREATEPENINDIRECT record. \return length of the U_WMRCREATEPENINDIRECT record in bytes, or 0 on error \param contents record to extract data from \param pen pointer to a U_PEN object to fill. */ int U_WMRCREATEPENINDIRECT_get( const char *contents, U_PEN *pen ){ int size = U_WMRCORE_RECSAFE_get(contents, (U_SIZE_WMRCREATEPENINDIRECT)); if(!size)return(0); memcpy(pen, contents + offsetof(U_WMRCREATEPENINDIRECT, pen), U_SIZE_PEN); return(size); } /** \brief Get data from a U_WMRCREATEFONTINDIRECT record. \return length of the U_WMRCREATEFONTINDIRECT record in bytes, or 0 on error \param contents record to extract data from \param font pointer to array of U_FONT structure in memory. Pointer may not be aligned properly for structure. */ int U_WMRCREATEFONTINDIRECT_get( const char *contents, const char **font ){ int size = U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEFONTINDIRECT), NULL, NULL, font); if(size){ if(IS_MEM_UNSAFE(*font, U_SIZE_FONT_CORE, contents+size))return(0); if(contents + size - *font > U_SIZE_FONT_CORE + 32)return(0); // font name must fit in a 32 bit field } return size; } /** \brief Get data from a U_WMRCREATEBRUSHINDIRECT record. \return length of the U_WMRCREATEBRUSHINDIRECT record in bytes, or 0 on error \param contents record to extract data from \param brush pointer to U_WLOGBRUSH structure in memory. Pointer may not be aligned properly for structure. */ int U_WMRCREATEBRUSHINDIRECT_get( const char *contents, const char **brush ){ // U_SIZE_WMRCREATEBRUSHINDIRECT is everything, no variable part, so the test below is sufficient return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEBRUSHINDIRECT), NULL, NULL, brush); } /** in GDI and Wine, not in WMF manual. */ int U_WMRCREATEBITMAPINDIRECT_get(void){ return U_WMRCORENONE_get("U_WMRCREATEBITMAPINDIRECT"); } /** in GDI and Wine, not in WMF manual. */ int U_WMRCREATEBITMAP_get(void){ return U_WMRCORENONE_get("U_WMRCREATEBITMAP"); } /** \brief Get data from a U_WMRCREATEREGION record. \return length of the U_WMRCREATEREGION record in bytes, or 0 on error \param contents record to extract data from \param Region pointer to U_REGION structure in memory. Pointer may not be aligned properly for structure. Caller must check at the returned Region does not extend outside of the record! */ int U_WMRCREATEREGION_get( const char *contents, const char **Region ){ return U_WMRCORE_2U16_N16_get(contents, (U_SIZE_WMRCREATEREGION), NULL, NULL, Region); } #ifdef __cplusplus } #endif