[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