/** * allocate - Place block, i.e. write header and footer. */ static void allocate(void *bp, size_t adjusted_size) { size_t csize = GET_THISSIZE(bp); size_t is_prev_alloc = GET_PREVALLOC(bp); TRACE(">>>Entering allocate(bp=0x%X, adjusted_size=%u)\n", (unsigned int)bp, adjusted_size); /* We will always need to remove tshi block from the free list */ remove_from_list(bp, calc_list_index(csize)); /* See if there's room to split this block into two */ if ((csize - adjusted_size) >= (MIN_SIZE)) { PUTW(GET_BLOCKHDR(bp), PACK(adjusted_size, THISALLOC | is_prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(adjusted_size, THISALLOC | is_prev_alloc)); /* Using the new header info, mark the newly created block as free */ bp = GET_NEXTBLOCK(bp); PUTW(GET_BLOCKHDR(bp), PACK(csize - adjusted_size, PREVALLOC)); PUTW(GET_BLOCKFTR(bp), PACK(csize - adjusted_size, PREVALLOC)); /* And add it to the appropriate free list */ coalesce(bp); } else {/* If there's not room to create split the block, just extend the amount to allocated */ PUTW(GET_BLOCKHDR(bp), PACK(csize, THISALLOC | is_prev_alloc)); PUTW(GET_BLOCKFTR(bp), PACK(csize, THISALLOC | is_prev_alloc)); /* Make sure the next block's header has the prevalloc field marked */ bp = GET_BLOCKHDR(GET_NEXTBLOCK(bp)); PUTW(bp, GETW(bp) | PREVALLOC); } TRACE("<<<---Leaving allocate()\n"); }
/* storage isn't very efficient, # of polygons, size of each polygon, data for each polygon */ static GpStatus PolyPolygon (MetafilePlayContext *context, BYTE *data) { GpStatus status = Ok; /* variable number of parameters */ int poly_num = GETW(WP1); int i, j; PointFList *list = GdipAlloc (poly_num * sizeof (PointFList)); if (!list) { return OutOfMemory; } PointFList *current = list; #ifdef DEBUG_WMF printf ("PolyPolygon has %d polygons", poly_num); #endif int n = 2; /* read size of each polygon and allocate the required memory */ for (i = 0; i < poly_num; i++) { current->num = GETW(WP(n)); n++; current->points = (GpPointF*) GdipAlloc (current->num * sizeof (GpPointF)); if (!current->points) { for (j = 0; j < i; j++) { GdipFree (list[j].points); } GdipFree (list); return OutOfMemory; } #ifdef DEBUG_WMF_2 printf ("\n\tSub Polygon #%d has %d points", i, current->num); #endif current++; } /* read the points for each polygons */ current = list; for (i = 0; i < poly_num; i++) { GpPointF *pt = current->points; int p; for (p = 0; p < current->num; p++) { pt->X = GETW(WP(n)); n++; pt->Y = GETW(WP(n)); n++; #ifdef DEBUG_WMF_3 printf ("\n\t\tpoly to %g,%g", pt->X, pt->Y); #endif pt++; } GpStatus s = gdip_metafile_Polygon (context, current->points, current->num); if (s != Ok) status = s; /* free points */ GdipFree (current->points); current++; } /* all points were freed, after being drawn, so we just have to free the polygon list*/ GdipFree (list); return status; }
GpStatus gdip_metafile_play_wmf (MetafilePlayContext *context) { GpStatus status = Ok; GpMetafile *metafile = context->metafile; BYTE *data = metafile->data; BYTE *end = data + metafile->length; #ifdef DEBUG_WMF int i = 1, j; #endif /* reality check - each record is, at minimum, 6 bytes long (4 size + 2 function) */ while (data < end - WMF_MIN_RECORD_SIZE) { DWORD size = GETDW(RECORDSIZE); WORD func = GETW(FUNCTION); int params = size - (WMF_MIN_RECORD_SIZE / sizeof (WORD)); #ifdef DEBUG_WMF printf ("\n[#%d] size %d ", i++, size); #endif /* reality check - enough data available to read all parameters ? (params is in WORD) */ if ((params << 1) > (long)(end - data)) { status = InvalidParameter; goto cleanup; } /* Notes: * - The previous check doesn't mean we have all required parameters (only the one encoded) * - sometimes there are extra (undocumented?, buggy?) parameters for some functions */ switch (func) { case META_SAVEDC: WMF_CHECK_PARAMS(0); status = gdip_metafile_SaveDC (context); break; case META_SETBKMODE: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetBkMode (context, GETW(WP1)); break; case META_SETMAPMODE: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetMapMode (context, GETW(WP1)); break; case META_SETROP2: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetROP2 (context, GETW(WP1)); break; case META_SETRELABS: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetRelabs (context, GETW(WP1)); break; case META_SETPOLYFILLMODE: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetPolyFillMode (context, GETW(WP1)); break; case META_SETSTRETCHBLTMODE: WMF_CHECK_PARAMS(1); /* 2 but second is unused (32bits?) */ status = gdip_metafile_SetStretchBltMode (context, GETW(WP1)); break; case META_RESTOREDC: WMF_CHECK_PARAMS(0); status = gdip_metafile_RestoreDC (context); break; case META_SELECTOBJECT: WMF_CHECK_PARAMS(1); status = gdip_metafile_SelectObject (context, GETW(WP1)); break; case META_SETTEXTALIGN: WMF_CHECK_PARAMS(1); status = gdip_metafile_SetTextAlign (context, GETW(WP1)); break; case META_DELETEOBJECT: WMF_CHECK_PARAMS(1); status = gdip_metafile_DeleteObject (context, GETW(WP1)); break; case META_SETBKCOLOR: WMF_CHECK_PARAMS(2); status = gdip_metafile_SetBkColor (context, GetColor (GETW(WP1), GETW(WP2))); break; case META_SETWINDOWORG: WMF_CHECK_PARAMS(2); status = gdip_metafile_SetWindowOrg (context, GETS(WP1), GETS(WP2)); break; case META_SETWINDOWEXT: WMF_CHECK_PARAMS(2); status = gdip_metafile_SetWindowExt (context, GETS(WP1), GETS(WP2)); break; case META_LINETO: WMF_CHECK_PARAMS(2); status = gdip_metafile_LineTo (context, GETS(WP1), GETS(WP2)); break; case META_MOVETO: WMF_CHECK_PARAMS(2); status = gdip_metafile_MoveTo (context, GETS(WP1), GETS(WP2)); break; case META_CREATEPENINDIRECT: /* note: documented with only 4 parameters, LOGPEN use a POINT to specify width, so y (3) is unused) */ WMF_CHECK_PARAMS(5); status = gdip_metafile_CreatePenIndirect (context, GETW(WP1), GETW(WP2), GetColor (GETW(WP4), GETW(WP5))); break; case META_CREATEBRUSHINDIRECT: WMF_CHECK_PARAMS(4); status = gdip_metafile_CreateBrushIndirect (context, GETW(WP1), GetColor (GETW(WP2), GETW(WP3)), GETW(WP4)); break; case META_POLYGON: status = Polygon (context, data, params); break; case META_POLYLINE: status = Polyline (context, data); break; case META_POLYPOLYGON: status = PolyPolygon (context, data); break; case META_ARC: WMF_CHECK_PARAMS(8); status = gdip_metafile_Arc (context, GETS(WP1), GETS(WP2), GETS(WP3), GETS(WP4), GETS(WP5), GETS(WP6), GETS(WP7), GETS(WP8)); break; case META_RECTANGLE: WMF_CHECK_PARAMS (4); status = gdip_metafile_Rectangle (context, GETS (WP1), GETS (WP2), GETS (WP3), GETS (WP4)); break; case META_SETPIXEL: WMF_CHECK_PARAMS (4); status = gdip_metafile_SetPixel (context, GetColor (GETW (WP1), GETW (WP2)), GETW (WP4), GETW (WP3)); break; case META_STRETCHDIB: { WMF_CHECK_PARAMS(14); BITMAPINFO *bmi = (BITMAPINFO*) (data + 14 * sizeof (WORD)); void* bits = (void*) (bmi + GETDW(WP12)); status = gdip_metafile_StretchDIBits (context, GETS(WP11), GETS(WP10), GETS(WP9), GETS(WP8), GETS(WP7), GETS(WP6), GETS(WP5), GETS(WP4), bits, bmi, GETW(WP3), GETDW(WP1)); break; } case META_DIBSTRETCHBLT: { WMF_CHECK_PARAMS(12); BITMAPINFO *bmi = (BITMAPINFO*) (data + 13 * sizeof (WORD)); void* bits = (void*) (bmi + GETDW(WP11)); status = gdip_metafile_StretchDIBits (context, GETS(WP10), GETS(WP9), GETS(WP8), GETS(WP7), GETS(WP6), GETS(WP5), GETS(WP4), GETS(WP3), bits, bmi, 0, GETDW(WP1)); break; } default: /* unprocessed records, ignore the data */ /* 3 for size (DWORD) == 2 * SHORT + function == 1 SHORT */ #ifdef DEBUG_WMF printf ("Unimplemented_%X (", func); for (j = 0; j < params; j++) { printf (" %d", GetParam (j, data)); } printf (" )"); #endif break; } if (status != Ok) { g_warning ("Parsing interupted, status %d returned from function %d.", status, func); goto cleanup; } data += size * 2; } cleanup: return status; }
/******************************************************************* KF 6/14/90 INPUT: display, screen, filename to read the pixmap data from, OUTPUT: ximage structure xi, width and height of pixmap PURPOSE: read_pixmap_file reads an Ximage data structure from the input file. This routine can handle pixmaps of both XYPixmap and ZPixmap. If a pixmap has ZPixmap format, then the image data, read in as spadColor index, is converted to the pixel value using spadColor. Note that reading in Z format takes less space and time too. ********************************************************************/ int read_pixmap_file(Display *display, int screen, char *filename, XImage **xi, int *width, int *height) { FILE *file; int wi, h, num, num_colors, read_this_time, offset; Colormap cmap; int ts; unsigned long *spadColors; /* colormap is necessary to call makeColors */ cmap = DefaultColormap(display, screen); if ((num_colors = makeColors(display, screen, &cmap, &spadColors, &ts)) < 0) { return(-1); } file = zzopen(filename, "r"); if (file == NULL) { printf("couldn't open %s\n", filename); return BitmapOpenFailed; } #define GETW(f) ntohl(getw(f)) *width = wi = GETW(file); *height = h = GETW(file); (*xi) = XCreateImage(display, DefaultVisual(display, screen), DisplayPlanes(display, screen), ZPixmap, 0, NULL, wi, h, 16, 0); /* handles both XY & Z */ if ((*xi) == NULL) { fprintf(stderr, "Unable to create image\n"); return(-1); } (*xi)->width = wi; (*xi)->height = h; (*xi)->xoffset = GETW(file); (*xi)->format = GETW(file); (*xi)->byte_order = GETW(file); (*xi)->bitmap_unit = GETW(file); (*xi)->bitmap_bit_order = GETW(file); (*xi)->bitmap_pad = GETW(file); (*xi)->depth = GETW(file); (*xi)->bytes_per_line = GETW(file); (*xi)->bits_per_pixel = GETW(file); (*xi)->red_mask = GETW(file); (*xi)->green_mask = GETW(file); (*xi)->blue_mask = GETW(file); /* program will bomb if XYPixmap is not allocated enough space */ if ((*xi)->format == XYPixmap) { /* printf("picture is in XYPixmap format.\n"); */ num = (*xi)->bytes_per_line * h * (*xi)->depth; } else /* ZPixmap */ num = (*xi)->bytes_per_line * h; (*xi)->data = (void*)halloc(num, "Ximage data"); offset = 0; while (offset < num) { read_this_time = fread(((*xi)->data + offset), 1, num - offset, file); offset = offset + read_this_time; } fclose(file); /* * pixmap data in ZPixmap format are spadColor indices; pixmap data in * XYPixmap format are pixel values */ if ((*xi)->format == ZPixmap) { int ii, jj; for (ii = 0; ii < wi; ii++) for (jj = 0; jj < h; jj++) { XPutPixel(*xi, ii, jj, spadColors[(int) XGetPixel(*xi, ii, jj)]); } } return 0; }