+\f
+static struct cell_color
+tlo_decode_color (uint32_t c)
+{
+ return (struct cell_color) CELL_COLOR (c, c >> 8, c >> 16);
+}
+
+static void
+tlo_decode_border (const struct tlo_separator *in,
+ struct table_border_style *out)
+{
+ if (in->type == 0)
+ {
+ out->stroke = TABLE_STROKE_NONE;
+ return;
+ }
+
+ out->color = tlo_decode_color (in->type_01.color);
+
+ switch (in->type_01.style)
+ {
+ case 0:
+ out->stroke = (in->type_01.width == 0 ? TABLE_STROKE_THIN
+ : in->type_01.width == 1 ? TABLE_STROKE_SOLID
+ : TABLE_STROKE_THICK);
+ break;
+
+ case 1:
+ out->stroke = TABLE_STROKE_DOUBLE;
+ break;
+
+ case 2:
+ out->stroke = TABLE_STROKE_DASHED;
+ break;
+ }
+}
+
+static struct cell_color
+interpolate_colors (struct cell_color c0, struct cell_color c1, int shading)
+{
+ if (shading <= 0)
+ return c0;
+ else if (shading >= 10)
+ return c1;
+ else
+ {
+ int x0 = 10 - shading;
+ int x1 = shading;
+
+ return (struct cell_color) CELL_COLOR ((c0.r * x0 + c1.r * x1) / 10,
+ (c0.g * x0 + c1.g * x1) / 10,
+ (c0.b * x0 + c1.b * x1) / 10);
+ }
+}
+
+static void
+tlo_decode_area (const struct tlo_area_color *color,
+ const struct tlo_area_style *style,
+ struct table_area_style *out)
+{
+ out->cell_style.halign = (style->halign == 0 ? TABLE_HALIGN_LEFT
+ : style->halign == 1 ? TABLE_HALIGN_RIGHT
+ : style->halign == 2 ? TABLE_HALIGN_CENTER
+ : style->halign == 4 ? TABLE_HALIGN_DECIMAL
+ : TABLE_HALIGN_MIXED);
+ out->cell_style.valign = (style->valign == 0 ? TABLE_VALIGN_TOP
+ : style->valign == 1 ? TABLE_VALIGN_BOTTOM
+ : TABLE_VALIGN_CENTER);
+ out->cell_style.decimal_offset = style->decimal_offset / 20;
+ out->cell_style.decimal_char = '.'; /* XXX */
+ out->cell_style.margin[TABLE_HORZ][0] = style->left_margin / 20;
+ out->cell_style.margin[TABLE_HORZ][1] = style->right_margin / 20;
+ out->cell_style.margin[TABLE_VERT][0] = style->top_margin / 20;
+ out->cell_style.margin[TABLE_VERT][1] = style->bottom_margin / 20;
+
+ out->font_style.bold = style->weight > 400;
+ out->font_style.italic = style->italic;
+ out->font_style.underline = style->underline;
+ out->font_style.markup = false;
+
+ out->font_style.fg[0] = out->font_style.fg[1]
+ = tlo_decode_color (style->text_color);
+
+ struct cell_color c0 = tlo_decode_color (color->color0);
+ struct cell_color c10 = tlo_decode_color (color->color10);
+ struct cell_color bg = interpolate_colors (c0, c10, color->shading);
+ out->font_style.bg[0] = out->font_style.bg[1] = bg;
+
+ free (out->font_style.typeface);
+ out->font_style.typeface = recode_string (
+ "UTF-8", "ISO-8859-1",
+ CHAR_CAST (char *, style->font_name), style->font_name_len);
+ out->font_style.size = -style->font_size * 3 / 4;
+}
+
+static struct pivot_table_look *
+tlo_decode (const struct tlo_table_look *in)
+{
+ struct pivot_table_look *out = pivot_table_look_new_builtin_default ();
+
+ const uint16_t flags = in->tl->flags;
+
+ out->omit_empty = (flags & 0x02) != 0;
+ out->row_labels_in_corner = !in->tl->nested_row_labels;
+ if (in->v2_styles)
+ {
+ out->col_heading_width_range[0] = in->v2_styles->min_col_heading_width;
+ out->col_heading_width_range[1] = in->v2_styles->max_col_heading_width;
+ out->row_heading_width_range[0] = in->v2_styles->min_row_heading_width;
+ out->row_heading_width_range[1] = in->v2_styles->max_row_heading_width;
+ }
+ else
+ {
+ out->col_heading_width_range[0] = 36;
+ out->col_heading_width_range[1] = 72;
+ out->row_heading_width_range[0] = 36;
+ out->row_heading_width_range[1] = 120;
+ }
+
+ out->show_numeric_markers = flags & 0x04;
+ out->footnote_marker_superscripts = !in->tl->footnote_marker_subscripts;
+
+ for (int i = 0; i < 4; i++)
+ {
+ static const enum pivot_border map[4] =
+ {
+ PIVOT_BORDER_DIM_ROW_HORZ,
+ PIVOT_BORDER_DIM_ROW_VERT,
+ PIVOT_BORDER_CAT_ROW_HORZ,
+ PIVOT_BORDER_CAT_ROW_VERT,
+ };
+ tlo_decode_border (in->ss->sep1[i], &out->borders[map[i]]);
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ static const enum pivot_border map[4] =
+ {
+ PIVOT_BORDER_DIM_COL_HORZ,
+ PIVOT_BORDER_DIM_COL_VERT,
+ PIVOT_BORDER_CAT_COL_HORZ,
+ PIVOT_BORDER_CAT_COL_VERT,
+ };
+ tlo_decode_border (in->ss->sep2[i], &out->borders[map[i]]);
+ }