Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. Using the LibCSS API
  2. ====================
  3.  
  4. This document explains how to use LibCSS. In addition to this document, please
  5. see the examples and the headers (found in /usr/local/include/libcss or a
  6. similar location). Experience with C is assumed.
  7.  
  8. Using the library consists of the following general steps:
  9.  
  10. 1. Initialize the library.
  11. 2. Load one or more CSS files.
  12. 3. Use the Selection API to determine styles.
  13. 4. Use the computed styles.
  14. 5. Shut down the library.
  15.  
  16. Please see example1.c for a demonstration of these steps.
  17.  
  18.  
  19. Initialize the library
  20. ----------------------
  21.  
  22. The library is initialized using css_initialise():
  23.  
  24.   css_initialise("Aliases", myrealloc, 0);
  25.  
  26. The first argument is the pathname of an Aliases file, which maps character
  27. encoding names to their canonical form. For an example, see test/data/Aliases.
  28.  
  29. The 2nd argument is an allocation function. All allocations required by library
  30. initialization will be made by calling this function. It takes the same
  31. arguments as realloc(); a pointer and a size. If pointer is NULL a new block is
  32. being requested. If size is 0 the block should be freed. Otherwise an existing
  33. block is being resized. In many cases this function can simply call realloc().
  34.  
  35. The allocation function also takes a private data pointer, which is the third
  36. argument to css_initialise(). This is not used by LibCSS but may be used to
  37. communicate context to the allocation function.
  38.  
  39. The allocation function pointer and private data pointer are arguments to many
  40. LibCSS functions and work in the same way.
  41.  
  42. css_initialise() returns a css_error value. It is CSS_OK if everything worked,
  43. and an error code otherwise. The error codes are defined in libcss/errors.h.
  44.  
  45. Many LibCSS functions return a css_error value. Checking the return value of
  46. every call that does is advised, for example:
  47.  
  48.   css_error code;
  49.   code = css_initialise("../test/data/Aliases", myrealloc, 0);
  50.   if (code != CSS_OK) {
  51.     fprintf(stderr, "ERROR: css_initialise failed: %s\n",
  52.                     css_error_to_string(code));
  53.     exit(EXIT_FAILURE);
  54.   }
  55.  
  56. LibCSS depends on LibWapcaplet. This must be initialized before LibCSS. For
  57. example:
  58.  
  59.   lwc_code = lwc_initialise(myrealloc, NULL, 0);
  60.   if (lwc_code != lwc_error_ok)
  61.     ...
  62.  
  63.  
  64. Load one or more CSS files
  65. --------------------------
  66.  
  67. A stylesheet is represented by the opaque type css_stylesheet. To create one,
  68. use css_stylesheet_create(), for example:
  69.  
  70.   css_stylesheet *sheet;
  71.   code = css_stylesheet_create(CSS_LEVEL_DEFAULT, "UTF-8", "", NULL,
  72.              false, false, myrealloc, 0, resolve_url, 0, &sheet);
  73.   if (code != CSS_OK)
  74.     ...
  75.  
  76. The arguments are as follows:
  77.  
  78.   css_language_level level
  79.     Which version of CSS the stylesheet should be treated as. It currently has
  80.     no effect and is reserved for future use. The recommended value is
  81.     CSS_LEVEL_DEFAULT.
  82.  
  83.   const char *charset
  84.     The encoding of the stylesheet data, or NULL if LibCSS should attempt to
  85.     detect it. If the encoding is known, for example from the Content-Type
  86.     header or a file attribute, then it should be supplied here.
  87.  
  88.   const char *url
  89.     The URL that the stylesheet was retrieved from. LibCSS uses this along with
  90.     the resolve function (see below) to convert relative URLs in the stylesheet
  91.     (e.g. imports, background images) to absolute URLs. If the stylesheet has
  92.     no URL, use "".
  93.  
  94.   const char *title
  95.     This is intended for the stylesheet title (for example from the <link> tag).
  96.     The title is not used by LibCSS but may be retrieved using
  97.     css_stylesheet_get_title(). May be NULL if there is no title.
  98.  
  99.   bool allow_quirks
  100.  
  101.  
  102.   bool inline_style
  103.  
  104.  
  105.   css_allocator_fn alloc
  106.   void *alloc_pw
  107.  
  108.  
  109.   css_url_resolution_fn resolve
  110.   void *resolve_pw
  111.  
  112.  
  113.   css_stylesheet **stylesheet
  114.     Updated with the newly created stylesheet object.
  115.  
  116. Once the stylesheet has been created, CSS source data can be added to it. LibCSS
  117. parses the data into internal structures. Only data in memory is supported; you
  118. must handle reading from files or the network if required. Data is added using
  119. css_stylesheet_append_data(), for example:
  120.  
  121.   code = css_stylesheet_append_data(sheet, data, length);
  122.   if (code != CSS_OK && code != CSS_NEEDDATA)
  123.     ...
  124.  
  125. The second argument is a pointer to a buffer containing some CSS to be parsed,
  126. with length in bytes given in the 3rd argument.
  127.  
  128. This function may be called repeatedly with more data from the same stylesheet,
  129. for example as data arrives over the network.
  130.  
  131. The return value may be CSS_NEEDDATA instead of CSS_OK. This indicates that more
  132. data may be expected. The two states can be treated identically.
  133.  
  134. When all the data has been supplied, css_stylesheet_data_done() completes the
  135. processing:
  136.  
  137.   code = css_stylesheet_data_done(sheet);
  138.   if (code != CSS_OK)
  139.     ...
  140.  
  141. The stylesheet is now in memory and ready for further use.
  142.  
  143.  
  144. Use the Selection API to determine styles
  145. -----------------------------------------
  146.  
  147. The Selection API is currently the only way to get information about styles from
  148. stylesheets that have been loaded. It takes a document node as input and returns
  149. the computed style that applies to that node. For example, it can be used to
  150. answer the question "What style should this <h1> element have?"
  151.  
  152. CSS selectors can be complex and apply to certain arrangments of elements within
  153. a document tree. Therefore LibCSS has to be able to navigate your document tree
  154. and read attributes of it to determine if a style applies. It does this through
  155. a series of functions that you supply. In this way LibCSS is independent of the
  156. representation of the document. For example, with the style rule:
  157.  
  158.   table h2 { color: red; }
  159.  
  160. when requesting the style for an h2 element node, LibCSS will search its
  161. ancestors for a table element to determine if this style applies.
  162.  
  163. The first step in using the Selection API is creating a selection context. This
  164. is a list of the stylesheets to be used. A context is created using
  165. css_select_ctx_create():
  166.  
  167.   css_select_ctx *select_ctx;
  168.   code = css_select_ctx_create(myrealloc, 0, &select_ctx);
  169.   if (code != CSS_OK)
  170.     ...
  171.  
  172. Stylesheets are added to the context using css_select_ctx_append_sheet():
  173.  
  174.   code = css_select_ctx_append_sheet(select_ctx, sheet, CSS_ORIGIN_AUTHOR,
  175.                                      CSS_MEDIA_ALL);
  176.   if (code != CSS_OK)
  177.     ...
  178.  
  179. When adding a stylesheet, the origin and media can be specified. These are used
  180. in the computation of styles as defined in the CSS specification.
  181.  
  182. Alternatively stylesheets may be added using css_select_ctx_insert_sheet().
  183.  
  184. After the context has been prepared, an empty computed style is created:
  185.  
  186.   css_computed_style *style;
  187.   code = css_computed_style_create(myrealloc, 0, &style);
  188.   if (code != CSS_OK)
  189.     ...
  190.  
  191. The style is then determined for a document node using css_select_style():
  192.  
  193.   code = css_select_style(select_ctx, element_node, 0,
  194.                           CSS_MEDIA_SCREEN, NULL, style,
  195.                           &select_handler, 0);
  196.   if (code != CSS_OK)
  197.     ...
  198.  
  199. The arguments are as follows:
  200.  
  201.   css_select_ctx *ctx
  202.     The selection context, as described above.
  203.  
  204.   void *node
  205.     A pointer to the document node for which the style is required. This is a
  206.     void pointer and may therefore be of any desired type. LibCSS can not use it
  207.     directly; instead it gets information about it through the functions given
  208.     in the handler argument, described below. Usually this will be a node in a
  209.     document tree.
  210.  
  211.   uint32_t pseudo_element
  212.  
  213.   uint64_t media
  214.     The media that the style should apply to. The computed style will only
  215.     consider stylesheets or @media blocks that include this media. See the CSS
  216.     specification for more details.
  217.  
  218.   const css_stylesheet *inline_style
  219.  
  220.   css_computed_style *result
  221.     Updated to the computed style for the node.
  222.  
  223.   css_select_handler *handler
  224.     This is a table of functions that are used to get information from and to
  225.     navigate the document tree, in order to determine if a CSS selector matches
  226.     the document node. Further details are below.
  227.  
  228.   void *pw
  229.     A private data pointer that is passed to each of the handler functions.
  230.  
  231. The types of the handler functions that need to be supplied and the definition
  232. of css_select_handler are given in libcss/select.h. The functions all have the
  233. following in common:
  234.  
  235.  * the first argument is the private data pointer that was the last argument to
  236.    css_select_style()
  237.  
  238.  * the second argument is the document node that is being queried is some way
  239.  
  240.  * the last one or two arguments are pointers that must be updated with the
  241.    required information
  242.  
  243.  * the return value is a css_error and should be CSS_OK if everything worked and
  244.    an error code otherwise
  245.  
  246. For example, the node_name function, which determines the element name of a
  247. node, could be this:
  248.  
  249.   css_error node_name(void *pw, void *n, lwc_string **name)
  250.   {
  251.     my_document_node *node = n;
  252.     *name = lwc_string_ref(node->name);
  253.     return CSS_OK;
  254.   }
  255.  
  256. where my_document_node is your document tree node type (e.g. a struct of some
  257. sort).
  258.  
  259.  
  260. Use the computed styles
  261. -----------------------
  262.  
  263. After the style has been computed by css_select_style() the CSS properties can
  264. finally be retrieved. This is done using the property accessor functions
  265. declared in libcss/computed.h.
  266.  
  267. Note that although struct css_computed_style is declared in computed.h, its
  268. members must not be used directly. The accessors carry out various additional
  269. work to read the properties correctly.
  270.  
  271. For example, the css_computed_color() accessor retrieves the color property:
  272.  
  273.   uint8_t color_type;
  274.   css_color color_shade;
  275.   color_type = css_computed_color(style, &color_shade);
  276.  
  277. In this case color_type can be CSS_COLOR_INHERIT or CSS_COLOR_COLOR. In the
  278. latter case, color_shade contains the actual color in RRGGBBAA format. Together
  279. these two variables encode the possible values for the property given by the
  280. CSS specification.
  281.  
  282.