[Mono-dev] =?gb2312?B?V2h5ICIgdGhlIG1hdHJpeCBNVVNUIGJlIGludmVydGlibGUgdG8gYmUgdXNlZCAiIGluIGxpYmdkaXBsdXMgd2hlbiB3ZSBjYWxsIEdkaXBTZXRXb3JsZFRyYW5zZm9ybSBvciBHZGlwTXVsdGlwbHlXb3JsZFRyYW5zZm9ybT8g?=
=?gb2312?B?b2tlbg==?=
okenjian at 163.com
Sat Aug 7 22:36:29 EDT 2010
hi, all!
The following code are from libgdiplus2.6.7, in graphics.c.
I have a few quetions:
1. Why " the matrix MUST be invertible to be used " when we call GdipSetWorldTransform or GdipMultiplyWorldTransform? It is unnecessary for windows's gdiplus.
2. each time when the world transformation is changed(translate, roate, scale), the function apply_world_to_bounds is called. what if we don't call apply_world_to_bounds?
3. GdipSetWorldTransform also change the world transformation, but it doesnt call world transformation, why?
4. apply_world_to_bounds use graphics->clip_matrix to transform points, why not use graphics->copy_of_ctm? As graphics->copy_of_ctm is the world transformation and graphics->clip_matrix is just the matrix of the clip region.
I use libgdiplus to draw something(I change the world transformation using the related functions, but the position and the size is incorrect. I don't know wether it has sth to do with the following questions.
thanks!
static GpStatus
apply_world_to_bounds (GpGraphics *graphics)
{
GpStatus status;
GpPointF pts[2];
pts[0].X = graphics->bounds.X;
pts[0].Y = graphics->bounds.Y;
pts[1].X = graphics->bounds.X + graphics->bounds.Width;
pts[1].Y = graphics->bounds.Y + graphics->bounds.Height;
status = GdipTransformMatrixPoints (graphics->clip_matrix, (GpPointF*)&pts, 2);/* why not use graphics->copy_of_ctm?*/
if (status != Ok)
return status;
if (pts[0].X > pts[1].X) {
graphics->bounds.X = float2int(pts[1].X);
graphics->bounds.Width = float2int(iround (pts[0].X - pts[1].X));
} else {
graphics->bounds.X = float2int(pts[0].X);
graphics->bounds.Width = float2int(iround (pts[1].X - pts[0].X));
}
if (pts[0].Y > pts[1].Y) {
graphics->bounds.Y = float2int(pts[1].Y);
graphics->bounds.Height = float2int(iround (pts[0].Y - pts[1].Y));
} else {
graphics->bounds.Y = float2int(pts[0].Y);
graphics->bounds.Height = float2int(iround (pts[1].Y - pts[0].Y));
}
return Ok;
}
GpStatus WINGDIPAPI GdipSetWorldTransform (GpGraphics *graphics, GpMatrix *matrix)
{
GpStatus status;
BOOL invertible;
if (!graphics || !matrix)
return InvalidParameter;
/* optimization - inverting an identity matrix result in the identity matrix */
if (gdip_is_matrix_empty (matrix))
return GdipResetWorldTransform (graphics);
/* the matrix MUST be invertible to be used */
status = GdipIsMatrixInvertible (matrix, &invertible);
if (!invertible || (status != Ok))
{printf("InvalidParameter\n");return InvalidParameter;}
gdip_cairo_matrix_copy (graphics->copy_of_ctm, matrix);
gdip_cairo_matrix_copy (graphics->clip_matrix, matrix);
/* we already know it's invertible */
GdipInvertMatrix (graphics->clip_matrix);
/* apply_world_to_bounds (graphics); is not called here! why?*/
switch (graphics->backend) {
case GraphicsBackEndCairo:
return cairo_SetWorldTransform (graphics, matrix);
case GraphicsBackEndMetafile:
return metafile_SetWorldTransform (graphics, matrix);
default:
return GenericError;
}
}
GpStatus WINGDIPAPI GdipMultiplyWorldTransform (GpGraphics *graphics, GpMatrix *matrix, GpMatrixOrder order)
{
Status s;
BOOL invertible;
GpMatrix inverted;
if (!graphics)
return InvalidParameter;
/* the matrix MUST be invertible to be used */
s = GdipIsMatrixInvertible (matrix, &invertible);
if (!invertible || (s != Ok))
{printf("InvalidParameter\n");return InvalidParameter;}
s = GdipMultiplyMatrix (graphics->copy_of_ctm, matrix, order);
if (s != Ok)
return s;
/* Multiply the inverted matrix with the clipping matrix */
gdip_cairo_matrix_copy (&inverted, matrix);
s = GdipInvertMatrix (&inverted);
if (s != Ok)
return s;
s = GdipMultiplyMatrix (graphics->clip_matrix, &inverted, order);
if (s != Ok)
return s;
apply_world_to_bounds (graphics);
switch (graphics->backend) {
case GraphicsBackEndCairo:
/* not a typo - we apply to calculated matrix to cairo context */
return cairo_SetWorldTransform (graphics, graphics->copy_of_ctm);
case GraphicsBackEndMetafile:
return metafile_MultiplyWorldTransform (graphics, matrix, order);
default:
return GenericError;
}
}
GpStatus WINGDIPAPI GdipRotateWorldTransform (GpGraphics *graphics, float angle, GpMatrixOrder order)
{
GpStatus s;
if (!graphics)
return InvalidParameter;
s = GdipRotateMatrix (graphics->copy_of_ctm, angle, order);
if (s != Ok)
return s;
s = GdipRotateMatrix (graphics->clip_matrix, -angle, gdip_matrix_reverse_order (order));
if (s != Ok)
return s;
apply_world_to_bounds (graphics);
switch (graphics->backend) {
case GraphicsBackEndCairo:
/* not a typo - we apply to calculated matrix to cairo context */
return cairo_SetWorldTransform (graphics, graphics->copy_of_ctm);
case GraphicsBackEndMetafile:
return metafile_RotateWorldTransform (graphics, angle, order);
default:
return GenericError;
}
}
GpStatus WINGDIPAPI GdipScaleWorldTransform (GpGraphics *graphics, float sx, float sy, GpMatrixOrder order)
{
GpStatus s;
if (!graphics || (sx == 0.0f) || (sy == 0.0f))
return InvalidParameter;
s = GdipScaleMatrix (graphics->copy_of_ctm, sx, sy, order);
if (s != Ok)
return s;
s = GdipScaleMatrix (graphics->clip_matrix, (1.0f / sx), (1.0f / sy), gdip_matrix_reverse_order (order));
if (s != Ok)
return s;
apply_world_to_bounds (graphics);
switch (graphics->backend) {
case GraphicsBackEndCairo:
/* not a typo - we apply to calculated matrix to cairo context */
return cairo_SetWorldTransform (graphics, graphics->copy_of_ctm);
case GraphicsBackEndMetafile:
return metafile_ScaleWorldTransform (graphics, sx, sy, order);
default:
return GenericError;
}
}
GpStatus WINGDIPAPI GdipTranslateWorldTransform (GpGraphics *graphics, float dx, float dy, GpMatrixOrder order)
{
GpStatus s;
if (!graphics)
return InvalidParameter;
s = GdipTranslateMatrix (graphics->copy_of_ctm, dx, dy, order);
if (s != Ok)
return s;
s = GdipTranslateMatrix (graphics->clip_matrix, -dx, -dy, gdip_matrix_reverse_order (order));
if (s != Ok)
return s;
apply_world_to_bounds (graphics);
switch (graphics->backend) {
case GraphicsBackEndCairo:
/* not a typo - we apply to calculated matrix to cairo context */
return cairo_SetWorldTransform (graphics, graphics->copy_of_ctm);
case GraphicsBackEndMetafile:
return metafile_TranslateWorldTransform (graphics, dx, dy, order);
default:
return GenericError;
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20100808/36fa1f72/attachment-0001.html
More information about the Mono-devel-list
mailing list