I have been taking a look at http://isocpp.org/files/papers/N3888.pdf
The current proposal proposes this:auto x1 = some_object();//Silently aliases x1auto x2 = x1;I think this approach won't be satisfactory, since it violates the usual semantics for c++ objects, at least in the standard library.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
Here are my comments. I understand that implementing these changes would in some cases imply that it can't be implemented on top of Cairo, but I don't think that could be a primary objective of a standardized API. I'm not knowledgeable in Cairo but in other drawing APIs and to some extent the underlying hardware. I think that it is more important to follow modern C++ paradigms is more important than simplicity of implementation. If we are not even taking away the void* context handling which is really arcane we can just as well use the original Cairo library, if you ask me. Also I think that this library is modeled too closely on Win32 with its 80ties style and today almost bizarre ideas of how to organize things. This is definitely not something we want to perpetuate.
Here are detailed comments based on reading the synopsis. As the paper does not go into detail I may have misunderstood some things, I apologize for this already here:The format enum seems a bit limited, as it does not contain for instance 3x12 bit RGB, which will be more and more used. Would it be possible to do a struct again to get an open ended set of formats. This should also contain thesubpixel_order information.
font_slant and font_weight: For instance wxWidgets provides more weight values than normal and bold. Some even has a 0-100 percent weight and slant in degrees. But maybe the enums only provide specific values on such a gradual scale?
rectangle and rectangle_int should be replaced with a template, instances of which are used in the api. This template along with point<T> should be in the top level std namespace and used throughout std when appropriate. Over time this will increase interoperability between 3rd party libraries as they start using them.
Similarly matrix should be called something like transform_matrix and inherit a generic std::matrix<2,3>, adding the affine transform specific setup methods as indicated.
If the to me a little bizzare class recangle_list exists region should have a ctor from it.
Is user_data_key and its use in device/surface really necessary to have?
Is shared_ptr semantics logical on device, really? It seems to me that these are more in the vein of singletons (although there may be more than one). That is, you get a handle to it from somewhere central, which you then never actually copy.
The same goes for surface unless you can create subsurfaces as rects on a parent surface, in which case reference counting is appropriate. However, I think that the reference counting should only be used between such surface objects, not for all "handles" to any one particular subwindow. This would mean that there would be no copy constructors or assignment operators. The ctor taking rect components is the one used to create a subsurface (and doing the reference counting).
There should be a ctor of surface which takes a rectangle<double> to describe the subsurface extent, not only one with four discrete ints. The use of double in this API is strange to me, or needs to be complemented with a (more commonly used) API using int. The latter solution would be appropriate in the case that using double implies a coordinate transform taking place before the subsurface is created. The hard thing about this is that if rotation or shear is included in the transform the subwindow can hardly be created.
get_font_options should return a const ref to the internal font_options object. I suspect that this is really a property of the device, but maybe not given recent GPU developments.
It seems that the fallback resolution handling would be more appropriately placed in device.mark_dirty_rectange shoud be available with a rectangle<int> as parameter. It seems inconsistent that the subsurface creation ctor takes a double rect and the dirty function takes a int rect.Is dirty rect handling really a function in this API at all? It is tightly connected to the windowing system event handling, while nothing else in this API really is.
write_to_png seems as a strange function here, as it sets one file format out in front of all others. Of course a image file read/write manager could be added to "make file formats equal" but I would put this in the hands of 3rd party developers and instead concentrate on standardizing an in-memory image memory class (placed in std or possibly its own sub-namespace, but not in std::drawing at least).The class image_surface seems to try to "be" this image memory, but only for the limited application of drawing in it. This is really a pity as we have lots of other application areas where image memories are important entities.vector<char> is a very unsuitable way to specify image data as it can't be constructed without being inited to 0. There seems be great opposition against allowing vectors to default-construct their elements, I have argued for this many a time without any success. In the absense of a real image memory class a char* + count API is actually much more appropriate as this allowd image memories from other libraries to be used. A stride parameter which is allowed to be larger than the number of bytes acutally required per line MUST be included or the value of this functionality dwindles. This is true even with the vector based signatures.
The image_surface constructor taking a generator function doesn't need the closure parameter handling now that we have lambdas (and functors).The image_surface constructor from a filename indicates that there might be an underlying image format reader system, which is not described. This seems not to be feasible at this time. Or it again implicitly refers to png files.
A color class seems called for. Such an abstraction is present in most all drawing libraries, except apparently, Cairo. Again this is one of those classes that are best placed directly in std, to be able to reuse them in future extensions working with colors in other ways.
The unification of different types of brushes into pattern class hierarchy seems promising. This should be unified with images, as all of them are ways of presenting pixel values (color data) at regular 2d positions, i.e. a raster. The raster_pattern type comes close to the image_memory I discussed above. Let's at least not have more than one type representing a in-memory stored x,y indexed raster of pixels!
In the 3D world rasters are regularly called textures. This is today not really a good name for the actual data even in this application as texture classes are also used for other things such as for instance bump maps. This actually goes beyond image data as such, but becomes a matrix type class if generalized far enough.
To get around this mess it seems logical to follow the path that C++ has taken in so many other areas, i.e. to templatize the methods and treat the parameter type (now a T) like a concept. Thus it is the concept of an "image" or "raster" that would be sdtandardized and then anything that complies to this concept can be drawn on or blitted onto something else. However, due to the plethora of storage formats for pixel data and the large sizes of images an efficient implementation of this is not easy to implement. I worked in a project which had implemented this and it was the module that had by far the longest compile times due to the large amount of template instantiations created. Note also that due to the dynamic nature of image file loading there must be ways to dispatch to these template functions at run time depending on the user's selection of file.The raster_source_pattern has a lot of callbacks and void* closure data that needs to be cleared out.
I'm not particularly fond of the name 'context' in this case, as it is rather non-descriptive.
It is not so logical that the actual drawing methods are located in the context, which mainly is a container for stateful drawing parameters. While it is established practice (stemming I think from WIN32) to use a notion of drawing context, I don't even think it really is sound object oriented design. I would much prefer that the actual drawing commands were methods on surface, and that these existed both in overloads with a context and without one (instead taking relevant parameters such as color and dash pattern for line drawing and brush for filling operations). This sort of unites the ideas of stateful parameter storage and GDI+ style possibilities of giving all parameters to each command. Both styles are useful! One reason for having a drawing context object may be if it enhances thread safety (i.e. contexts are not thread safe per se byt serialize their (hidden) interactions with the underlying surface so that several worker threads can be given parts of the same surface to draw on without problems). I don't however think that this is the intention of this proposal, is it?
I would like to see a simple way of rendering an image onto the surface without the convoluted procedure of first creating a pattern around the image, then setting this as the "sourc _pattern" of a context and then drawing a filled rectangle(!) to actually get the image data drawn.
Text output from unicode strings must be as simple as for 8 bit strings. Proper codepage handling must also be included for the 8 bit case I presume.
Drawing commands need to exist in overloads with int coordinates. This is the most common source of availability of data for drawing I think.Drawing commands should primarily work on Point data rather than discrete coordinate values, although overloads are a possibility. Mainly to reduce typing when calling but also to increase eficiency as the data is known to be placed together.Polyline/polygon drawing should be included, using a range-of-pointers concept.The paint() versus stroke() methods which I assume mean to fill and/or outline closed figures subsequently drawn makes the interface even more stateful than Win32, as you have both a possibility to set pattern and enable its use. On the other hand, compared to win32 and its followers, this gets rid of the need to set an "empty" brush to avoid filling figures, which is an advantage. The double calls to get a patterned figure is however error prone. Also, as I understand this, there is no shortcut to set a solid fill colour (you have to give the context a solid_colour_pattern to achieve the simplest of filled figures). Most other libraries has a shortcut for this called "setbackgroundcolour" or something like this.As filled/stroked figures are so common I would contemplate encoding this in the method name even. FillRectangle() and StrokeRectangle() is very easy to understand... You loose some if you want to do both with the same rectangle, but in honest, how common is that?The copy_page() and show_page() seem misplaced in a context type of object, but if drawing commands were on the surface object they would come more natural.
Il giorno 26/gen/2014, alle ore 21:38, Bengt Gustafsson <bengt.gu...@beamways.com> ha scritto:
> Here are my comments. <cut>
Hello everybody.
I’m new to this list and I acknowledge that my opinion might not have a big weight if at all, but I have my two cents.
I completely agree with Bengt regarding everything he said, but my point goes further. With modern C++
gaining relevance thanks to new language features and new common practices, why on earth should the committee
standardize an interface based on an old C library? I think that the idea of basing a standard rendering library
on Cairo (or GDI, or any library designed before C++11 or even before C++98) is flawed by principle.
Differently from other standard library facilities or subsystems, a 2D drawing API cannot be designed by
one or few men alone. To get it right, it needs enough field-testing, to be sure that:
1) the API is easy to use (in my opinion, the Qt drawing API is a reference point from this point of view),
2) it is flexible enough, given possible future uses and future hardware capabilities
3) it doesn’t impose artificial constraints, allowing the most efficient implementation across varying architectures and OSes.
Because of this, proposing an interface (even if a modern, well thought interface), without actually having implemented it and
made it used by actual users for enough time, is a bad idea.
Anyway, should I have to answer my list of bullets, here it is:
1) Please make simple things simple, hard things possible.
i.e. We all want the highest flexibility, but I don’t want to create or retrieve 8 objects to draw a filled circle.
2) Please handle fonts in a modern way and flexible. A 2D drawing API is useless nowadays without strong typographic support.
3) This points out the convenience of a text-layout facility.
4) An extensible reading/writing facility for image formats is a must, not an option
5) Don’t ignore platform differences. Giving access to native handles is not sufficient. Make it possible to have, for example,
a raster engine, an OpenGL engine, a D3D engine, etc…
6) For the software engine, writing the spec to have (or make it easy to have) pixel-to-pixel portability across implementations is a must.
7) Printing support is highly coupled with drawing, and it’s difficult to get the API right. You need a complete interface to set
all the possible printing options out there, but with a connection with the underlying platform because in GUI code you want to make the
user choose them with the native interface (this means importing the settings from the native type that represent them, not to handle the
8) Interoperability with the underlying platform is essential (again with a standard way to convert types that represents images, brushes,
colors, fonts etc… from the native type to the std:: ones).
9) Please give us powerful mathematical and geometrical primitives (a well designed and efficient std::matrix and two point<T> and
rectangle<T> classes are not enough at all)
10) With regards of the previous two points, it would be even better if everything is abstracted with a trait system like the boost geometric l
library (but possibly less complex)
11) shared_ptr is good, but why do the API have to expose the memory managed object at all? Let’s face the users with RAII types that
opaquely handles everything.
12) Please investigate on an FP-like approach to compose drawing operations.
i.e. we have stroke() and fill(), make me compose them to stroke and fill and reuse the composition, in a way that it run faster than execute two operations again.
Note that I’m not saying “Cairo doesn’t do any of these”, but even if the library itself have strong support for a lot of those points,
the interface is still fundamentally old...
12) Please investigate on an FP-like approach to compose drawing operations.
i.e. we have stroke() and fill(), make me compose them to stroke and fill and reuse the composition, in a way that it run faster than execute two operations again.
FP? I'm afraid I'm not sure what you are referring to. Possible because it's 3:46 in the morning and all that is coming to mind is floating point.
I try my best to judge opinions based on the ideas contained in them, not the person expressing them.
I completely agree with Bengt regarding everything he said, but my point goes further. With modern C++
gaining relevance thanks to new language features and new common practices, why on earth should the committee
standardize an interface based on an old C library? I think that the idea of basing a standard rendering library
on Cairo (or GDI, or any library designed before C++11 or even before C++98) is flawed by principle.
Cairo wasn't designed before C++98. It was started sometime in the 2002-2003 time frame as best I can tell. N3888 does not contemplate GDI.
I know of no major graphics library that was designed after C++11.
Differently from other standard library facilities or subsystems, a 2D drawing API cannot be designed by
one or few men alone. To get it right, it needs enough field-testing, to be sure that:
1) the API is easy to use (in my opinion, the Qt drawing API is a reference point from this point of view),
2) it is flexible enough, given possible future uses and future hardware capabilities
3) it doesn’t impose artificial constraints, allowing the most efficient implementation across varying architectures and OSes.
Because of this, proposing an interface (even if a modern, well thought interface), without actually having implemented it and
made it used by actual users for enough time, is a bad idea.
As for Qt, I invite you to consider the number of dependencies that Qt has on Qt. I considered and consciously rejected deriving an API from QPainter. Not because it is bad; I think it is quite good. I rejected it because I believed that trying to carve out the 2D drawing part of Qt without needing to standardize most of the rest of Qt (or butcher the API to the point where we'd be losing most of the benefits that Qt provides) would be extremely difficult. To me, Qt is designed to be used with Qt. Take a look at the QPainter API: http://qt-project.org/doc/qt-5/qpainter.html . Note the QVector<T> and the QString and QImage and all the other Qt types. It's a lot of baggage. Cairo, by contrast, is a graphics library. Period.If you want to write a proposal based on QPainter or some other aspect of Qt you can. Things only get standardized when someone decides to write a proposal and put in the work of explaining it, defending it, accepting valid criticisms of it, changing it, and so on until such time as it is at last accepted as a standard. And there is no guarantee that it ever will be accepted.
2) Please handle fonts in a modern way and flexible. A 2D drawing API is useless nowadays without strong typographic support.
3) This points out the convenience of a text-layout facility.Handling fonts, text rendering, and typography in general is a hard problem. We are going to do the best we can on this front, but understand that A) N3888 is a starting point not a final destination; and B) the final destination will still only be version 1. We are intentionally aiming at a small scope for the reasons set forth in N3791. We will be doing our best to craft a final API that is not final. In other words, one that can be expanded in the future to provide more functionality based on what users of the library tell us they want.Also, I completely reject the statement that "[a] 2D drawing API is useless nowadays without strong typographic support." Indeed, I contend that it would be useful even with no typography. If I could write standard, portable C++ code to do all of my 2D drawing and have it just work on Windows, GNU/Linux, the various *BSD distributions, Mac OS X, iOS, Android, Windows Phone, Blackberry, AIX, etc., and all I had to do was write platform specific code for font management and text rendering, I would still have saved myself a huge amount of work.
5) Don’t ignore platform differences. Giving access to native handles is not sufficient. Make it possible to have, for example,
a raster engine, an OpenGL engine, a D3D engine, etc…This is untenable. Native handles are a nice, proven abstraction for exposing platform-specific functionality without being compelled to standardize all of those platforms. Because if we had an OpenGL engine and a D3D engine, etc., we would need to standardize those interfaces. Even assuming that the Khronos Group and Microsoft both suddenly decided to allow these technologies to be submitted for standardization, it would still be a herculean task. With a horribly fragile result. The changes between different versions of OpenGL and D3D are not trivial. Even if we could standardize these things we would then be chained to them for the indefinite future, forced to update the standard every time they made a change or else fall woefully behind. For these reasons and more, even contemplating a design that includes platform specifics is futile.
6) For the software engine, writing the spec to have (or make it easy to have) pixel-to-pixel portability across implementations is a must.You can't even get pixel-to-pixel portability between different generations of GPUs from the same manufacturer (though they have gotten much better in recent years). Beyond stating that, I'm not really sure what point you were trying to make. We standardize an interface. The interface has semantics that define behaviors based on inputs. Implementers implement those interfaces and (hopefully) comply with the semantics, thus giving the results that the standard specifies. But we cannot compel implementers to do anything. It's ultimately their responsibility to deliver what their user base desires. So the best we can do is create something fun and exciting that we really want to use and in turn promote it to other C++ users so that they want to use it too which in turn puts pressure on the compiler vendors to provide what we are asking for.
8) Interoperability with the underlying platform is essential (again with a standard way to convert types that represents images, brushes,
colors, fonts etc… from the native type to the std:: ones).This is one of the main purposes of native handles, those things that you dismissed earlier as being not sufficient.
9) Please give us powerful mathematical and geometrical primitives (a well designed and efficient std::matrix and two point<T> and
rectangle<T> classes are not enough at all)That is the domain of SG6 and LEWG. See generally http://isocpp.org/std/the-committee . Many of the people involved with SG13 undoubtedly have good math backgrounds, but to find people who are the real subject matter experts in this, you would turn to SG6.
Standards don't happen unless someone writes a proposal. If you believe these things need to be standardized, start working on a proposal. If you need help, ask. There are people who would be happy to help guide you through the process of writing a proposal, though you need to be ready and willing to spend the hundreds of hours that a proposal of the nature that you have asked for would take. And, as mentioned above, willing to spend all of that time with no guarantee that anything will ever come of it.
10) With regards of the previous two points, it would be even better if everything is abstracted with a trait system like the boost geometric l
library (but possibly less complex)Someone else will have to address this point; I do not know if anyone has ever proposed standardizing Boost's Geometry library and if so what the status of any such effort is.
11) shared_ptr is good, but why do the API have to expose the memory managed object at all? Let’s face the users with RAII types that
opaquely handles everything.In points 5 and 7 you are asking for exposure of all sorts of platform specific functionality. Here you are saying bury everything in opaque types. There is a logical inconsistency between these two positions.
12) Please investigate on an FP-like approach to compose drawing operations.
i.e. we have stroke() and fill(), make me compose them to stroke and fill and reuse the composition, in a way that it run faster than execute two operations again.
FP? I'm afraid I'm not sure what you are referring to. Possible because it's 3:46 in the morning and all that is coming to mind is floating point.
Good bye,-Mike
point a = {1, 1}, b = {1, 2};
a += b;