[gnumeric] xls: style export improvements.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] xls: style export improvements.
- Date: Fri, 9 Mar 2012 18:41:40 +0000 (UTC)
commit 30efc6e22a2b0dc93152b4e155943a5ce7f5f3bd
Author: Morten Welinder <terra gnome org>
Date: Fri Mar 9 13:41:19 2012 -0500
xls: style export improvements.
ChangeLog | 8 +
NEWS | 1 +
plugins/excel/ChangeLog | 13 ++
plugins/excel/ms-excel-write.c | 37 ++--
plugins/excel/xlsx-write.c | 2 +-
plugins/openoffice/ChangeLog | 5 +
plugins/openoffice/openoffice-write.c | 6 +-
src/sheet-style.c | 290 ++++++++++++++++++---------------
src/sheet-style.h | 10 +-
src/sheet.c | 2 +-
10 files changed, 215 insertions(+), 159 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 95c501c..2c64b04 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-03-09 Morten Welinder <terra gnome org>
+
+ * src/sheet-style.c (sheet_style_is_default)
+ (sheet_style_get_nondefault_extent): New function.
+ (sheet_style_has_visible_content, sheet_style_most_common_in_col): Delete.
+ (sheet_style_get_extent): Drop col_styles argument. All callers
+ changed.
+
2012-03-08 Morten Welinder <terra gnome org>
* src/expr-name.c (expr_name_set_pos): Make this work even without
diff --git a/NEWS b/NEWS
index 3bb1498..09191d2 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,7 @@ Morten:
* Improve xls image export. [Part of #671513]
* Fix sheet object order on xls export.
* Fix xls export for formulas in conditions. [Part of #671513]
+ * Export non-visible style stuff to xls. [Part of #671513]
--------------------------------------------------------------------------
Gnumeric 1.11.2
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index acdc7c9..33d6bd7 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,16 @@
+2012-03-09 Morten Welinder <terra gnome org>
+
+ * xlsx-write.c (xlsx_write_sheet): Use new
+ sheet_style_most_common.
+
+ * ms-excel-write.c (excel_sheet_extent): Use new
+ sheet_style_get_nondefault_extent.
+ (gather_styles): Gather styles for all columns.
+ (excel_write_colinfos): Ensure a column style for all columns.
+ (excel_sheet_write_block): Drop only styles that differ from the
+ column default. Visibility is irrelevant.
+ (excel_sheet_new): Use new sheet_style_most_common.
+
2012-03-08 Morten Welinder <terra gnome org>
* ms-formula-write.c (excel_write_formula): Base length
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index 55f655c..75796be 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -211,10 +211,16 @@ excel_sheet_extent (Sheet const *sheet, GnmRange *extent, GnmStyle **col_styles,
int maxcols, int maxrows, GOIOContext *io_context)
{
int i;
+ GnmRange r;
/* Ignore spans and merges past the bound */
*extent = sheet_get_extent (sheet, FALSE);
+ range_init (&r, 0, 0,
+ MAX (maxcols, gnm_sheet_get_max_cols(sheet)) - 1,
+ MAX (maxrows, gnm_sheet_get_max_rows(sheet)) - 1);
+ sheet_style_get_nondefault_extent (sheet, extent, &r, col_styles);
+
if (extent->end.col >= maxcols) {
go_io_warning (io_context,
ngettext("Some content will be lost when saving. "
@@ -240,8 +246,6 @@ excel_sheet_extent (Sheet const *sheet, GnmRange *extent, GnmStyle **col_styles,
extent->end.row = maxrows - 1;
}
- sheet_style_get_extent (sheet, extent, col_styles);
-
/* include collapsed or hidden rows */
for (i = maxrows ; i-- > extent->end.row ; )
if (!colrow_is_empty (sheet_row_get (sheet, i))) {
@@ -2406,7 +2410,6 @@ xf_init (XLExportBase *xle)
if (xle->xf.default_style == NULL)
xle->xf.default_style = gnm_style_new_default ();
else {
- gnm_style_dump (xle->xf.default_style);
gnm_style_ref (xle->xf.default_style);
}
@@ -2587,16 +2590,16 @@ static void
gather_styles (ExcelWriteState *ewb)
{
unsigned i;
- int col;
- ExcelWriteSheet *esheet;
for (i = 0; i < ewb->esheets->len; i++) {
- esheet = g_ptr_array_index (ewb->esheets, i);
- sheet_cell_foreach (esheet->gnum_sheet,
+ ExcelWriteSheet *esheet = g_ptr_array_index (ewb->esheets, i);
+ Sheet *sheet = esheet->gnum_sheet;
+ int col, cols = MIN (XLS_MaxCol, gnm_sheet_get_max_cols(sheet));
+ sheet_cell_foreach (sheet,
(GHFunc) cb_cell_pre_pass, &ewb->base);
- sheet_style_foreach (esheet->gnum_sheet,
+ sheet_style_foreach (sheet,
(GHFunc) cb_accum_styles, &ewb->base);
- for (col = 0; col < esheet->max_col; col++) {
+ for (col = 0; col < cols; col++) {
ExcelStyleVariant esv;
esv.style = esheet->col_style[col];
esv.variant = 0;
@@ -3726,12 +3729,11 @@ excel_write_colinfos (BiffPut *bp, ExcelWriteSheet *esheet)
ColRowInfo const *ci, *info;
int first_col = 0, i;
guint16 new_xf, xf = 0;
+ int cols = MIN (XLS_MaxCol, gnm_sheet_get_max_cols (esheet->gnum_sheet));
- if (esheet->max_col <= 0)
- return;
info = sheet_col_get (esheet->gnum_sheet, 0);
xf = esheet->col_xf [0];
- for (i = 1; i < esheet->max_col; i++) {
+ for (i = 1; i < cols; i++) {
ci = sheet_col_get (esheet->gnum_sheet, i);
new_xf = esheet->col_xf [i];
if (xf != new_xf || !colrow_equal (info, ci)) {
@@ -5122,7 +5124,7 @@ excel_sheet_write_DBCELL (ExcelWriteSheet *esheet,
*
* See: 'Finding records in BIFF files'
*/
-static guint32
+guint32
excel_sheet_write_block (ExcelWriteSheet *esheet, guint32 begin, int nrows,
GArray *dbcells)
{
@@ -5163,8 +5165,8 @@ excel_sheet_write_block (ExcelWriteSheet *esheet, guint32 begin, int nrows,
/* Save start pos of 1st cell in row */
r.start.row = r.end.row = row;
rc_start [row - begin] = ewb->bp->streamPos;
- if (! (NULL != sheet_row_get (sheet, row) ||
- sheet_style_has_visible_content (sheet, &r)))
+ if (sheet_row_get (sheet, row) == NULL &&
+ sheet_style_is_default (sheet, &r, esheet->col_style))
continue;
has_content = TRUE;
for (col = 0; col < max_col; col++) {
@@ -5500,9 +5502,8 @@ excel_sheet_new (ExcelWriteState *ewb, Sheet *sheet,
g_return_val_if_fail (ewb, NULL);
esheet->col_xf = g_new (guint16, gnm_sheet_get_max_cols (sheet));
- esheet->col_style = g_new (GnmStyle*, gnm_sheet_get_max_cols (sheet));
- excel_sheet_extent (sheet, &extent, esheet->col_style,
- maxcols, maxrows, ewb->io_context);
+ esheet->col_style = sheet_style_most_common (sheet, TRUE);
+ excel_sheet_extent (sheet, &extent, esheet->col_style, maxcols, maxrows, ewb->io_context);
esheet->gnum_sheet = sheet;
esheet->streamPos = 0x0deadbee;
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index 1338a16..4f7553b 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -1927,7 +1927,7 @@ xlsx_write_sheet (XLSXWriteState *state, GsfOutfile *dir, GsfOutfile *wb_part, u
GnmStyle **col_styles;
state->sheet = workbook_sheet_by_index (state->base.wb, i);
- col_styles = g_new (GnmStyle*, XLSX_MAX_COLS);
+ col_styles = sheet_style_most_common (state->sheet, TRUE);
excel_sheet_extent (state->sheet, &extent, col_styles,
XLSX_MAX_COLS, XLSX_MAX_ROWS, state->io_context);
cell_extent = sheet_get_cells_extent (state->sheet);
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index 944cca0..551e22f 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,8 @@
+2012-03-09 Morten Welinder <terra gnome org>
+
+ * openoffice-write.c (odf_write_sheet): Use new
+ sheet_style_most_common.
+
2012-03-07 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-write.c (odf_write_axis_style): only write user defined
diff --git a/plugins/openoffice/openoffice-write.c b/plugins/openoffice/openoffice-write.c
index 584b8e1..8a38b3a 100644
--- a/plugins/openoffice/openoffice-write.c
+++ b/plugins/openoffice/openoffice-write.c
@@ -3451,7 +3451,7 @@ odf_write_sheet (GnmOOExport *state)
int max_cols = gnm_sheet_get_max_cols (sheet);
int max_rows = gnm_sheet_get_max_rows (sheet);
GnmStyle **col_styles = g_new0 (GnmStyle *, max_cols);
- GnmRange extent, style_extent, cell_extent, r;
+ GnmRange extent, cell_extent, r;
GSList *sheet_merges = NULL;
GnmPageBreaks *pb = sheet->print_info->page_breaks.v;
gboolean repeat_top_use, repeat_left_use;
@@ -3461,9 +3461,7 @@ odf_write_sheet (GnmOOExport *state)
cell_extent = sheet_get_cells_extent (sheet);
extent = range_union (&extent, &cell_extent);
- style_extent = extent;
- /* We only want to get the common column style */
- sheet_style_get_extent (sheet, &style_extent, col_styles);
+ col_styles = sheet_style_most_common (sheet, TRUE);
repeat_top_use = print_load_repeat_range
(sheet->print_info->repeat_top, &r, sheet);
diff --git a/src/sheet-style.c b/src/sheet-style.c
index 5986d67..25e5f41 100644
--- a/src/sheet-style.c
+++ b/src/sheet-style.c
@@ -1925,103 +1925,193 @@ sheet_style_insert_colrow (GnmExprRelocateInfo const *rinfo)
}
static void
-cb_visible_content (GnmStyle *style,
- int corner_col, int corner_row, int width, int height,
- GnmRange const *apply_to, gpointer res)
+cb_style_extent (GnmStyle *style,
+ int corner_col, int corner_row, int width, int height,
+ GnmRange const *apply_to, gpointer user)
{
- *((gboolean *)res) |= gnm_style_visible_in_blank (style);
+ GnmRange *res = user;
+ if (gnm_style_visible_in_blank (style)) {
+ int tmp = corner_col+width-1;
+ if (res->end.col < tmp)
+ res->end.col = tmp;
+ if (res->start.col > corner_col)
+ res->start.col = corner_col;
+
+ tmp = corner_row+height-1;
+ if (res->end.row < tmp)
+ res->end.row = tmp;
+ if (res->start.row > corner_row)
+ res->start.row = corner_row;
+ }
}
/**
- * sheet_style_has_visible_content :
+ * sheet_style_get_extent:
*
- * @sheet :
- * @r :
+ * @sheet: sheet to measure
+ * @res: starting range and resulting range
*
- * Are any of the styles in the target region visible in a blank cell. The
- * implementation is simplistic. We should really ignore borders at the
- * edges IF they have been seen before.
+ * A simple implementation that finds the smallest range containing all visible styles
+ * and containing @res.
*/
-gboolean
-sheet_style_has_visible_content (Sheet const *sheet, GnmRange *src)
+void
+sheet_style_get_extent (Sheet const *sheet, GnmRange *res)
{
- gboolean res = FALSE;
+ GnmRange r;
+
+ range_init_full_sheet (&r, sheet);
foreach_tile (sheet->style_data->styles,
- sheet->tile_top_level, 0, 0, src,
- cb_visible_content, &res);
- return res;
+ sheet->tile_top_level, 0, 0, &r,
+ cb_style_extent, res);
}
-typedef struct {
+struct cb_nondefault_extent {
GnmRange *res;
- GnmStyle **most_common_in_cols;
-} StyleExtentData;
+ GnmStyle **col_defaults;
+};
static void
-cb_style_extent (GnmStyle *style,
- int corner_col, int corner_row, int width, int height,
- GnmRange const *apply_to, gpointer user)
+cb_nondefault_extent (GnmStyle *style,
+ int corner_col, int corner_row, int width, int height,
+ GnmRange const *apply_to, gpointer user_)
{
- StyleExtentData *data = user;
- if (gnm_style_visible_in_blank (style)) {
+ struct cb_nondefault_extent *user = user_;
+ GnmRange *res = user->res;
+ int i;
- /* always check if the column is extended */
- int tmp = corner_col+width-1;
- int i = corner_col;
- if (data->res->end.col < tmp)
- data->res->end.col = tmp;
- if (data->res->start.col > corner_col)
- data->res->start.col = corner_col;
-
- /* only check the row if the style is not the most common in
- * all of the columns in the tile */
- if (data->most_common_in_cols != NULL) {
- for (; i <= tmp ; i++)
- if (style != data->most_common_in_cols[i])
- break;
- if (i > tmp)
- return;
+ for (i = 0; i < width; i++) {
+ int col = corner_col + i;
+ if (col >= apply_to->start.col &&
+ col <= apply_to->end.col &&
+ style != user->col_defaults[col]) {
+ int max_row = MIN (corner_row + height - 1,
+ apply_to->end.row);
+ int min_row = MAX (corner_row, apply_to->start.row);
+
+ res->start.col = MIN (col, res->start.col);
+ res->start.row = MIN (min_row, res->start.row);
+
+ res->end.col = MAX (col, res->end.col);
+ res->end.row = MAX (max_row, res->end.row);
}
- tmp = corner_row+height-1;
- if (data->res->end.row < tmp)
- data->res->end.row = tmp;
- if (data->res->start.row > corner_row)
- data->res->start.row = corner_row;
}
}
-/**
- * sheet_style_get_extent :
- *
- * @sheet :
- * @r :
- * most_common_in_cols : optionally NULL.
- *
- * A simple implementation that finds the smallest range containing all visible styles
- * and containing res. x If @most_common_in_cols is specified it finds the most common
- * style for each column (0..gnm_sheet_get_last_col (sheet)) and ignores that style in
- * boundary calculations.
- */
void
-sheet_style_get_extent (Sheet const *sheet, GnmRange *res,
- GnmStyle **most_common_in_cols)
+sheet_style_get_nondefault_extent (Sheet const *sheet, GnmRange *extent,
+ const GnmRange *src, GnmStyle **col_defaults)
{
- StyleExtentData data;
- GnmRange r;
+ struct cb_nondefault_extent user;
+ user.res = extent;
+ user.col_defaults = col_defaults;
+ foreach_tile (sheet->style_data->styles,
+ sheet->tile_top_level, 0, 0, src,
+ cb_nondefault_extent, &user);
+}
- if (most_common_in_cols != NULL) {
- int i;
- for (i = 0; i < gnm_sheet_get_max_cols (sheet); i++)
- most_common_in_cols[i] = sheet_style_most_common_in_col (sheet, i);
+struct cb_is_default {
+ gboolean res;
+ GnmStyle **col_defaults;
+};
+
+static void
+cb_is_default (GnmStyle *style,
+ int corner_col, int corner_row, int width, int height,
+ GnmRange const *apply_to, gpointer user_)
+{
+ struct cb_is_default *user = user_;
+ int i;
+
+ for (i = 0; user->res && i < width; i++) {
+ if (style != user->col_defaults[corner_col + i])
+ user->res = FALSE;
}
+}
+
+gboolean
+sheet_style_is_default (Sheet const *sheet, const GnmRange *r, GnmStyle **col_defaults)
+{
+ struct cb_is_default user;
+
+ user.res = TRUE;
+ user.col_defaults = col_defaults;
+
+ foreach_tile (sheet->style_data->styles,
+ sheet->tile_top_level, 0, 0, r,
+ cb_is_default, &user);
+
+ return user.res;
+}
+
+
+struct cb_most_common {
+ GHashTable *h;
+ int l;
+ gboolean is_col;
+};
+
+static void
+cb_most_common (GnmStyle *style,
+ int corner_col, int corner_row, int width, int height,
+ GnmRange const *apply_to, gpointer user)
+{
+ struct cb_most_common *cmc = user;
+ int *counts = g_hash_table_lookup (cmc->h, style);
+ int i;
+ if (!counts) {
+ counts = g_new0 (int, cmc->l);
+ g_hash_table_insert (cmc->h, style, counts);
+ }
+
+ if (cmc->is_col)
+ for (i = 0; i < width; i++)
+ counts[corner_col + i] += height;
+ else
+ for (i = 0; i < height; i++)
+ counts[corner_row + i] += width;
+}
+
+GnmStyle **
+sheet_style_most_common (Sheet const *sheet, gboolean is_col)
+{
+ GnmRange r;
+ struct cb_most_common cmc;
+ int *max;
+ GnmStyle **res;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_return_val_if_fail (IS_SHEET (sheet), NULL);
- /* This could easily be optimized */
- data.res = res;
- data.most_common_in_cols = most_common_in_cols;
range_init_full_sheet (&r, sheet);
+ cmc.h = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+ cmc.l = colrow_max (is_col, sheet);
+ cmc.is_col = is_col;
foreach_tile (sheet->style_data->styles,
sheet->tile_top_level, 0, 0, &r,
- cb_style_extent, &data);
+ cb_most_common, &cmc);
+
+ max = g_new0 (int, cmc.l);
+ res = g_new0 (GnmStyle *, cmc.l);
+ g_hash_table_iter_init (&iter, cmc.h);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ int *counts = value;
+ GnmStyle *style = key;
+ int j;
+ for (j = 0; j < cmc.l; j++) {
+ /* FIXME: we really ought to break ties in a
+ consistent way that does not depend on hash
+ order. */
+ if (counts[j] > max[j]) {
+ max[j] = counts[j];
+ res[j] = style;
+ }
+ }
+ }
+ g_hash_table_destroy (cmc.h);
+ g_free (max);
+
+ return res;
}
/****************************************************************************/
@@ -2448,68 +2538,6 @@ style_list_get_style (GnmStyleList const *list, int col, int row)
}
static void
-cb_accumulate_count (GnmStyle *style,
- int corner_col, int corner_row, int width, int height,
- GnmRange const *apply_to, gpointer accumulator)
-{
- gpointer count;
-
- count = g_hash_table_lookup (accumulator, style);
- if (count == NULL) {
- int *res = g_new (int, 1);
- *res = height;
- g_hash_table_insert (accumulator, style, res);
- } else
- *((int *)count) += height;
-}
-
-typedef struct
-{
- GnmStyle *style;
- int count;
-} MostCommon;
-
-static void
-cb_find_max (gpointer key, gpointer value, gpointer user_data)
-{
- MostCommon *mc = user_data;
- int count = *((int *)value);
- if (mc->style == NULL || mc->count < count) {
- mc->style = key;
- mc->count = count;
- }
-
- g_free (value);
-}
-
-/**
- * sheet_style_most_common_in_col :
- * @sheet :
- * @col :
- *
- * Find the most common style in a column.
- * The resulting style does not have its reference count bumped.
- */
-GnmStyle *
-sheet_style_most_common_in_col (Sheet const *sheet, int col)
-{
- MostCommon res;
- GHashTable *accumulator;
- GnmRange r;
-
- range_init_cols (&r, sheet, col, col);
- accumulator = g_hash_table_new (gnm_style_hash, (GCompareFunc) gnm_style_equal);
- foreach_tile (sheet->style_data->styles,
- sheet->tile_top_level, 0, 0, &r,
- cb_accumulate_count, accumulator);
-
- res.style = NULL;
- g_hash_table_foreach (accumulator, cb_find_max, &res);
- g_hash_table_destroy (accumulator);
- return res.style;
-}
-
-static void
cb_find_link (GnmStyle *style,
int corner_col, int corner_row, int width, int height,
GnmRange const *apply_to, gpointer user)
diff --git a/src/sheet-style.h b/src/sheet-style.h
index 696b46c..2238765 100644
--- a/src/sheet-style.h
+++ b/src/sheet-style.h
@@ -44,19 +44,21 @@ void sheet_style_insert_colrow (GnmExprRelocateInfo const *rinfo);
void sheet_style_relocate (GnmExprRelocateInfo const *rinfo);
unsigned int sheet_style_find_conflicts (Sheet const *sheet, GnmRange const *r,
GnmStyle **style, GnmBorder **borders);
-void sheet_style_get_extent (Sheet const *sheet, GnmRange *r,
- GnmStyle **most_common_in_cols);
-gboolean sheet_style_has_visible_content(Sheet const *sheet, GnmRange *src);
+void sheet_style_get_extent (Sheet const *sheet, GnmRange *r);
+void sheet_style_get_nondefault_extent (Sheet const *sheet, GnmRange *extent,
+ const GnmRange *src, GnmStyle **col_defaults);
+gboolean sheet_style_is_default (Sheet const *sheet, const GnmRange *r, GnmStyle **col_defaults);
void style_row_init (GnmBorder const * * *prev_vert,
GnmStyleRow *sr, GnmStyleRow *next_sr,
int start_col, int end_col,
gpointer mem, gboolean hide_grid);
-GnmStyle *sheet_style_most_common_in_col (Sheet const *sheet, int col);
GnmHLink *sheet_style_region_contains_link (Sheet const *sheet, GnmRange const *r);
void sheet_style_foreach (Sheet const *sheet,
GHFunc func,
gpointer user_data);
+GnmStyle **sheet_style_most_common (Sheet const *sheet, gboolean is_col);
+
void sheet_style_init (Sheet *sheet);
void sheet_style_resize (Sheet *sheet, int cols, int rows);
void sheet_style_shutdown (Sheet *sheet);
diff --git a/src/sheet.c b/src/sheet.c
index 70bec82..9d19388 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -2240,7 +2240,7 @@ sheet_get_printarea (Sheet const *sheet,
print_area = sheet_get_extent (sheet, TRUE);
if (include_styles)
- sheet_style_get_extent (sheet, &print_area, NULL);
+ sheet_style_get_extent (sheet, &print_area);
return print_area;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]