On Fri, 14 Jun 2019 at 13:07, Eli Zaretskii wrote: > From: Richard Copley > Date: Fri, 14 Jun 2019 12:21:19 +0100 > Cc: Stefan Monnier , Emacs Development < emacs-devel@gnu.org> > > Firstly, all the 2D graphics libraries (XRender and NS, as we have > seen, GDI, Direct2D, HTML5 Canvas, Cairo) specify the transformation > with a homogeneous matrix. (The same goes for 3D graphics > libraries.) It's fundamental to graphics programming. Why make up > our own, inferior, system? Two reasons: (a) Emacs is not a system for graphics programming, and doesn't target programmers in that domain; (2) an API based on transformation matrices is IMO too low-level, unlike anything else in Emacs. > (The Windows API documentation is no longer very good for finding out about > previous versions of Windows. Is GM_ADVANCED not supported on some GDI > versions we're interested in? If so, is it important to provide image > support there?) I'm using this site when I need information about older versions of Windows: http://winapi.freetechsecrets.com/win32 According to it, GM_ADVANCED is not supported on Windows 9X. Is it important to support such advanced features there? > Secondly, for users who want to specify a scale, translation and > rotation, it's easy to construct the matrix from that > information. "Easy"? For those with background in graphics programming, sure. For others, not so sure. The point I was making is that it is easy compared with going in the opposite direction. > (All the graphics libraries provide helper functions for this, and > so should we.) So you are saying that we should accept the attributes and convert them to a matrix in Lisp? Sure. And we shouldn't allow users to access the attributes afterwards. That might work, and doesn't really contradict what I say above, but we should first make sure that all the toolkits we support interpret the matrix the same. They don't, but the differences are small platform-specific fixups (possibly inverting and/or transposing the matrix, as well as converting the values to the appropriate types). The mathematical fundamentals are the same for all the platforms. We are still arguing about the meaning we ourselves assign to the matrix (see the recent clockwise vs counter-clockwise rotation issue), which somehow doesn't increase my confidence that exposing the transformation through a Lisp API would be a good/useful idea. It's not so important that everybody gets everything correct every time in this discussion. The important thing is that the implementation is correct in the end. > On the other hand for users who want to specify the homogeneous > matrix, it's not easy to decompose the matrix into scale, shear, > rotation and translation and rotation. I still don't understand why users would want to specify transformations via a matrix. Most won't. > Thirdly, the homogeneous matrix is compact and uniform, and makes > it easy to compose and invert (undo) transformations. So are/do the attributes. I think you're underestimating the difficulty of that part. Here's a concrete example. Suppose the user wants to apply two transformations, 1. Stretch by factor 2 in the x direction, then rotate clockwise by 45 degrees, then translate to the right by 100 pixels. 2. Stretch by factor 0.5 in the x direction, then rotate clockwise by 90 degrees, then translate left by 100 pixels. Calculating the resulting matrix might be a little tricky to get right, but with some experimentation you'll get there. Calculating the resulting shear, rotation, scale and translation is much more difficult to conceptualize. You would first have to calculate the matrix in any case. Then you would need to do Singular Value Decomposition. I can help you with the equations, if it comes to it, but I don't think it's needed for this. We just shouldn't expose the individual parameters to the users in the first place. Which representation is more compact is arguable: for example, the matrix representation of a rotation is much more wasteful than just a single angle of rotation parameter. I didn't say "more compact". But I think this is a tangent, because my proposal doesn't preclude providing a matrix-based API in the future. It will make it difficult to preserve backward compatibility. Constructing the :crop, :rotate, etc., from the matrix, is hard.