#include "output/charts/scree.h"
#include "output/charts/scatterplot.h"
#include "output/driver-provider.h"
+#include "output/group-item.h"
#include "output/message-item.h"
#include "output/options.h"
#include "output/render.h"
#include <pango/pangocairo.h>
#include <stdlib.h>
+#include "gl/c-ctype.h"
#include "gl/c-strcase.h"
#include "gl/intprops.h"
#include "gl/minmax.h"
#define H TABLE_HORZ
#define V TABLE_VERT
-/* The unit used for internal measurements is inch/(72 * XR_POINT). */
+/* The unit used for internal measurements is inch/(72 * XR_POINT).
+ (Thus, XR_POINT units represent one point.) */
#define XR_POINT PANGO_SCALE
/* Conversions to and from points. */
for (i = 0; i < TABLE_N_AXES; i++)
xr->params->min_break[i] = xr->min_break[i];
xr->params->supports_margins = true;
+ xr->params->rtl = render_direction_rtl ();
}
cairo_set_source_rgb (xr->cairo, xr->fg.red, xr->fg.green, xr->fg.blue);
int *widthp, int *brk)
{
unsigned int options = contents->options;
- size_t length;
int w, h;
struct xr_font *font = (options & TAB_FIX ? &xr->fonts[XR_FONT_FIXED]
else
footnote_adjustment = px_to_xr (style->margin[H][1]);
- length = strlen (contents->text);
- if (footnote_adjustment)
+ struct string tmp = DS_EMPTY_INITIALIZER;
+ const char *text = contents->text;
+
+ /* Deal with an oddity of the Unicode line-breaking algorithm (or perhaps in
+ Pango's implementation of it): it will break after a period or a comma
+ that precedes a digit, e.g. in ".000" it will break after the period.
+ This code looks for such a situation and inserts a U+2060 WORD JOINER
+ to prevent the break.
+
+ This isn't necessary when the decimal point is between two digits
+ (e.g. "0.000" won't be broken) or when the display width is not limited so
+ that word wrapping won't happen.
+
+ It isn't necessary to look for more than one period or comma, as would
+ happen with grouping like 1,234,567.89 or 1.234.567,89 because if groups
+ are present then there will always be a digit on both sides of every
+ period and comma. */
+ if (bb[H][1] != INT_MAX)
{
- PangoAttrList *attrs;
- struct string s;
+ const char *decimal = text + strcspn (text, ".,");
+ if (decimal[0]
+ && c_isdigit (decimal[1])
+ && (decimal == text || !c_isdigit (decimal[-1])))
+ {
+ ds_extend (&tmp, strlen (text) + 16);
+ ds_put_substring (&tmp, ss_buffer (text, decimal - text + 1));
+ ds_put_unichar (&tmp, 0x2060 /* U+2060 WORD JOINER */);
+ ds_put_cstr (&tmp, decimal + 1);
+ }
+ }
+ if (footnote_adjustment)
+ {
bb[H][1] += footnote_adjustment;
- ds_init_empty (&s);
- ds_extend (&s, length + contents->n_footnotes * 10);
- ds_put_cstr (&s, contents->text);
- cell_contents_format_footnote_markers (contents, &s);
- pango_layout_set_text (font->layout, ds_cstr (&s), ds_length (&s));
- ds_destroy (&s);
+ if (ds_is_empty (&tmp))
+ {
+ ds_extend (&tmp, strlen (text) + 16);
+ ds_put_cstr (&tmp, text);
+ }
+ size_t initial_length = ds_length (&tmp);
- attrs = pango_attr_list_new ();
+ cell_contents_format_footnote_markers (contents, &tmp);
+ pango_layout_set_text (font->layout, ds_cstr (&tmp), ds_length (&tmp));
+
+ PangoAttrList *attrs = pango_attr_list_new ();
if (style->underline)
pango_attr_list_insert (attrs, pango_attr_underline_new (
PANGO_UNDERLINE_SINGLE));
- add_attr_with_start (attrs, pango_attr_rise_new (7000), length);
+ add_attr_with_start (attrs, pango_attr_rise_new (7000), initial_length);
add_attr_with_start (
- attrs, pango_attr_font_desc_new (font->desc), length);
+ attrs, pango_attr_font_desc_new (font->desc), initial_length);
pango_layout_set_attributes (font->layout, attrs);
pango_attr_list_unref (attrs);
}
else
{
- pango_layout_set_text (font->layout, contents->text, -1);
+ const char *content = ds_is_empty (&tmp) ? text : ds_cstr (&tmp);
+ pango_layout_set_text (font->layout, content, -1);
if (style->underline)
{
pango_attr_list_unref (attrs);
}
}
+ ds_destroy (&tmp);
pango_layout_set_alignment (
font->layout,
else if (is_message_item (item))
{
const struct message_item *message_item = to_message_item (item);
- const struct msg *msg = message_item_get_msg (message_item);
- char *s = msg_to_string (msg, NULL);
+ char *s = msg_to_string (message_item_get_msg (message_item));
r = xr_rendering_create_text (xr, s, cr);
free (s);
}
r = xzalloc (sizeof *r);
r->item = output_item_ref (item);
}
+ else if (is_group_open_item (item))
+ r = xr_rendering_create_text (xr, to_group_open_item (item)->command_name,
+ cr);
return r;
}
/* Draws onto CR */
void
-xr_rendering_draw_all (struct xr_rendering *r, cairo_t *cr)
+xr_rendering_draw (struct xr_rendering *r, cairo_t *cr,
+ int x0, int y0, int x1, int y1)
{
if (is_table_item (r->item))
{
xr_set_cairo (xr, cr);
- render_pager_draw (r->p);
-
+ render_pager_draw_region (r->p, x0 * XR_POINT, y0 * XR_POINT,
+ (x1 - x0) * XR_POINT, (y1 - y0) * XR_POINT);
}
else
xr_draw_chart (to_chart_item (r->item), cr,
xr_render_text (struct xr_driver *xr, const struct text_item *text_item)
{
enum text_item_type type = text_item_get_type (text_item);
- const char *text = text_item_get_text (text_item);
switch (type)
{
- case TEXT_ITEM_TITLE:
- free (xr->title);
- xr->title = xstrdup (text);
- break;
-
- case TEXT_ITEM_SUBTITLE:
- free (xr->subtitle);
- xr->subtitle = xstrdup (text);
- break;
-
- case TEXT_ITEM_COMMAND_CLOSE:
+ case TEXT_ITEM_PAGE_TITLE:
break;
case TEXT_ITEM_BLANK_LINE:
xr_render_message (struct xr_driver *xr,
const struct message_item *message_item)
{
- const struct msg *msg = message_item_get_msg (message_item);
- char *s = msg_to_string (msg, message_item->command_name);
+ char *s = msg_to_string (message_item_get_msg (message_item));
struct text_item *item = text_item_create (TEXT_ITEM_PARAGRAPH, s);
free (s);
struct xr_render_fsm *fsm = xr_create_text_renderer (xr, item);