Mercurial > dillo_port1.3
changeset 394:0c759db427b5
- Removed obsolete Dw* documentation.
author | jcid |
---|---|
date | Wed, 08 Oct 2008 15:37:46 +0200 |
parents | c3bafcdde88a |
children | 094b63be5d0f |
files | doc/Dw.txt doc/DwImage.txt doc/DwPage.txt doc/DwRender.txt doc/DwStyle.txt doc/DwTable.txt doc/DwWidget.txt |
diffstat | 7 files changed, 4 insertions(+), 2203 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/Dw.txt Tue Oct 07 21:01:41 2008 +0200 +++ b/doc/Dw.txt Wed Oct 08 15:37:46 2008 +0200 @@ -1,383 +1,11 @@ -Jan 2001, S.Geerken@ping.de -Last update: Dec 2004 +Last update: Oct 2008 ================ Dw: Dillo Widget ================ -NOTE (Aug 2004): The rendering has changed quite much, and many other -documents are out of date, in ways described in DwRendering.txt. They -will be updated some day. - -Dw is mainly the module for rendering HTML. It provides a framework -for widgets, based on the Gtk+ object framework, and is very similar -to Gtk+, so that experiences in using and extending Gtk+ help very -much in understanding Dw. There is some documentation at www.gtk.org -(and probably on your local harddisk, somewhere in /usr/doc/*gtk*), -you should especially have read the chapter "Writing Your Own -Widgets" in the tutorial. - - -Why Not Gtk+? -============= - -There are two reasons for designing a new model instead of simply -using Gtk+ objects: - - 1. Most important, Gtk+ widgets are limited in size, because X - windows are so. - 2. There are a few extensions which are due to the different needs - for HTML rendering compared to GUI's. (Of course, this could - have been solved by defining a new object derived from - GtkWidget.) - - -Notes On Naming -=============== - -According to the naming standards, functions beginning with "a_Dw_" -may be used outside of Dw, while, as an extention, functions used -within Dw (e.g. p_Dw_widget_queue_resize) are prefixed with "p_Dw_". -[todo: This could be included in NC_design.txt.] - -Non-static functions beginning with "Dw_" are only used between -GtkDwViewport and DwWidget (e.g. Dw_gtk_viewport_remove_dw), they -belong to the core of Dw. And, of course, functions only used within a -sub-module (e.g. a specific widget) start with "Dw_" and are static -(e.g. Dw_page_find_line_index). - -Dw widgets and some other structures have the prefix "Dw", while Gtk+ -widgets in Dw have the prefix "GtkDw", but functions of them begin -with "Dw_gtk_" or "a_Dw_gtk", respectively. - - -Basic Overview -============== - -Dw widgets are objects derived from DwWidget, which itself derives -from GtkObject. DwWidget is quite similar to GtkWidget, the main -difference is that Dw widgets are always windowless and that they are -presented in a viewport, so there is no need to limit the size. Much -of the functionality normally provided by the X server is simulated -by Dw. - -The interface between Gtk+ and Dw is the Gtk+ widget GtkDwViewport, -which contains (at most) one top-level Dw widget. - -A Few Definitions: - - - world coordinates: coordinates relative to the upper left corner - of the whole scrolled area ("the world") - - viewport coordinates: coordinates relative to the upper left - corner of the visible area - - widget coordinates: coordinates relative to the upper left corner - of the widget - -Dw widgets draw into the viewport window, and must adhere to -*viewport coordinates*: the "world" is only an abstract term, there -is no window for it. When GtkDwViewport processes expose events, they -are automatically delivered to the Dw widgets. Redrawing requests due -to scrolling of the viewport is done by the base object GtkLayout, -you will not find any code for this in Dw. - -Mouse events also contain viewport coordinates. Dw will try to find -the right Dw widget to deliver the event to. - -Resizing the GtkDwViewport will not resize the top-level Dw widget, -but the latter will get some hints, so that, e.g., the page widget -rewraps the lines at the appropriate width. - -See DwWidget.txt for more details. - - -Embedding Gtk+ Widgets In Dw ----------------------------- -Dw Widgets may embed Gtk+ widgets, this is done by the Dw widget -DwEmbedGtk. For Gtk+, these embedded Gtk+ widgets are themselves -children of the GtkDwViewport, since Gtk+ does not care about Dw. - -Of course, embedded Gtk+ widgets are again limited in size, but but -in position: GtkDwViewport is derived from GtkLayout which is exactly -designed for positioning widgets in an infinite scrolled area. - - -How To Get The Top-Level Dw Widget From A BrowserWindow -------------------------------------------------------- -The member "docwin" of BrowserWindow points on a GtkDwScrolledWindow, -which contains a GtkDwScrolledFrame, which contains a GtkDwViewport. -The member "child" of the latter points on the top-level Dw widget, -or may be NULL. The top-level Dw is (currently) a DwPage (HTML and -plain text documents) or a DwImage (images). - -There is a function a_Dw_gtk_scrolled_window_get_dw for this. - - -Sizes ------ -A feature adapted from the old Dw are baselines. As well DwAllocation -as DwRequisition do not have a height member, but instead ascent and -descent, both positive or zero. (Originally I removed this, but there -will be a few widgets in future depending on this, e.g., math -formulas.) - -Unlike in Gtk, sizes of zero are allowed. The upper limit for the -size of a widget is 2^31 (this will be enough to show the contents of -a small library in a web page). - - -Resizing -======== - -From outside: When writing a new widget, you should implement the -signal "size_request". When the widget changes its size, it should -call p_Dw_widget_queue_resize, as in a_Dw_image_size. See "Incremental -Resizing" below for a way to increase the speed. - -Even if the implementation of "size_request" gets quite expensive, -you do not have to check whether the size has changed, this is done -by a_Dw_widget_size_request. - -Inside: q_Dw_widget_queue_resize will set the DW_NEEDS_RESIZE flag, a -further call of a_Dw_widget_size_request will only then emit the -"size_request" signal. Furthermore, mark_size_change and -mark_extremes_change are called (see below). After that, the resizing -is done in an idle loop, this prevents too many size requests. The -algorithm is quite simple: any widget with a child which needs -resizing, needs resizing, thus all parents up to top-level widget are -marked. - -Incremental Resizing ---------------------- -A widget may calculate its size based on size calculations already -done before. In this case, a widget must exactly know the reasons, why -a call of size_request is necessary. To make use of this, a widget -must implement the following: - - 1. There is a member in DwWidget, called parent_ref, which is - totally under control of the parent widget (and so sometimes not - used at all). It is necessary to define how parent_ref is used - by a specific parent widget, and it has to be set to the correct - value whenever necessary. - - 2. The widget must implement mark_size_change and - mark_extremes_change, these methods are called in two cases: - - a) directly after q_Dw_widget_queue_resize, with the argument - ref was passed to q_Dw_widget_queue_resize, and - b) if a child widget has called q_Dw_widget_queue_resize, - with the value of the parent_ref member of this child. - -This way, a widget can exactly keep track on size changes, and so -implement resizing in a faster way. A good example on how to use this -is the DwPage widget, see DwPage.txt for details. - - -Anchors and Scrolling -===================== - -Anchors -------- -todo: This section is out of sync with the actual code. - -To set the anchor a page is viewed at, you can use one of the -following functions: - - - void a_Dw_gtk_viewport_set_anchor (GtkDwViewport *viewport, - gchar *anchor) - - Scroll directly to an anchor. The anchor does not need to exist - already, see below. - - - void a_Dw_gtk_viewport_queue_anchor (GtkDwViewport *viewport, - gchar *anchor) +Dw is the internal widget library for rendering HTML. It has excellent +documentation. - Set the anchor for the next top-level DwWidget (the next call - of a_Dw_gtk_viewport_add_dw). - -There are wrappers, a_Dw_gtk_scrolled_window_queue_anchor and -a_Dw_gtk_scrolled_window_set_anchor. - -After a_Dw_gtk_viewport_set_anchor has been called (indirectly by -Nav_open_url, or by a_Dw_gtk_viewport_add_dw), changes of anchor -positions (e.g., if widgets change there size or the anchor was not -known before) will correct the viewport adjustment (in function -p_Dw_gtk_viewport_update_anchor), but only as long as the user did not -change it directly. Look at Dw_gtk_scrolled_window_init for details -about the latter. - -Use p_Dw_widget_set_anchor to add anchors to a widget, see -DwWidget.txt. - -Scrolling ---------- -Here is an overview on more functions for scrolling: - - - To scroll to a given position, there are two possibilities: - a_Dw_gtk_viewport_set_scrolling_position simply scrolls to this - position, while Dw_gtk_viewport_scroll_to has more facilities: - you specify a rectangle you want to see, and the way how it is - seen (at the border, centered, or just scroll as much as - necessary, that it is seen). If you have a widget, you can also - use Dw_widget_scroll_to. There is also a wrapper for - GtkDwScrolledWindow, - a_Dw_gtk_scrolled_window_set_scrolling_position, and two - functions for getting the position, - a_Dw_gtk_scrolled_window_get_scrolling_position_x, and - a_Dw_gtk_scrolled_window_get_scrolling_position_y. - - - If you have a region, and want to display it, use - a_Dw_iterator_scroll_to. For example, the findtext module makes - use of it. There are equivalents for DwExtIterator and - DwWordIterator. See comments on and in the function for more - informations. - - - If you just want to determine where some content is allocated, - represented by an iterator, you can use - a_Dw_iterator_get_allocation. There are equivalents for - DwExtIterator and DwWordIterator. - - -The Objects -=========== - -This is the hierarchy of all objects of Dw: - - (GtkObject) - +-DwWidget - | +----DwBullet - | +----DwContainer - | | `----DwPage - | +----DwEmbedGtk - | +----DwHruler - | `----DwImage - `----(GtkWidget) - `----(GtkContainer) - +----(GtkBin) - | +----(GtkScrolledWindow) - | | `----GtkDwScrolledWindow - | `----GtkDwScrolledFrame - `----(GtkLayout) - `----GtkDwViewport - -Objects in parentheses are part of Gtk+, not of Dw. - - -DwBullet --------- -Simple widget used for unnumbered list (<ul>). - - -DwContainer ------------ -The base object for Dw widgets which contain other Dw widgets. As in -Gtk+, containers are responsible for storing the children, there is -no common data structure. There are a few signals: - - - void add (DwContainer *container, - DwWidget *child); - - Currently not used, but may be in future. - - - void remove (DwContainer *container, - DwWidget *widget); - - *Recognize* that a widget is destroyed, i.e., an implementation - should remove *the pointer* from the list or so, but not - destroy the child widget. It is called by Dw_widget_shutdown. + Just run "doxygen" and browse the html/ directory! - - void forall (DwContainer *container, - DwCallback callback, - gpointer callback_data); - - Process callback for all children, in the form - (*callback)(child, callback_data). - - The include_internals of the Gtk+ equivalent was not adapted, - since it is used for more sophisticated purposes not needed in - Dw. - - -DwEmbedGtk ----------- -This Dw widget is used to embed Gtk+ widgets into Dw container -widgets. The Gtk+ widget is set by a_Dw_embed_gtk_add_gtk, and can -simply be removed by destroying it. - -If the DwEmbedGtk contains no Gtk+ widget, it always returns 0x0x0 as -size, so, for speed reasons, first add the Gtk+ widget into the -DwEmbedGtk, and then the DwEmbedGtk into the other Dw widget, as at -the end of Html_tag_open_input. - - -DwHruler --------- -Simple widget used for the <hr> tag. - - -DwImage -------- -Widget for displaying image. See DwImage.txt for details. - - -DwPage ------- -A widget for displaying texts. See DwPage.txt for details. - - -DwTable -------- -A container widget for rendering tables. See DwTable.txt for details. - - -DwWidget --------- -The base object for all Dw widgets. See DwWidget.txt for details. - - -GtkDwScrolledWindow -------------------- -Adds a few functionalities to GtkScrolledWindow: it creates the -GtkDwScrolledFrame and the GtkDwViewport, connects some signals, and -provides some wrappers for using the GtkDwViewport. - - -GtkDwScrolledFrame ------------------- -General purpose scrolled widget containing another scrolled widget, -adding a border and a focus frame. Furthermore, it processes key -presses and mouse drags (button 2, as in Gimp) to move the viewport. - -There are two signals (except "set_scroll_adjustments"), -"user_hchanged" and "user_vchanged", which are emitted when the user -changed the viewport adjustments horizontally/vertically by using the -keys or button 2 dragging. - - -GtkDwViewport -------------- -The interface between Gtk+ and Dw. It is responsible for displaying -Dw Widgets and processing their events. It is derived from GtkLayout, -to make embedding Gtk+ widgets into Dw widgets simpler, see the -documentation of GtkLayout in the Gtk+ tutorial for details. - -GtkDwViewport contains at most one top-level Dw Widget, if it exists. -The Gtk+ methods of GtkDwViewport are more or less mapped on the -methods of the DwWidget. In detail: - - - Dw_gtk_viewport_size_allocate will call a_Dw_widget_set_width, - a_Dw_widget_set_ascent (with allocation->height) and - a_Dw_widget_set_descent (with zero as argument), and then allocate - the Dw widget at the size returned by a_Dw_widget_size_request. - - - Dw_gtk_viewport_draw and Dw_gtk_viewport_expose will call - a_Dw_widget_draw, which will emit the "draw" signal. - - - Handling of mouse events is mostly done in Dw_widget_mouse_event, - see DwWidget.txt for details. Note that the functions return - FALSE, if the event was not processed, so that they are delivered - to the parent widget(s) of the GtkDwViewport, this scheme e.g. - prevents dragging of the viewport (done by GtkScrolledFrame) when - pressing mouse button 2 on a link. - -You may call gtk_container_set_border_width for a border around the -scrolled area.
--- a/doc/DwImage.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +0,0 @@ -Jan 2001, S.Geerken@ping.de -Last update: Dec 2004 - -======= -DwImage -======= - -A widget for displaying images and handling image maps. - - -Image Maps -========== - -Client Side Image Maps ----------------------- -You must first create a list of image maps: Allocate a DwImageMapList, -and initialize it by calling a_Dw_image_map_list_init. Adding a map is -done by a_Dw_image_map_list_add_map. a_Dw_image_map_list_add_shape -adds a shape to the last map. For the meaning of the link argument, -see Section "Signals". - -Image maps are referred by a URL (not only by a name). But currently, -the image map list is stored in DilloHtmlLB and there is no -possibility to parse documents without rendering, so images can only -use maps defined in the same document. - -To use a map in an image, call a_Dw_image_set_usemap with the image, -the map list, and the URL of the map. Passing the whole list makes it -possible to use maps parsed after the image is created. - - -Server Side Image Maps ----------------------- -To use images for server side image maps, you must call -a_Dw_image_set_ismap and the style must contain a valid link -element. See section "Signals" for more details. - - -Signals -======= - -There are five signals, which can be connected to process actions with -links. All have at least three arguments: - - - link is the link element of the DwStyle (server side image maps) - or DwImageMapShape (client side image maps). The value is an - integer, which is currently only used for hypertext links. But - generally, it depends on the signal callback how this value is - used. - - - x and y are, when server side image maps are used, the relative - coordinates of the mouse pointer, otherwise always -1. - -Note that, unlike by DwPage before, no cursors are set. Instead, the -signal callback function has to do this. - -The signals: - - - void link_entered (DwImage *image, - gint link, gint x, gint y) - - Emitted when the link the mouse pointer is over has - changed. "Changed" includes link, x and y, so this signal is also - emitted each time the pointer is moved within a server side image - map. If the pointer is outside of a link, all arguments have the - value -1. - - - - void link_pressed (DwImage *image, - gint link, gint x, gint y, - GdkEventButton *event) - - Emitted when the user presses a mouse button _inside_ a link, - this signal is never emitted with link = -1. You can use the - event to get information about the button, shift keys, etc. - - - - void link_released (DwImage *image, - gint link, gint x, gint y, - GdkEventButton *event) - - - void link_clicked (DwImage *image, - gint link, gint x, gint y, - GdkEventButton *event) - - Analogue to link_pressed. - - - void void (*image_pressed) (DwImage *page, - GdkEventButton *event) - - Emitted when the user presses the mouse button on an image which - has no related map. In some cases, it may be neccessary to - suppress event processing by a_Dw_widget_set_button_sensitive(). - - -Future Extentions -================= - -(See also Imgbuf.txt, what is named DilloImageBuffer here, has been -implemented under the name Imgbuf.) - -These are some ideas for a different design, which will solve several -problems (image transparency, memory usage when implementing a global -size factor): - -1. Instead of a guchar array, a new data type, DilloImageBuffer, - should be used (DICacheEntry::ImageBuffer and DwImage::buffer). Any - access is done by function calls. Copying the lines (in - a_Image_write) is done by a_Image_buffer_copy_line, etc. The call to - Image_line becomes obsolete, since DilloImageBuffer will deal with - different types: indexed, RGB, gray, RGBA, gray-alpha(?). This may - be useful for a more efficient implementation of DilloImageBuffer. - -2. The modules Png, Jpeg, Gif, Image and DICache deal with the - original image size (read by the decoders), while DwImage gets the - "viewed" size (original size, multiplied by the global image - scaling factor) from DilloImageBuffer. - -3. For DwImage, there are further methods which replace the current - direct access. Note to worth: - - - Scaled buffers are shared, reference counters are used. Copying - rows will automatically also affect the related scaled buffers. - - - There are two methods for drawing, one called after expose events - (Dw_image_draw) and another called by a_Dw_image_draw_row. The - exact rules, how the buffer is scaled (this can, e.g., differ by a - pixel or so), is hidden by DilloImageBuffer. - - - As noted above, all DwImage code is based on the viewed size. - -4. The global image scaling factor is used in two places. The HTML - parser must apply it on the WIDTH and HEIGHT attributes of the - <IMG> tag and DilloImageBuffer must use it to scale the inherent - size of an image. There are two modes, which the user can switch - by a dillorc option: - - (i) The original image data is preserved, and an additional scaled - buffer is created: - - +-------+ +------------------+ additional - | Image | -- copy --> | DilloImageBuffer | --> scaled - +-------+ rows | (original size) | buffers - +------------------+ - | ^ - | | - scale requests - each row for scaled - | buffers - | | - v | - +------------------+ - | DilloImageBuffer | - | (viewed size) | - +------------------+ - ^ - | - +---------+ - | DwImage | - +---------+ - - (ii) The original data gets lost just after scaling: - - +-------+ +------------------+ - | Image | -- copy --> | DilloImageBuffer | --> scaled - +-------+ rows | (viewed size) | buffers - +------------------+ - ^ - | - +---------+ - | DwImage | - +---------+ - - (ii) uses generally less memory, while in some cases leads to a - lower rendering quality, as in this example: - - "foo.png" has a size of 100x100 pixels, the image scaling factor is - 50%, and the following HTML sniplet is rendered: - - <img src="foo.png"> - <img src="foo.png" width=200 height=200> - - The first image is displayed at a size of 50x50, the second at - 100x100. (i) will, for the second, use the original buffer, but - (ii) will enlarge the buffer, which was scaled down before, so - resulting in a "pixelized" image. - -5. Any implementation of DilloImageBuffer will handle transparency - independent of the background, i.e., the background colour will not - be used anymore. The first implementation may be based on GdkRGB - and (when needed) dithered clipping bitmaps. Better implementations - may then be developed in the future. - -6. Background images: The modules Image and DICache do no longer - access the DwImage directly, all calls are replaced by an - Interface, which is then implemented by DwImage and an appropriate - structure for background images (part of DwStyle). The interface is - in C realized by a struct of function pointers, and a generic - pointer on DwImage, etc. - -7. If someone really needs it, animated GIF's may be considered.
--- a/doc/DwPage.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,152 +0,0 @@ -Nov 2001, S.Geerken@ping.de -Last update: Dec 2004 - -====== -DwPage -====== - -A widget for displaying texts. It is (currently) the main widget for -rendering HTML documents. - - -Signals -======= - -DwPage defines the same signals as DwImage, except "image_pressed", -with the exception that the coordinates are always -1. See -DwImage.txt for more details. - - -Collapsing Spaces -================= - -The idea behind this is that every text box has a specific vertical -space around and that they are combined to one space, according to -rules stated below. A rule is either a paragraph within a DwPage -widget, or a DwPage within a DwPage widget, in a single line; the -latter is used for indented boxes and list items. - -The rules: - - 1. If a box is following another, the space between them is the - maximum of both box spaces: - - +---------+ - |/////////| - |/////////| +---------+ - +---------+ |/////////| - | A | |/////////| - +---------+ +---------+ - |/////////| | A | - |/////////| +---------+ - +---------+ are combined like this: |/////////| - |XXXXXXXXX| - +---------+ +---------+ - |\\\\\\\\\| | B | - +---------+ +---------+ - | B | |\\\\\\\\\| - +---------+ +---------+ - |\\\\\\\\\| - +---------+ - - 2. a) If one box is the first box within another, the upper space - of these boxes collapse. b) The analogue is the case for the - last box: - - +---------+ If B and C are put into A, - |/////////| the result is: - |/////////| - +---------+ +---------+ +---------+ - | A | <--+-- |\\\\\\\\\| |/////////| - +---------+ ¦ +---------+ |XXXXXXXXX| - |/////////| | | B | +---------+ - |/////////| | +---------+ | B | - +---------+ | |\\\\\\\\\| +---------+ - | +---------+ |\\\\\\\\\| - | |\\\\\\\\\| - | +---------+ |\\\\\\\\\| - `-- |\\\\\\\\\| +---------+ - |\\\\\\\\\| | C | - |\\\\\\\\\| +---------+ - +---------+ |\\\\\\\\\| - | C | |XXXXXXXXX| - +---------+ |XXXXXXXXX| - |\\\\\\\\\| +---------+ - |\\\\\\\\\| - |\\\\\\\\\| - +---------+ - -For achieving this, there are some features of DwPage: - - - Consequent breaks are automatically combined, according to - rule 1. See the code of a_Dw_page_add_break for details. - - - If a break is added as the first word of the DwPage within - another DwPage, collapsing according to rule 2a is done - automatically. See the code of a_Dw_page_add_break. - - - To collapse spaces according to rule 2b, - a_Dw_page_hand_over_break must be called for the *inner* - widget. The HTML parser does this in Html_eventually_pop_dw. - - -Collapsing Margins -================== - -Collapsing margins, as defined in the CSS2 specification, are, -supported in addition to collapsing spaces. Also, spaces and margins -collapse themselves. I.e., the space between two paragraphs is the -maximum of the space calculated as described in "Collapsing Spaces" -and the space calculated according to the rules for collapsing margins. - -(This is an intermediate hybrid state, collapsing spaces are used in -the current version of dillo, while I implemented collapsing margins -for CSS and integrated it already into the main trunk. For a pure -CSS-based dillo, collapsing spaces will not be needed anymore, and may -be removed for simplicity.) - - -Some Internals -============== - -There are two lists, words and lines. The word list is quite static; -only new words may be added. A word is either text, a widget, a break -or an anchor. Anchors are stored in the text, because it may be -necessary to correct the scroller positions at rewrapping. - -Lines refer to the word list (first and last), they are completely -redundant, i.e., they can be rebuilt from the words. Lines can be -rewrapped either completely or partially (see "Incremental Resizing" -below). For the latter purpose, several values are accumulated in the -lines. See the file "dw_page.h" for details. - - -Incremental Resizing --------------------- -DwPage makes use of incremental resizing as described in Dw.txt, -section "Resizing". The parent_ref is, for children of a DwPage, -simply the number of the line. - -Generally, there are three cases which may change the size of the -widget: - - 1. The available size of the widget has changed, e.g., because the - user has changed the size of the browser window. In this case, - it is necessary to rewrap all the lines. - - 2. A child widget has changed its size. In this case, only a rewrap - down from the line where this widget is located is necessary. - - (This case is very important for tables. Tables are quite at the - bottom, so that a partial rewrap is relevant. Otherwise, tables - change their size quite often, so that this is necessary for a - fast, non-blocking rendering) - - 3. A word (or widget, break etc.) is added to the page. This makes - it possible to reuse the old size by simply adjusting the - current width and height, so no rewrapping is necessary. - -The state of the size calculation is stored in wrap_ref within DwPage, -which has the value -1 if no rewrapping of lines necessary, or -otherwise the line from which a rewrap is necessary. -
--- a/doc/DwRender.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,620 +0,0 @@ -Aug 2004, S.Geerken@ping.de - -=========================== - Dw Render Abstraction -=========================== - -This document describes the rendering abstraction used in Dw. At the -time this document was written, some other documents about Dw were out -of date, and have to be rewritten. - -Sometimes, you will find remarks about the old design (with one -concrete Gtk+ widget instead of the layout/multiple rendering views); -those are useful for those, who are already familiar with the old -design. Furthermore, it makes the explanation often simpler, because -the new design is a bit more complex. - -Naming ------- -As stated in "Dw.txt", the prefix "p_Dw_" is used for functions used -within the whole Dw module, but not outside. Typically, these are -protected functions, which are called by inherited classes. E.g., a -specific widget will have to call p_Dw_widget_queue_resize(), but this -function should not called outside from Dw. - -The "Dw_" prefix is not only used for functions, which use is -restricted to a sub-module, but also for functions used only within -the core of Dw. The distinction between both can simply made, whether -the function is declared as static or not. The core of Dw consists of -the modules Dw_widget and Dw_render, anything else is inherited from -these two modules (widgets, platforms, views). As an example, -Dw_gtk_viewport_queue_resize() is only called in the Dw_widget module, -it should not be called by a widget implementation. - - -Overview -======== - -Rendering of Dw is done in a way resembling the model-view pattern, at -least formally. Actually, the counterpart of the model, the layout -(DwRenderLayout), does a bit more than a typical model, namely -calculating the layout, and the views do a bit less than a typical -view, i.e. only the actual drawing. - -Additionally, there is a structure representing common properties of -the platform, views generally work only together with one specific -platform. A platform is typically related to the underlying UI -toolkit, but other uses may be thought of. - -The general structure looks like this: - - 1 +------------------+ - .---->| DwRenderPlatform | - +----------------+ 1 / +------------------+ - | DwRenderLayout |--< ^ 1 - +----------------+ \ | * - 1 ^ | 1 \ +--------------+ - | | `---->| DwRenderView | - | | * +--------------+ - | | - layout | | toplevel_dw - | | - * | V 0..1 - +----------+ 0..1 - | DwWidget |--. parent - +----------+ | - * | | - `-------' - (children) - -(This is a bit simplified, actually, only DwContainer has child -widgets, and the relation is only defined in an abstract way). - -DwRenderLayout and DwWidget (including sub classes) are platform and -view independant, i.e., it should be possible to adopt them into -another platform, after suitable implementations of DwRenderPlatform -and DwRenderView have been developed. - -(The only exception is DwEmbedGtk, a widget which, in the old design, -embeds Gtk+ widgets into the DwWidget tree. This will still remain a -platform specific widget, see notes in the section "UI Widgets". - -Furthermore, this design does not yet cover DwStyle, which is still -bound to the Gtk+ platform. It may be simply replaced for other -platforms, but this will lose the possibility to have multiple -implementations of DwRenderPlatform running within the same program. -The same aplies to DwTooltip and Imgbuf.) - -This new design helps to archieve two important goals: - - 1. Abstraction of the actual rendering. Currently, we only have the - normal viewport, but a list of planned implementations can be - found below in this text. - - 2. It makes different views of the same document simple, e.g. the - normal viewport and the preview window. - - 3. It makes portability simpler. - -Vieports are handles by this design, but only in a rather abstract -way, and may be removed completely, i.e., they will be only part of -specific view implementations. This also means, that the distinction -between world coordinates and viewport coordinates vanishes from most -parts of Dw. - - -World -===== - -The world is the whole area, in which content is rendered. For a view -without a viewport, this is the whole itself. A view with a viewport -provides a way, so that the user may see some part of the world within -a (in most cases) smaller window, the viewport. - -The world may have a base line, so that the worls size is described by -three numbers, width, ascent and descent. - -Any view must implement the method set_world_size(), which is called, -whenever the world size changes. For viewports, this will change -scroll bars etc., for views without viewport, this will normally -change the size of the view itself. (Although on this level, "view -size" is not defined. This should not be confused with the viewport -size!) - - -Drawing -======= - -A view must implement several drawing methods, which work on the whole -world. If it is neccesary to convert them (e.g. in DwGtkViewport), -this is done in a way fully transparent to DwWidget and -DwRenderingLayout, instead, this is done by the view implementation. - -There exist following situations: - - - A view gets an expose event: It will delegate this to the - rendering layout, which will then pass it to the widgets, with - the view as a parameter. Eventually, the widgets will call - drawing methods of the view. - - - A widget requests a redraw: In this case, the widget will - delegate this to the layout. The drawing requests are queued, and - compressed. in an this idle function, DwWidget::draw is called - for the toplevel widget, for each view. - - (This is still something to consider, the queueing may be moved - again into the view implementations.) - -If the draw method of a widget is implemented in a way that it may -draw outside of the widget's allocation, it should draw into a -clipping view. A clipping view is a rendering view related to the -actual rendering view, which guarantees that the parts drawn outside -are discarded. At the end, the clipping view is merged into the actual -view. Sample code for widget DwFoo: - - void Dw_foo_draw (DwWidget *widget, - DwRenderView *view, - DwRectangle *area) - { - DwRenderView *clip_view; - - /* 1. Create a clipping view. */ - clip_view = - p_Dw_render_view_get_clipping_view (view, - widget->allocation.x, - widget->allocation.y, - widget->allocation.width - DW_WIDGET_HEIGHT (widget)); - - /* 2. Draw into clip_view. */ - Dw_render_view_do_some_drawing (clip_view, ...); - - /* 3. Draw the children, they receive the clipping view as argument. */ - for (<all relevant children>) { - if (p_Dw_widget_intersect (button->child, area, &child_area)) - p_Dw_widget_draw (child, clip_view, child_area); - } - - p_Dw_render_view_merge_clipping_view (view, clip_view); - } - -A drawing process is always embedded into calls of -DwRenderView::start_drawing() and DwRenderView::finish_drawing(). An -implementation of this are backing pixmaps, to prevent flickering. - - -Viewports and Scrolling Positions -================================= - -Although the design implies that the usage of viewports should be -fully transparent to the Dw_render module, this cannot be fully -archived, for the following reasons: - - 1. Some features, which are used on the level of DwWidget, - e.g. anchors, refer to scrolling positions. - - 2. Some code in DwWidget is currently tightly bound to viewports. - This may be change, by delegating some of this functionality to - viewports, and defining scrolling positions in a more abstract - way. - -Therefor, DwRenderLayout keeps track of the viewport size, the -viewport position, and even the thickness of the scrollbars (or, -generally, "viewport marker"), they are relevant, see below. These -sizes are always equal in all views. However, a given view may not use -viewports at all, and there may be the case, that no view related to a -layout uses viewports, in this case, the viewport size is not defined -at all. - -Unlike world sized, viewports are not considered to have a base line, -i.e., they are described by only two numbers, width and height. - -Viewport Size -------------- -All viewport sizes and positions are the same in all views, which uses -viewports. There are two cases, in which the viewport size changes: - - 1. As an reaction on a user event, e.g. when the user changes the - window size. In this case, the affected view delegates this - change to the layout, by calling - p_Dw_render_layout_vieport_size_changed(). All other views are - told about this, by calling DwRenderView::set_viewport_size(). - - 2. The viewport size may also depend on the visibility of UI - widgets, which depend on the world size, e.g scrollbars, - generally called "viewport markers". This is described in an own - section. - -After the creation of the layout, the viewport size is undefined. When -a view is attached to a layout, and this view is already to be able to -define its viewport size, it may already call -p_Dw_render_layout_vieport_size_changed() within the implementation of -set_layout. If not, it may do this, as soon as the viewport size gets -known. - -Each call of p_Dw_render_layout_vieport_size_changed() will change the -viewport size of all other views, which use viewports, so this -function has to be called with care. - -If there is no view attached, which used viewports, the viewport size -remains undefined. - -Viewport Markers ----------------- -Viewport markers are UI widgets, which display to the user the -relation of the world size and the widget size. Most commonly, -scrollbars will be used. - -When they are not needed, they are hidden, as in the following figure: - - - +--------------------+ - | This is only a | - | very short text. | - | | - | | - | | - +--------------------+ - -but shown, as soon as the world size exceeds the viewport size: - - +------------------+-+ - | In this example, |^| - | there is some |#| - | more text, so |#| - | that the | | - | vertical |v| - +------------------+-+ - -A view using viewports must provide, how large the differences -are. Generally, there are four cases, from the combinations of whether -the world width is smaller (-) or greater (+) than the viewport width, -and whether the world height is smaller (-) or greater (+) than the -viewport height. So there are eight numbers, the horizontal difference -dh, and the vertical difference dv, for the cases --, -+, +-, and ++. - -For scrollbars, the values are rather simple: - - - dh is 0 for the cases -- and -+, and the thickness of the - vertical scrollbar in the cases +- and ++. - - - dv is 0 for the cases -- and +-, and the thickness of the - horizontal scrollbar in the cases -+ and ++. - -For any view implementation, the following rules must be fullfeeded -(dx means either dh or dv): - - - dx(-+) >= d(--) - - dx(++) >= d(+-) - - dx(+-) >= d(--) - - dx(++) >= d(-+) - -In short, when smaller world dimensions (-) grow (switch to +), the -differences may not become less. - -The sizes of viewport markers are part of the viewport size, the -method DwRenderView::set_viewport_size() has four parameters: - - - two for the size of the viewport, *including* the markers - (i.e. the markers never change the size), and - - - two, which denote the differences between the above and the - actual viewport size, caused by the markers. If a value of these - is 0, the respective marker is hidden, if it is greater than 0, - it is shown. In the latter case, the maximun is calculated, and - passed to all views. - -(Actually, the decision, whether the markers are visible or not, is a -bit more complicated, since the vieport size also defines the size -hints for the topmost widget, which may affect the widget size, and so -the world size. Handling this problem is done within DwRenderLayout, -look at the comments there.) - -Scrolling Positions -------------------- -The scrolling position is the world position at the upper left corner -of the viewport. Views using viewports must - - 1. change this value on request, and - 2. tell other changes to the layout, e.g. caused by user events. - -Applications of scrolling positions (anchors, test search etc.) are -handled by the layout, in a way fully transparent to the views. - - -An Example with Nested Views -============================ -The following example refers to graphical plugins, which are not yet -realized (I have some working proof-of-concept code), but which will -most likely follow the design, which is here shortly described, as -needed to understand the example (since there is no specification of -graphical plugins yet). I included this, to demonstrate, how nested -layouts can be used. - -Graphical plugins will communicate with dillo via two protocols, dpi1 -(for anything not directly related to rendering), and a new protocol, -which is an extension of the XEmbed protocol (see somewhere at -http://freedesktop.org, this is the protocol, which GtkPlug and -GtkSocket use). Within dillo, a socket window will be created, which -window id will be (via dpi1?) passed to the plugin. The plugin will -then create a plugin window, in which the contents of a web recource -is shown, which dillo cannot show natively. - -XEmbed will be extended, so that the plugins may make use of the -extensions, which the Dw size model adds to the XEmbed size -model. Such a plugin behaves (on an abstract level) like a DwWidget, -so following extensions are necessary: - - - a plugin may not simply have a size, but instead distinguish - between ascent and descent, - - a plugin may return width extremes, and - - it is possible to send size hints to the plugin. - -Within Dw, the socket will be realized by a special plugin, -DwSocketGtk (or a respective widget for other platforms), which is a -sub class of DwEmbedGtk, and embeds another UI widget, which will -provide the socket window (for Gtk+, either GtkSocket, or a sub class -of this). - -The plugins may be implemented independently of Dw, they either do not -support the extensions to XEmbed (then, the respective features behave -in a default way), or they may contain there own implementation. -However, Dw may be extracted from dillo, to become an own library. A -plugin using this library may then use a special type of view, -GtkDwFlatView (for plugins based on Gtk+, actually, the UI toolkit for -dillo and the plugin must not be the same, since the protocol will be -UI toolkit independant.) - -This will lead to a structure like this: - - top_layout:DwRenderLayout ----- top_page:DwPage - / \ | - :GtkDwPlatform top_view:GtkDwView `- table:DwTable - | - `- cell:DwTableCell - | - `- socket:DwSocketGtk - | - DILLO gtk_socket:GtkSocket - . -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - . (extension of - . XEmbed) - PLUGIN - plugin_layout:DwRenderLayout ----- dw_flat_view:GtkDwFlatView - \ - `------- foo:DwFoo - -GtkDwFlatView is both an extension of GtkSocket, as well as an -implementation of DwRenderView. - -This case must be equivalent to the case, that the widget "foo" is a -direct child of the widget "cell", since all objects between them only -delegate all functionality. Size hints must so sent as in the -following scenario: - - 1. The view "top_view" receieves an event, which will change the - viewport size, and delegates this to the layout. - - 2. The layout will make size hints of this viewport size, i.e., it - calls the set_* methods of the widget "top_page". - - 3. DwPage::set_* will queue a resize request, which is delegated - to the layout. - - 4. Handling the resize request is done within a idle loop. Here, - size_request is called for the widget "top_page", to determine - the preferred size. - - 5. DwPage::size_request will depend on the size hints, especially, - it will use the hinted size to determine the word wrap width. - Within DwPage::size_request, size hints will be sent to the - child widgets. The size hints sent to the children are those - sent to the page, minus the respective border widths (margins, - borders, paddings). (How the ascent and descent hints should - generally be delegated to the children, is still a matter of - consideration, and may change.) - - 6. DwTable::size_request, which is called within this context, has - a different way to delegate the size hints to the children: - ascent and descent are handled the same way, but the widths are - calculated from the column widths, which are calculated within - DwTable::size_request. - - 7. Via the widget "cell", finally the widget "socket" receives - appropriate size hints. These must be (equally) delegated to - the widget "foo", this is done in a way described in the - following steps. - - 8. The size hints are transmitted via the protocol extending - XEmbed. The Gtk+ widget "dw_flat_view" receives them (via the - widget "gtk_socket"), and delegates them to the respective - layout "plugin_layout". (TODO: How is this done? What has to be - done is to send the size hints to the toplevel widget, but a - view has no access to it.) - - 9. The layout "plugin_layout" will then delegate this (what ever - "this" means), as size hints, to the widget "foo". - - 10. The widget "foo" will queue a size_request, which is delegated - to the layout. In the idle function handling this request, the - recalculation of the widget size will change the world size, - which is delegated to the view "dw_flat_view". - - 11. For GtkDwFlatView, the world size is the view size. For this - reason, it changes its size, to fit the world size. This size - is send to the DwSocket, which will then request a size - request. - - -UI Widgets -========== -A note before: This chapter refers often to Gtk+ as base UI toolkit, -just to make naming simpler, For other UI toolkits, the same, mostly -only with other names, applies. - -In some cases, it is necessary to embed widgets from the UI toolkit -into the view, e.g. to realize HTML forms in dillo. - -The Dw_render module provides no interface at all, instead, this is -completely left to the platform implementations. Below, two design -approaches are discussed, which have following in common: - - 1. There is a special Dw widget, which embeds something related to - the UI widgets (below called DwEmbedGtk). - - 2. This Dw widget, the platform, and the views are tightly bound, - beyond the methods, which the respective interfaces provide. The - Dw widget can simply refer to the platform by - (DwWidget::render_layout->platform, and the platform may refer - to the views, when DwPlatform::attach_view and - DwPlatform::detach_view are implemented. - -General Problems ----------------- -For most UI toolkits, there have to be multiple instances of widgets -in different views. Furthermore, there may be, on the same platform, -different classes for the same widgets. Consider this simple example: - - :DwRenderLayout ------------------- :DwPage - / \ | - ,----' `----. dw:DwEmbedGtk - / \ - view1:GtkDwViewport view2:GtkDwViewport - | | - gtk1:GtkButton gtk2:GtkButton - -This structure represents a page with one button in it, which is, in -the DwWidget tree, represented by the DwEmbedGtk "dw", and, in the -views "view1" and "view2", by the Gtk+ widgets "gtk1" and "gtk2", -respectively. The old approach, where the UI widget (in this case -GtkButton) is not directly applicable, since there must be multiple -instances of this UI widget. - -Here is a more complex example: - - :DwRenderLayout ------------------- :DwPage - / \ | - ,----' `----. dw:DwEmbedGtk - / \ - view1:GtkDwFooView view2:GtkDwBarView - | | - gtk1:GtkFooButton gtk2:GtkBarButton - -In this case, the different views GtkDwFooView and GtkDwBarView deal -with different classes for buttons, GtkFooButton and GtkBarButton. - -Simple Approach ---------------- -Within dillo, the following limitations are reasonable: - - 1. There is only one view instance, which actually needs UI widgets - (GtkDwViewport for Gtk+). There may be multiple views, but these - additional views do not need instances of widgets, e.g. in the - preview, a UI widget is simply shown as a grey box. - - 2. There is only one type of UI widget, i.e. normal Gtk+ widgets. - -Because of these limitations, the implementation of UI widgets is -currently quite simple in dillo. As before, the widget DwEmbedGtk -refers to an instance of a concrete Gtk+ widget. This Gtk+ widget is -told to the platform, of which DwEmbedGtk knows, that it is an -instance of GtkDwPlatform. GtkDwPlatform will add this Gtk+ widget to -the single view, which needs it, and DwEmbedGtk will be responsible of -allocating etc. of the Gtk+ widget. - -Advanced Approach ------------------ -This is a short overview of an approach, which will overcome the -limitations of the simple approach, but with the costs of a greater -complexity. It will be detailed, in the case, that it is implemented. - - +------------+ factory +---------------------+ - | DwEmbedGtk | ---------> | DwGtkWidgetFactory | - +------------+ 1 1 +---------------------+ - | create_foo_widget() | - | create_bar_widget() | - +---------------------+ - . . . - /_\ /_\ /_\ - | | | - - - - - - - - - - - - - - - - - - . - | | - +---------------------+ +---------------------+ | - | DwGtkButtonFactory | | DwGtkListFactoty | (other ...) - +---------------------+ +---------------------+ - | create_foo_widget() | | create_foo_widget() | - | create_bar_widget() | | create_bar_widget() | - +---------------------+ | add_list_item(...) | - +---------------------+ - -DwEmbedGtk refers to a factory, which creates the UI widgets for each -view. For each general widget type (e.g. button, list, ...), there is -an implementation of this interface. - -This interface DwGtkWidgetFactory contains different method for -different views. E.g., when a button is shown, and so DwEmbedGtk -refers to a DwGtkButtonFactoty, GtkDwFooView may need a GtkFooButton, -which is created by create_foo_widget(), while GtkDwBarView may call -create_bar_widget(), to get a GtkBarButton. (This design still makes -it hard to add new views, which then need, say, GtkBazButtons.) - -The concrete factories may contain additional methods, in the diagram -above, DwGtkListFactory must provide a function to add items to the -lists. This method will add a item to all list widget, which were -created by this factory. - - -More Ideas for View Implementations -=================================== - -Preview Window --------------- -The status bar gets a new button, on which the user may click to get a -small image of the small page, in which he can select the viewport -position by dragging a rubber-band rectangle. The actual scaling -factor will probably depend on the aspect ratio of the page. - -(This has already been implemented for Gtk+, as GtkDwPreview and -GtkDwPreviewButton.) - -Graphical Plugin ----------------- -See section "An Example with Nested Views" for explanations. - -====================================================================== - -Alternative design for handling UI widgets: - -- There is a platform *independant* widget, the platform dependencies - are within the factories. - - DwEmbedUI::draw - -> DwRenderView::draw_ui_widget(..., factory) - -Implementation of "draw_ui_widget" in a preview view: - -> draw some gray boxes etc. - -Implementation of "draw_ui_widget" in a normal "bar" view (for platform "foo"): - -> determine that is is a factory for a "baz" widget? - -> (BarFactory*)factory->get_foo_bar_widget(this) - -This method either returns an already created widget, or creates one -with the current state of the factory. "This" is taken as a key. - ----- - - | general | widget specific -----------------------+------------------+------------------------ - platform independant | nothing? | e.g. adding list items -----------------------+------------------+------------------------ - platform dependant | e.g. creating a | ??? - | widget, or | - | informations | - | about drawing in | - | a preview | - -====================================================================== - -Abstraction of DwStyle ----------------------- -structures needed:
--- a/doc/DwStyle.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,310 +0,0 @@ -Apr 2001, S.Geerken@ping.de -Last update: Dec 2004 - -======= -DwStyle -======= - -Styles of Dillo Widgets - - -Note -==== - -DwStyle has derived from DwPageAttr, and its current structure is very -similar to it. In the future, there will be some changes and extensions. -Namely: - - - image maps will be handled differently (done), - - margins, borders, paddings (done), - - background colors/images, and - - cursors and tooltips will perhaps move into DwStyle. - -Furthermore, widgets will probably refer to different styles for -different states. - - -Overview -======== - -DwStyle provides some resources and attributes for drawing widgets, as -well as for parts of a widget (e.g., DwPage uses DwStyle's for its -words). Creating a style is done by filling a DwStyle with the -attributes (except the ref_count), and calling Dw_style_new: - - DwStyle style_attrs, *style; - - style_attrs.foo = bar; - // etc. - style = a_Dw_style_new (&style_attrs, random_window); - // do something with style - -After this, the attributes of style should not be changed anymore, -since styles are often shared between different widgets etc. (see -below). Most times, you simply copy the attributes of another style -and modify them: - - style_attrs = *another_style; - style_attrs.foo = bar; - style = a_Dw_style_new (&style_attrs, random_window); - -The font structure can be created by Dw_style_font_new, in a similar -way (the GdkFont in font_attrs will be ignored), and colors by -Dw_style_color_new, passing 0xrrggbb as an argument. Note that fonts -and colors are only intended to be used in conjunction with DwStyle. - - -Lengths and Percentages -======================= - -DwStyleLength is a simple data type for lengths and percentages: - - - A length refers to an absolute measurement. It is used to - represent the HTML type %Pixels; and the CSS type <length>. - - For CSS lenghts, there are two units: (i) pixels and absolute - units, which have to be converted to pixels (a pixel is, unlike - in the CSS specification, treated as absolute unit), and (ii) the - relative units "em" and "ex" (see below). - - - A percentage refers to a value relative to another value. It is - used for the HTML type %Length; (except %Pixels;), and the CSS - type <percentage>. - - - A relative length can be used in lists of HTML MultiLengths. - -Since many values in CSS may be either lengths or percentages, a -single type is very useful. - -Useful macros and functions ---------------------------- -Macros for creating lengths: - - DW_STYLE_CREATE_LENGTH (n) Returns a length of n pixels. - - DW_STYLE_CREATE_EX_LENGTH (n) Returns a length of n times the - 'x-height' - - DW_STYLE_CREATE_EM_LENGTH (n) Returns a length of n times the - 'font-size' - - DW_STYLE_CREATE_PERCENTAGE (n) Returns a percentage, n is relative - to 1, not to 100. - - DW_STYLE_CREATE_RELATIVE (n) Returns a relative length. - - DW_STYLE_UNDEF_LENGTH Used to indicate unspecified sizes, - errors, and the end of a list of - lengths. - -Furthermore, there are some functions in html.c: - - DwStyleLength Html_parse_length (gchar *attr); - - Returns a length or a percentage, or DW_STYLE_UNDEF_LENGTH in - case of an error. - - DwStyleLength* Html_parse_multi_length (gchar *attr); - - Returns a vector of lengths/percentages. The caller has to free - the result when it is not longer used. - -Macros for examining lengths: - - DW_STYLE_IS_LENGTH (l) Returns TRUE if l is a length. - - DW_STYLE_IS_PERCENTAGE (l) Returns TRUE if l is a percentage. - - DW_STYLE_IS_RELATIVE (l) Returns TRUE if l is a relative - length. - - DW_STYLE_GET_LENGTH (l, f) Returns the value of a length in - pixels, as an integer. f is the - font, this is used if l is based on - font sizes. - - DW_STYLE_GET_PERCENTAGE (l) Returns the value of a percentage, - relative to 1, as a float. - - DW_STYLE_GET_RELATIVE (l) Returns the value of a relative - length, as a float. - - -Representation --------------- -Notes: - - 1. This is not part of the interface and may change! Use the - macros described above. - 2. Negative numbers may not work yet. - -DwStyleLength is represented by an integer (n is the number of bits of -an integer): - - - Undefined lengths are represented by 0. - - - Lenghts in pixel: - - +---+ - - - +---+---+---+---+ - | int value | 0 | 1 | - +---+ - - - +---+---+---+---+ - n-1 3 2 1 0 - - - Lengths in in x-height: - - +---+ - - - +---+---+---+---+ - | real value | 0 | 1 | 1 | - +---+ - - - +---+---+---+---+ - n-1 3 2 1 0 - - - Lengths in in font-size: - - +---+ - - - +---+---+---+---+ - | real value | 1 | 1 | 1 | - +---+ - - - +---+---+---+---+ - n-1 3 2 1 0 - - - Percentages: - - +---+ - - - +---+---+---+---+ - | real value | 0 | 1 | 0 | - +---+ - - - +---+---+---+---+ - n-1 3 2 1 0 - - - Relative lengths: - - +---+ - - - +---+---+---+---+ - | real value | 1 | 1 | 0 | - +---+ - - - +---+---+---+---+ - n-1 3 2 1 0 - -A "real value" is a fixed point number consisting of (m is the number -of bits of the value, not the whole integer): - - +---+ - - - +---+---+ - - - +---+ - | integer part | rest | - +---+ - - - +---+---+ - - - +---+ - m 16 15 0 - -For *internal* use, there are two converting macros, -DW_STYLE_REAL_TO_FLOAT and DW_STYLE_FLOAT_TO_REAL. - - -DwStyle Boxes -============= - -The CSS Box Model ------------------ -For borders, margins etc., DwStyle uses the box model defined by -CSS2. DwStyle contains some members defining these attributes. A -widget must use these values for any calculation of sizes. There are -some helper functions (see dw_style.h). A DwStyle box looks quite -similar to a CSS box: - - - ,-- margin.left - | ,-- border.left - | | ,-- padding.left - |---+---+---| - +---------------------------------------+ --- - | | | margin.top - | +-------------------------------+ | -+- - | | Border | | | border.top - | | +-----------------------+ | | -+- - | | | Padding | | | | padding.top - new widget | | | +---------------+ | | | --- - allocation -->| | | | | | | | - | | | | Content | | | | - former widget ------------>| | | | | - allocation | | | +---------------+ | | | --- - | | | | | | | margin.bottom - | | +-----------------------+ | | -+- - | | | | | border.bottom - | +-------------------------------+ | -+- - | | | padding.bottom - +---------------------------------------+ --- - |---+---+---| - padding.right --' | | - border.right --' | - margin.right --' - -Background colors ------------------ -The background color is stored in style->background_color, which be -NULL (the background color of the parent widget is shining through). - -For toplevel widgets, this color is set as the background color of the -viewport, for other widgets, a filled rectangle is drawn, covering the -content and padding. (This is compliant with CSS2, the background -color of the toplevel element covers the whole canvas.) - -Drawing -------- -There is a new function Dw_widget_draw_widget_box, which should be -called at the beginning of Dw_foo_draw. For parts referring to styles -(e.g., words in a page), Dw_widget_draw_box should be used. - - -Notes on Memory Management -========================== - -Memory management is done by reference counting, a_Dw_style_new -returns a pointer to DwStyle with an increased reference counter, so -you should care about calling Dw_style_unref if it is not used -anymore. You do *not* need to care about the reference counters of -fonts and styles. - -In detail: - - - a_Dw_style_ref is called in - - * a_Dw_widget_set_style, to assign a style to a widget, - - * a_Dw_page_add_text, a_Dw_page_add_widget, - a_Dw_page_add_anchor, to assign a style to a word, - - * and Html_push_tag (often the reference counter is again - decreased shortly after this). - - - a_Dw_unref_style is called in: - - * Dw_page_destroy, Dw_widget_destroy, Html_cleanup_tag, - Html_pop_tag, Html_close, - - * a_Dw_widget_set_style, Html_set_top_font (and several - Html_tag_open_... functions), these functions overwrite an - existing style. - - -HTML Stack -========== - -(This is not DwStyle specific, but may be useful if you are working on -the HTML parser.) - -The topmost element of the HTML stack contains a (reference to a) -style which will be used to add the text to the current page. If you -use a style only for a short while (see Html_tag_open_frame for an -example), you may use it this way: - - style_attrs = *html->stack[html->stack_top].style; - style_attrs.foo = bar; - style = a_Dw_style_new (&style_attrs, random_window); - -Do not forget to unref it afterwards. A good choice for random_window -is html->bw->main_window->window. - -In many cases, you want to set the style for the content of an element -(e.g., <A>). Then you must store it in the stack: - - DwStyle style_attrs, *old_style; - - old_style = html->stack[html->stack_top].style; - style_attrs = *old_style; - style_attrs.foo = bar; - html->stack[html->stack_top].style = - a_Dw_style_new (&style_attrs, random_window); - a_Dw_style_unref (old_style); - -The macro HTML_SET_TOP_ATTR can be used for single attributes, for -changing more attributes, this code should be copied for efficiency.
--- a/doc/DwTable.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -May 2001, S.Geerken@ping.de -Last update: Dec 2004 - -======= -DwTable -======= - -A container widget for rendering tables. - - -The DwTable Widget -================== - -DwTable is a container widget for rendering tables. It aligns other -DwWidgets (normally DwPage), according to the following rules: - - 1. All columns have have the same width W, except: - - - W is less than the minimal column width, or - - W is greater than the maximal column width. - - Furthermore, W is - - - less than all minimal widths of columns not having W as - width, and - - greater than all maximal widths of columns not having W as - width. - - 2. The table tries to use exactly the whole available width, except - if it is not possible, because the it is less/greater than the - minimal/maximal table width. - -This is simple to implement for columns with COLSPAN == 1, using -a_Dw_get_extremes for getting the minimal and maximal widths. For -arbitrary COLSPAN values, an approach described in "Subtables" is -used to get optimal results (as described above) in most cases, while -the rendering remains fast. - - -Subtables -========= - -A table is divided into subtables, which do not (in most cases) share -spanning cells, until single columns are left. Cells spanning the -whole width are removed before dividing further. Example: - - +---+-------+---+ - | A | B | C | - +---+-------+---+ - | D | E | - +---+-------+---+ - | F | G | H | - +---+-------+---+ - ' ' ` ` - ' ' ` ` - +---+-------+ +---+ - | A | B | | C | - +---+-------+ +---+ - removed --> | D | | E | - +---+-------+ +---+ - | F | G | | H | - +---+-------+ +---+ - ' ' ` ` final - ' ' ` ` - +---+ +-------+ - | A | | B | <-. - +---+ +-------+ >- removed - | F | | G | <-' - +---+ +-------+ - final ' ' ` ` - ' ' ` ` - [empty] [empty] - final final - -There is a structure, DwTableSub, for holding all the information. It -is rebuilt when new cells are added. Do not confuse this with nested -tables, these are represented by the Dw widget hierarchy. - -If table cells overlap horizontally, they are (virtually) divided. The -minimal and maximal widths are apportioned to the other columns -(resulting in a non optimal layout): - - +-------+---+---+ - | A | B | C | - +---+---+---+---+ - | D | E | - +---+-----------+ - ' ' ` ` - ' ' ` ` - +-------+ +---+---+ - | A | | B | C | - +---+---+ +---+---+ - | D |1/3| | 2/3 E | - | | E | | | - +---+---+ +-------+ - -Example for a non-optimal case ------------------------------- -The HTML document fragment - - <table> - <tr> - <td colspan="2">Text - <td>LongText - <tr> - <td>Text - <td colspan="2">LongText - </table> - -will result in: - - | 0 | 1 | 2 | - - +------------+----------+ - | Text | LongText | - +------+-----+----------+ - | Text | LongText | - +------+----------------+ - -The width of column 1 is determined by the half of the minimal width -of the LongText. An optimal rendering would be something like: - - ,- 1 - | 0 || 2 | - - +-------+----------+ - | Text | LongText | - +------++----------+ - | Text | LongText | - +------+-----------+ - - -Algorithms -========== - -Calculating extremes --------------------- -The extremes of all subtables are calculated by -Dw_table_sub_get_extremes and stored in DwTableSub: - - minimal/maximal width (sub table) = - - for single column: maximum of all minimal/maximal widths - - otherwise: maximum of - 1. all minimal/maximal widths of cells spanning - the whole width, and - 2. the sum of the minimal/maximal widths of the - sub-subtables - - In step 1, the width argument is used to adjust the maximum - and minimum width of the whole subtable and mark it as fixed. - -todo: describe percentages. - -Calculating column widths -------------------------- -The calculation is based on a fixed width, which is, at the top, the -width set by a_Dw_widget_set_width. This is corrected by the minimal and -maximal width of the whole table, and, if given, the width attribute -of the table. At each level, the available width is always between the -minimal and the maximal width of the subtable. - -For single columns, the width is the passed fixed width. Otherwise: - - 1. Calculate relative widths, they effect the minimal and maximal - widths. (Temporally, not permanently!) - - 2. The sum of these corrected minima may be greater as the fixed - width of the subtable. In this case, decrease them again to - match exactly the fixed width, then use them as sub-subtable - fixed widths and finish. Otherwise, continue: - - 3. If the extremes of the spanning widths of the subtable are - greater than the sum of sub-subtables extremes, adjust the - extremes of sub-subtables which are not fixed, i.e., where no - width argument (either percentage or fixed) freezes the width. - - 4. Use an iteration on the subtables, to determine the column - widths, see Dw_table_sub_calc_col_widths for details. - - 5. After this, apply this recursively on all subtables and pass the - subtable width as fixed width. - - -Borders, Paddings, Spacing -========================== - -Currently, DwTable supports only the separated borders model (see CSS -specification). Borders, paddings, spacing is done by creating DwStyle -structures with values equivalent to following CSS: - - TABLE { - border: outset <table-border>; - border-collapse: separate; - border-spacing: <table-cellspacing> - background-color: <table-bgcolor> - } - - TD TH { - border: inset <table-border>; - padding: <table-cellspacing> - background-color: <td/th-bgcolor> - } - -Here, <foo-bar> refers to the attribute bar of the tag foo. See -Html_open_table and Html_open_table_cell for more details.
--- a/doc/DwWidget.txt Tue Oct 07 21:01:41 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,339 +0,0 @@ -Jan 2001, S.Geerken@ping.de -Last update: Dec 2004 - -======== -DwWidget -======== - -The base object for all Dw widgets. - - -Structures -========== - -DwRectangle ------------ -A replacement for GdkRectangle, the only difference is the use of 32 -instead of 16 bit integers. - - -DwAllocation, DwRequisition ---------------------------- -Similar to GtkAllocation and GtkRequisition. Instead of a height, you -have two members, ascent and descent. - - -DwExtremes ----------- -A structure containing the minimal and maximal width of a widget. See -get_extremes below for details. - - -DwWidget --------- -Some members you may use: - - parent The parent widget. NULL for toplevel widgets. - - flags See below. - - style The style attached to the widget, this must - always be defined, but is not created - automatically. Instead, this has to be done - immediately after creating the widget - (e.g., in a_Web_dispatch_by_type). This style - contains attributes and resources for general - drawing. See DwStyle.txt for details. - -These members should only be used within the "core" (GtkDw*, DwWidget -and DwEmbedGtk): - - viewport The viewport containing the widget. Defined - for all widgets. - - allocation, - requisition, - extremes, - user_requisition These are used to optimize several wrappers, - see below. - - anchors_table See notes on achors. - -Flags ------ -Flags can be set and unset with DW_WIDGET_SET_FLAGS and -DW_WIDGET_UNSET_FLAGS. For reading flags use the macros DW_WIDGET_... - - DW_NEEDS_RESIZE - DW_EXTREMES_CHANGED Denotes that the widget must be resized. Used - only internally. See Dw.txt and the source - for more details. - - DW_NEEDS_ALLOCATE Set to overide the optimation in - a_Dw_widget_size_allocate. Used only - internally. - - DW_REALIZED Set when the widget is realized. Should be - used to prevent crashes in certain - situations. - -Following flags describe characteristics of widgets and are typically -set in the init function: - - DW_USES_HINTS A widget with this flag set has a complex way - to deal with sizes, and should - - - implement the functions set_width, - set_ascent, set_descent, and - get_extremes, and - - deal completely with width and height - in widget->style. - - Examples are DwPage and DwTable. Other - widgets, like DwImage and DwHRuler, are much - simpler and don't have to set this flag. For - these widgets, much of the size calculation - is done by the parent widget. - - This flag is unset by default. - - DW_HAS_CONTENT If this flag is set, more space is reserved - for the widget in some circumstances. E.g., - if an image has a width of 100%, it makes - sense to use more space within a table cell, - as compared to a horizontal ruler, which does - not "have a content". - - This flag is set by default. - - -Signal Prototypes -================= - - - void size_request (DwWidget *widget, - DwRequisition *requisition); - - Similar to Gtk. - - void get_extremes (DwWidget *widget, - DwExtremes *extremes); - - Return the maximal and minimal width of the widget, equivalent - to the requisition width after calling set_width with zero and - infinitive, respectively. This is important for fast table - rendering. Simple widgets do not have to implement this; the - default is the requisition width for both values. - - - void size_allocate (DwWidget *widget, - DwAllocation *allocation); - - Similar in Gtk. Note: allocation has world coordinates. - - - void set_width (DwWidget *widget, - guint32 width); - - - void set_height (DwWidget *widget, - guint32 height); - - These are hints by the caller, which *may* influence the size - returned by size_request. The implementation should call - Dw_widget_queue_resize if necessary. In most cases, these - signals do not have to be implemented. Currently, only the - DwPage widget uses this to determine the width for rewrapping - text (note that the resulting width returned by - Dw_page_size_request may be _bigger_) and relative sizes of the - children. - - - void draw (DwWidget *widget, - DwRectangle *area, - GdkEventExpose *event); - - Draw the widget's content in the specified area. It may either - be caused by an expose event, or by an internal drawing request - (e.g., followed by resizing of widgets). In the first case, you - get the *original* expose event as third argument. In the - latter, event is NULL. The area argument has widget - coordinates. A DwContainer is responsible for drawing its - children. - - (Since DwWidget's are always windowless, there was no need for - two signals, "draw" and "expose_event".) - - - void realize (DwWidget *widget); - - Create all necessary X resources. Called when either the - viewport (top-level widgets) or, respectively, the parent Dw - widget is realized, or an widget is added to an already - realized Dw widget/viewport. - - - void unrealize (DwWidget *widget); - - Remove created X resources. - - - gint button_press_event (DwWidget *widget, - guint32 x, - guint32 y, - GdkEventButton *event); - - This signal is emitted when the user presses a mouse button in - a DwWidget. x and y are the coordinates relative to the origin - of the widget, event is the *original* event, which may, e.g., - be used to determine the number of the pressed button, the state - of the shift keys, etc. The implementation of this signal - should return TRUE, if the event has been processed, otherwise - FALSE. - - A DwContainer is *not* responsible for delivering button press - events to its children. Instead, Dw first emits the - button_press_event signal for the most inner widgets and - continues this for the parents, until TRUE is returned. - - - gint button_release_event (DwWidget *widget, - guint32 x, - guint32 y, - GdkEventButton *event); - - Compare button_press_event. - - - gint motion_notify_event (DwWidget *widget, - guint32 x, - guint32 y, - GdkEventMotion *event); - - Compare button_press_event. event may be NULL when the call was - caused by something different than a "real" motion notify event. - E.g., either when widgets are moved (not yet implemented), or the - viewport. - - - gint enter_notify_event (DwWidget *widget, - DwWidget *last_widget, - GdkEventMotion *event); - - These "events" are simulated based on motion nofify events. - event is the *original* event (may also be NULL in some cases). - last_widget is the widget in which the pointer was in before. - - - gint leave_notify_event (DwWidget *widget, - DwWidget *next_widget, - GdkEventMotion *event); - - Compare enter_notify_event. next_widget is the widget the - pointer is now in. - - -Useful Internal Functions and Macros -==================================== - - - gint Dw_widget_intersect (DwWidget *widget, - DwRectangle *area, - DwRectangle *intersection); - - Calculates the intersection of widget->allocation and area, - returned in intersection (in widget coordinates!). Typically - used by containers when drawing their children. Returns whether - intersection is not empty. - - - gint32 Dw_widget_x_viewport_to_world (DwWidget *widget, - gint16 viewport_x); - - - gint32 Dw_widget_y_viewport_to_world (DwWidget *widget, - gint16 viewport_y); - - - gint16 Dw_widget_x_world_to_viewport (DwWidget *widget, - gint32 world_x); - - - gint16 Dw_widget_y_world_to_viewport (DwWidget *widget, - gint32 world_y); - - These functions convert between world and viewport coordinates. - - - void Dw_widget_queue_draw (DwWidget *widget); - - - void Dw_widget_queue_draw_area (DwWidget *widget, - gint32 x, - gint32 y, - guint32 width, - guint32 height); - - - void Dw_widget_queue_clear (DwWidget *widget); - - - void Dw_widget_queue_clear_area (DwWidget *widget, - gint32 x, - gint32 y, - guint32 width, - guint32 height); - - Equivalents to the Gtk+ functions. They (currently) result in a - call of gtk_widget_xxx_area with the viewport as first - argument. x and y are widget coordinates. - - - void Dw_widget_queue_resize (DwWidget *widget, - gint ref, - gboolean extremes_changed); - - Similar to gtk_widget_queue_resize. Call this function when the - widget has changed its size. The next call to - Dw_xxx_size_request should then return the new size. - - See Dw.txt for explanation on how to use the ref argument, - extremes_changed specifies whether the extremes have changed - (the latter is often not the case for an implementations of - set_{width|ascent|descent}). - - - void Dw_widget_set_anchor (DwWidget *widget, - gchar *name, - int pos); - - Add an anchor to a widget. The name will not be copied, it has - to be stored elsewhere (DwPage e.g. stores it in the DwPageWord - structure). - - - void a_Dw_widget_set_cursor (DwWidget *widget, - GdkCursor *cursor) - - Set the cursor for a DwWidget. cursor has to be stored - elsewhere, it is not copied (and not destroyed). If cursor is - NULL, the cursor of the parent widget is used. - - (This will probably be changed in the future and replaced by a - common style mechanism.) - - - DW_WIDGET_WINDOW (widget) - - Returns the window a widget should draw into. - - -External Functions -================== - - - void a_Dw_widget_set_usize (DwWidget *widget, - guint32 width, - guint32 ascent, - guint32 descent); - - Override the "desired" size of a widget. Further calls of - a_Dw_widget_request_size will return these values, except those - specified as -1. A possible use shows Html_add_widget in - html.c. - - (This will probably be removed. Instead DwStyle should be used.) - - - - void a_Dw_widget_set_bg_color (DwWidget *widget, - gint32 color); - - Set the background color of a widget. This works currently only - for the top-level widget. In this case, the background color of - the GtkDwViewport is changed. In future, background colors for - all widgets will be needed, e.g., for table cells (will be - DwPage's), this will (probably) be based on filled rectangles. - - - void a_Dw_widget_scroll_to (DwWidget *widget, - int pos) - - Scroll viewport to pos (vertical widget coordinate). - -There are furthermore wrappers for the signals, in some cases they -are optimized and/or provide further functionality. In (almost) no -case should you emit the signals directly. See dw_widget.c for more -details.