Beispiel #1
0
static void DrawPolyPolyPolygonRaw(
    SystemDraw& draw, const Point *vertices, int vertex_count,
    const int *subpolygon_counts, int subpolygon_count_count,
    const int *disjunct_polygon_counts, int disjunct_polygon_count_count)
{
    GuiLock __;
    for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++)
    {
        int poly = *disjunct_polygon_counts;
        int sub = 1;
        if(*subpolygon_counts < poly)
            if(disjunct_polygon_count_count > 1)
            {
                const int *se = subpolygon_counts;
                int total = 0;
                while(total < poly)
                    total += *se++;
                sub = (int)(se - subpolygon_counts);
            }
            else
                sub = subpolygon_count_count;
        ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not
        if(sub == 1)
            Polygon(draw, (const POINT *)vertices, poly);
        else
            PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, sub);
        vertices += poly;
        subpolygon_counts += sub;
    }
}
Beispiel #2
0
static void DrawPolyPolygonRaw(Draw& draw, const Point *vertices, int vertex_count,
	const int *subpolygon_counts, int subpolygon_count_count,
	bool is_inside, int outline_width, Color outline_color
)
{
#ifdef SYSTEMDRAW
	SystemDraw *w = dynamic_cast<SystemDraw *>(&draw);
	if(w) { SystemDraw& draw = *w;
#endif
	draw.SetDrawPen(outline_width, outline_color);
	ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not
	enum { MAX_POLY = 8000 };
	if(subpolygon_count_count == 1 && vertex_count < MAX_POLY)
		Polygon(draw, (const POINT *)vertices, vertex_count);
	else if(vertex_count < MAX_POLY)
		PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, subpolygon_count_count);
	else {
		if(is_inside) {
			draw.SetDrawPen(PEN_NULL, Black);
			Vector<Point> split_vertices;
			Vector<int> split_counts;
		#ifdef SYSTEMDRAW
			SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count,
				split_vertices, split_counts, Size(9999, 9999));
		#else
			SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count,
				split_vertices, split_counts, draw.GetClip());
		#endif
			//!! todo: maxcount for splitpolygon
			const Point *sv = split_vertices.Begin();
			for(const int *sc = split_counts.Begin(), *se = split_counts.End(); sc < se; sc++) {
				Polygon(draw, (const POINT *)sv, *sc);
				sv += *sc;
			}
		}
		if(outline_width != PEN_NULL) {
			draw.DrawPolyPolyline(vertices, vertex_count, subpolygon_counts, subpolygon_count_count,
				outline_width, outline_color, Null);
			Buffer<Point> finish(2 * subpolygon_count_count);
			Buffer<int> counts(subpolygon_count_count);
			Fill(&counts[0], &counts[subpolygon_count_count], 2);
			Point *d = finish;
			const Point *p = vertices;
			const int *c = subpolygon_counts, *e = c + subpolygon_count_count;
			while(c < e)
			{
				*d++ = *p;
				*d++ = (p += *c++)[-1];
			}
			draw.DrawPolyPolyline(finish, 2 * subpolygon_count_count,
				counts, subpolygon_count_count, outline_width, outline_color, Null);
		}
		draw.SetDrawPen(outline_width, outline_color);
	}
#ifdef SYSTEMDRAW
	}
#endif
}
Beispiel #3
0
void DrawPolyPolyPolygon(Draw& draw, const Point *vertices, int vertex_count,
	const int *subpolygon_counts, int subpolygon_count_count,
	const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
	Color color, int width, Color outline, uint64 pattern, Color doxor)
{
	if(vertex_count == 0)
		return;

#ifdef PLATFORM_WIN32_ //!!TODO
	if(PdfDraw *pdf = dynamic_cast<PdfDraw *>(&draw)) {
		pdf->DrawPolyPolyPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count,
			disjunct_polygon_counts, disjunct_polygon_count_count, color, width, outline, pattern, doxor);
		return;
	}
#endif

//	LOG("DrawPolyPolyPolygon: drawing = " << (draw.IsDrawing() ? "yes" : "no")
//		<< ", backdraw = " << (draw.IsBack() ? "yes" : "no")
//		<< ", " << (draw.Dots() ? "dots" : "pixels")
//		<< ", printer = " << (draw.IsPrinter() ? "yes" : "no"));
//	LOG("#vertices = " << vertex_count << ", #subpolygons = " << subpolygon_count_count
//	<< ", #disjunct polygons = " << disjunct_polygon_count_count);
//	LOG("color = " << Dump(color) << ", width = " << width << ", outline = " << Dump(outline)
//	<< ", pattern = " << Dump(pattern) << ", doxor = " << doxor);

#ifdef _DEBUG
//	for(int v = 0; v < vertex_count; v++)
//		if(abs2(vertices[v] - vertices[(v ? v : vertex_count) - 1]) >= 500 * 500)
//			NEVER();
#endif

	if(!dynamic_cast<SystemDraw *>(&draw)) {
		draw.DrawPolyPolyPolygon(vertices, vertex_count,
			subpolygon_counts, subpolygon_count_count,
			disjunct_polygon_counts, disjunct_polygon_count_count,
			color, width, outline, pattern, doxor);
		return;
	}

//	TIMING("DrawPolyPolygon/hdc");
	bool is_xor = !IsNull(doxor);

#ifdef PLATFORM_X11
	unsigned xor_pixel = (is_xor ? GetXPixel(doxor) : 0);
	XGCValues gcv;
	gcv.function = is_xor ? X11_ROP2_XOR : X11_ROP2_COPY;
	GC fill_gc = NULL;
	Image pattern_image;
	if(!IsNull(color)) {
		gcv.foreground = GetXPixel(color) ^ xor_pixel;
		int fmask = GCForeground | GCFunction;
		if(pattern) {
			pattern_image = GetPatternImage(pattern);
			gcv.stipple = pattern_image.GetMaskPixmap();
			gcv.fill_style = FillStippled;
			fmask |= GCStipple | GCFillStyle;
		}
		fill_gc = XCreateGC(Xdisplay, draw.GetDrawable(), fmask, &gcv);
	}
	GC line_gc = NULL;
	if(!IsNull(outline)) {
		gcv.foreground = GetXPixel(outline) ^ xor_pixel;
		gcv.line_width = width;
		line_gc = XCreateGC(Xdisplay, draw.GetDrawable(), GCForeground | GCFunction | GCLineWidth, &gcv);
		Point offset = draw.GetOffset();
	}
#endif

	for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++) {
		int poly = *disjunct_polygon_counts;
		int sub = 1;
		if(*subpolygon_counts < poly)
			if(disjunct_polygon_count_count > 1) {
				const int *se = subpolygon_counts;
				int total = 0;
				while(total < poly)
					total += *se++;
				sub = se - subpolygon_counts;
			}
			else
				sub = subpolygon_count_count;

		if(sub > poly) {
			vertices += poly;
			subpolygon_counts += sub;
			continue;
		}


#if defined(PLATFORM_WIN32)
	#ifdef SYSTEMDRAW
		SystemDraw *w = dynamic_cast<SystemDraw *>(&draw);
		if(w) { SystemDraw& draw = *w;
	#endif
		if(pattern) {
			int old_rop = GetROP2(draw);
			HGDIOBJ old_brush = GetCurrentObject(draw, OBJ_BRUSH);
			word wpat[8] = {
				(byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32),
				(byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0),
			};
			HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat);
			HBRUSH brush = ::CreatePatternBrush(bitmap);
			COLORREF old_bk = GetBkColor(draw);
			COLORREF old_fg = GetTextColor(draw);
			if(!is_xor) {
				SetROP2(draw, R2_MASKPEN);
				SelectObject(draw, brush);
				SetTextColor(draw, Black());
				SetBkColor(draw, White());
				DrawPolyPolygonRaw(draw, vertices, poly,
					subpolygon_counts, sub, true, PEN_NULL, Null);
				SetROP2(draw, R2_MERGEPEN);
				SetTextColor(draw, color);
				SetBkColor(draw, Black());
			}
			else { // xor fill with pattern data
				SetROP2(draw, R2_XORPEN);
				SelectObject(draw, brush);
			}
			DrawPolyPolygonRaw(draw, vertices, poly,
				subpolygon_counts, sub, true, PEN_NULL, Null);
			SelectObject(draw, old_brush);
			SetTextColor(draw, old_fg);
			SetBkColor(draw, old_bk);
			SetROP2(draw, old_rop);
			DeleteObject(brush);
			DeleteObject(bitmap);
			if(!IsNull(outline))
			{
				draw.SetColor(Null);
				draw.SetDrawPen(width, outline);
				ASSERT(sizeof(POINT) == sizeof(Point));
				PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, sub);
			}
		}
		else
		{ // simple fill
	//		RTIMING("AreaTool::Fill(solid color)");
			int out_wd = (IsNull(width) || IsNull(outline) ? PEN_NULL : width);
			Color out_co = Nvl(outline, Black);
			draw.SetDrawPen(out_wd, out_co);
			if(is_xor)
			{
				color = Color(color.GetR() ^ doxor.GetR(), color.GetG() ^ doxor.GetG(), color.GetB() ^ doxor.GetB());
				SetROP2(draw, R2_XORPEN);
			}
			HGDIOBJ old_brush = 0;
			if(IsNull(color))
			{
				static HGDIOBJ null_brush = GetStockObject(NULL_BRUSH);
				old_brush = SelectObject(draw, null_brush);
			}
			else
				draw.SetColor(color);
			DrawPolyPolygonRaw(draw, vertices, poly, subpolygon_counts, sub,
				!IsNull(color), out_wd, out_co);
			if(old_brush)
				SelectObject(draw, old_brush);
			if(is_xor)
				SetROP2(draw, R2_COPYPEN);
		}
	#ifdef SYSTEMDRAW
		}
	#endif
#elif defined(PLATFORM_X11)
		if(fill_gc)
			FillPolyPolygonRaw(fill_gc, draw.GetDrawable(), draw.GetClip(), draw.GetOffset(),
				vertices, poly, subpolygon_counts, sub);
		if(line_gc)
			DrawPolyPolygonRaw(line_gc, draw.GetDrawable(), draw.GetOffset(),
				vertices, poly, subpolygon_counts, sub);
#else
	#error
#endif
		vertices += poly;
		subpolygon_counts += sub;
	}
Beispiel #4
0
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;
}
Beispiel #5
0
// A carbon copy of the Win\Gdi\Region\Polygon implementation
// without some parameter checks (no poly-fill-mode given)
PHP_METHOD(WinGdiRegionPolygon, polygon)
{
    wingdi_devicecontext_object *dc_obj;
    wingdi_path_object *path_obj;
    HashPointer p;              // We use this to determine what index we are at in the array
    POINT *points = NULL;
    zval  ***parameters,
          **current_elem,
          **x, **y;
    INT *point_counts   = NULL; // Number of POINTs in corresponding points array
    int  ints_in_count  = 0,    // Number of ints in point_counts
         param_count,
         i, t = 0;              // Total number of POINTs

    WINGDI_ERROR_HANDLING();
    // Will throw an exception if no parameters are given
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &parameters, &param_count) == FAILURE)
        return;
    WINGDI_RESTORE_ERRORS();

    point_counts = emalloc(param_count * sizeof(INT));

    for (i = 0; i < param_count; i++)
    {
        if (Z_TYPE_PP(parameters[i]) == IS_ARRAY)
        {
            point_counts[ints_in_count] = 0;

            for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(parameters[i]));
                 zend_hash_has_more_elements(Z_ARRVAL_PP(parameters[i])) == SUCCESS;
                 zend_hash_move_forward(Z_ARRVAL_PP(parameters[i])))
            {
                points = erealloc(points, t * sizeof(POINT) + sizeof(POINT));
                zend_hash_get_pointer(Z_ARRVAL_PP(parameters[i]), &p);
                zend_hash_get_current_data(Z_ARRVAL_PP(parameters[i]), (void **)&current_elem);

                if (Z_TYPE_PP(current_elem) != IS_ARRAY)
                {
                    php_error_docref(NULL TSRMLS_CC, E_ERROR,
                        "expected array in array for parameter %d, got %s", i + 1, zend_zval_type_name(*current_elem));
                    goto CLEANUP;
                }
                else
                {
                    if (zend_hash_num_elements(Z_ARRVAL_PP(current_elem)) != 2)
                    {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR,
                            "expected point-array at index %d for parameter %d to have 2 elements, %d given",
                            p.h, i + 1, zend_hash_num_elements(Z_ARRVAL_PP(current_elem)));
                        goto CLEANUP;
                    }
                    else
                    {
                        zend_hash_index_find(Z_ARRVAL_PP(current_elem), 0, (void **)&x);
                        zend_hash_index_find(Z_ARRVAL_PP(current_elem), 1, (void **)&y);
                        if (Z_TYPE_PP(x) != IS_LONG)
                            convert_to_long(*x);
                        if (Z_TYPE_PP(y) != IS_LONG)
                            convert_to_long(*y);

                        points[t].x = Z_LVAL_PP(x);
                        points[t].y = Z_LVAL_PP(y);
                        t++;
                        point_counts[ints_in_count]++;
                    }
                }
            }

            ints_in_count++;
        }
        else
        {
            php_error_docref(NULL TSRMLS_CC, E_ERROR,
                "expecting array for parameter %d, got %s", zend_zval_type_name(*(parameters[i])));
            goto CLEANUP;
        }
    }

    path_obj = zend_object_store_get_object(getThis() TSRMLS_CC);
    dc_obj = zend_object_store_get_object(path_obj->device_context TSRMLS_CC);
    RETURN_BOOL(PolyPolygon(dc_obj->hdc, points, point_counts, ints_in_count));

CLEANUP:
    efree(parameters);
    efree(points);
    efree(point_counts);
}