Commit a57d6d8c authored by Jean Bréfort's avatar Jean Bréfort

Make graphs (and images) not resize with cells by default. [#684450]

parent a48fb1a5
2015-03-30 Jean Brefort <jean.brefort@normalesup.org>
* src/graph.h: add support for absolute anchoring of sheet objects.
* src/item-grid.c: ditto.
* src/sheet-control-gui.c: ditto.
* src/sheet-filter.c: ditto.
* src/sheet-object-cell-comment.c: ditto.
* src/sheet-object-component.c: ditto.
* src/sheet-object-graph.c: ditto and make graphs not anymore resize with
cells by default. [#684450]
* src/sheet-object-image.c: make images don't resize with cells by default.
* src/sheet-object.c : add support for absolute anchoring of sheet objects.
* src/sheet-object.h: ditto.
* src/workbook-view.c: ditto.
* src/xml-sax-read.c: ditto.
* src/xml-sax-write.c: ditto.
2015-03-30 Morten Welinder <terra@gnome.org>
* src/xml-sax-read.c (grammar): Use new libgsf check for "2nd".
......
......@@ -6,6 +6,8 @@ Andreas:
Jean:
* Fix signal handling while running Python. [#744638]
* Implement absolute anchoring for sheet objects.
* Make graphs (and images) not resize with cells by default. [#684450]
Morten:
* xlsx import/export of log axis.
......
2015-03-30 Jean Brefort <jean.brefort@normalesup.org>
* ms-chart.c (ms_excel_chart_read): support absolute sheet object anchoring.
* ms-escher.c (ms_escher_clientanchor): ditto.
* ms-excel-read.c (ms_sheet_obj_anchor_to_pos),
(ms_sheet_realize_obj): ditto.
* ms-excel-write.c (excel_write_autofilter_objs),
(excel_write_other_v8): ditto.
* xlsx-read-drawing.c (xlsx_draw_anchor_start),
(xlsx_drawing_twoCellAnchor_end), (xlsx_drawing_oneCellAnchor_end),
(xlsx_drawing_absoluteAnchor_end), (xlsx_drawing_anchor_pos),
(xlsx_vml_client_data_end): ditto.
* xlsx-read.c: ditto.
* xlsx-write-drawing.c (xlsx_write_drawing_objects): ditto.
2015-03-28 Morten Welinder <terra@gnome.org>
* xlsx-read-drawing.c (xlsx_axis_crossax): Improve parsing. Take
......
......@@ -3825,7 +3825,7 @@ ms_excel_chart_read (BiffQuery *q, MSContainer *container,
static GnmRange const fixed_size = { { 1, 1 }, { 12, 32 } };
SheetObjectAnchor anchor;
sheet_object_anchor_init (&anchor, &fixed_size, NULL,
GOD_ANCHOR_DIR_DOWN_RIGHT);
GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (sog, &anchor);
sheet_object_set_sheet (sog, full_page);
g_object_unref (sog);
......
......@@ -2373,6 +2373,16 @@ ms_escher_clientanchor (GString *buf, SheetObjectAnchor const *anchor)
guint8 *p = tmp + 10;
GSF_LE_SET_GUINT32 (tmp + 4, sizeof (tmp) - 8);
switch (anchor->mode) {
case GNM_SO_ANCHOR_ONE_CELL:
tmp[8] = 2;
break;
case GNM_SO_ANCHOR_ABSOLUTE:
tmp[8] = 3;
break;
default:
break;
}
GSF_LE_SET_GUINT16 (p + 0, anchor->cell_bound.start.col);
GSF_LE_SET_GUINT16 (p + 2, (guint16)(anchor->offset[0]*1024. + .5));
GSF_LE_SET_GUINT16 (p + 4, anchor->cell_bound.start.row);
......
......@@ -391,7 +391,7 @@ static gboolean
ms_sheet_obj_anchor_to_pos (Sheet const * sheet,
G_GNUC_UNUSED MsBiffVersion const ver,
guint8 const *raw_anchor,
GnmRange *range, double offset[4])
GnmRange *range, double offset[4], GnmSOAnchorMode *mode)
{
/* NOTE :
* gnm_float const row_denominator = (ver >= MS_BIFF_V8) ? 256. : 1024.;
......@@ -407,6 +407,17 @@ ms_sheet_obj_anchor_to_pos (Sheet const * sheet,
gsf_mem_dump (raw_anchor, 18);
});
switch (raw_anchor[0]) {
case 2:
*mode = GNM_SO_ANCHOR_ONE_CELL;
break;
case 3:
*mode = GNM_SO_ANCHOR_ABSOLUTE;
break;
default:
*mode = GNM_SO_ANCHOR_TWO_CELLS;
break;
}
/* Ignore the first 2 bytes. What are they ? */
/* Dec/1/2000 JEG: I have not researched it, but this may have some
* flags indicating whether or not the object is anchored to the cell
......@@ -494,6 +505,7 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
SheetObjectAnchor anchor;
SheetObject *so;
GOStyle *style;
GnmSOAnchorMode mode = GNM_SO_ANCHOR_TWO_CELLS;
if (obj == NULL)
return TRUE;
......@@ -518,7 +530,7 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
}
if (ms_sheet_obj_anchor_to_pos (esheet->sheet, container->importer->ver,
attr->v.v_ptr, &range, offsets))
attr->v.v_ptr, &range, offsets, &mode))
return TRUE;
flip_h = ms_obj_attr_bag_lookup (obj->attrs, MS_OBJ_ATTR_FLIP_H);
......@@ -527,10 +539,12 @@ ms_sheet_realize_obj (MSContainer *container, MSObj *obj)
((flip_h == NULL) ? GOD_ANCHOR_DIR_RIGHT : 0) |
((flip_v == NULL) ? GOD_ANCHOR_DIR_DOWN : 0);
sheet_object_anchor_init (&anchor, &range, offsets, direction);
sheet_object_anchor_init (&anchor, &range, offsets, direction, GNM_SO_ANCHOR_TWO_CELLS);
sheet_object_set_anchor (so, &anchor);
}
sheet_object_set_sheet (so, esheet->sheet);
if (mode != GNM_SO_ANCHOR_TWO_CELLS)
sheet_object_set_anchor_mode (so, &mode);
{
gpointer label;
......
......@@ -4251,7 +4251,7 @@ excel_write_autofilter_objs (ExcelWriteSheet *esheet)
r.end.col = 1 + (r.start.col = filter->r.start.col + i);
sheet_object_anchor_init (&anchor, &r, NULL,
GOD_ANCHOR_DIR_DOWN_RIGHT);
GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
if (bp->version >= MS_BIFF_V8) {
guint32 id = excel_write_start_drawing (esheet);
memcpy (buf, obj_v8, sizeof obj_v8);
......@@ -4615,6 +4615,14 @@ excel_write_other_v8 (ExcelWriteSheet *esheet,
? g_hash_table_lookup (esheet->widget_macroname, so)
: NULL;
if (anchor.mode != GNM_SO_ANCHOR_TWO_CELLS) {
double pts[4];
GnmSOAnchorMode mode = anchor.mode;
sheet_object_anchor_to_pts (&anchor, esheet->gnum_sheet, pts);
anchor.mode = GNM_SO_ANCHOR_TWO_CELLS;
sheet_object_pts_to_anchor (&anchor, esheet->gnum_sheet, pts);
anchor.mode = mode; /* this anchor is not valid for gnumeric but is what we need there */
}
if (GNM_IS_CELL_COMMENT (so)) {
static double const offset[4] = { .5, .5, .5, .5 };
GnmRange r;
......@@ -4625,7 +4633,7 @@ excel_write_other_v8 (ExcelWriteSheet *esheet,
r.end.col = r.start.col + 2;
r.end.row = r.start.row + 4;
sheet_object_anchor_init (&anchor, &r, offset,
GOD_ANCHOR_DIR_DOWN_RIGHT);
GOD_ANCHOR_DIR_DOWN_RIGHT, GNM_SO_ANCHOR_TWO_CELLS);
type = MSOT_COMMENT;
flags = 0x4011; /* not autofilled */
do_textbox = TRUE;
......
......@@ -3116,6 +3116,7 @@ xlsx_draw_anchor_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
memset ((gpointer)state->drawing_pos, 0, sizeof (state->drawing_pos));
state->drawing_pos_flags = 0;
state->so_direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
state->so_anchor_mode = GNM_SO_ANCHOR_TWO_CELLS;
}
static void
......@@ -3135,7 +3136,7 @@ xlsx_drawing_twoCellAnchor_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
GnmRange r;
double coords[4];
double size;
int i;
int i, max;
range_init (&r,
state->drawing_pos[COL | FROM],
......@@ -3143,19 +3144,34 @@ xlsx_drawing_twoCellAnchor_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
state->drawing_pos[COL | TO],
state->drawing_pos[ROW | TO]);
switch (state->so_anchor_mode) {
default:
case GNM_SO_ANCHOR_TWO_CELLS:
max = 8;
break;
case GNM_SO_ANCHOR_ONE_CELL:
max = 4;
break;
case GNM_SO_ANCHOR_ABSOLUTE:
max = 0;
break;
}
for (i = 0; i < 8; i+=2) {
ColRowInfo const *cri;
if (i & 2) {
cri = sheet_row_get (state->sheet, state->drawing_pos[i]);
size = cri? cri->size_pts: sheet_row_get_default_size_pts (state->sheet);
} else {
cri = sheet_col_get (state->sheet, state->drawing_pos[i]);
/* FIXME: scaling horizontally just like in xlsx_CT_Col */
size = (cri? cri->size_pts: sheet_col_get_default_size_pts (state->sheet)) * 1.16191275167785;
}
coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700. / size;
if (i < max) {
if (i & 2) {
cri = sheet_row_get (state->sheet, state->drawing_pos[i]);
size = cri? cri->size_pts: sheet_row_get_default_size_pts (state->sheet);
} else {
cri = sheet_col_get (state->sheet, state->drawing_pos[i]);
/* FIXME: scaling horizontally just like in xlsx_CT_Col */
size = (cri? cri->size_pts: sheet_col_get_default_size_pts (state->sheet)) * 1.16191275167785;
}
coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700. / size;
} else
coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700.;
}
sheet_object_anchor_init (&anchor, &r, coords, state->so_direction);
sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
sheet_object_set_anchor (state->so, &anchor);
if (state->cur_style &&
g_object_class_find_property (G_OBJECT_GET_CLASS (state->so), "style"))
......@@ -3177,12 +3193,35 @@ xlsx_drawing_oneCellAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
state->drawing_pos[COL | TO] = state->drawing_pos[COL | FROM] + 5;
state->drawing_pos[ROW | TO] = state->drawing_pos[ROW | FROM] + 5;
state->drawing_pos[COL | TO] = state->drawing_pos[COL | FROM];
state->drawing_pos[ROW | TO] = state->drawing_pos[ROW | FROM];
state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)));
state->so_anchor_mode = GNM_SO_ANCHOR_ONE_CELL;
xlsx_drawing_twoCellAnchor_end (xin, blob);
}
static void
xlsx_drawing_absoluteAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)) |
(1 << (COL | FROM)) | (1 << (ROW | FROM)));
state->so_anchor_mode = GNM_SO_ANCHOR_ABSOLUTE;
xlsx_drawing_twoCellAnchor_end (xin, blob);
}
static void
xlsx_drawing_anchor_pos (GsfXMLIn *xin, xmlChar const **attrs)
{
XLSXReadState *state = (XLSXReadState *)xin->user_state;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (attr_int64 (xin, attrs, "x", state->drawing_pos + (COL | FROM | OFFSET)))
state->drawing_pos_flags |= (1 << (COL | FROM | OFFSET));
else if (attr_int64 (xin, attrs, "y", state->drawing_pos + (ROW | FROM | OFFSET)))
state->drawing_pos_flags |= (1 << (ROW | FROM | OFFSET));
}
static void
xlsx_drawing_ext (GsfXMLIn *xin, xmlChar const **attrs)
{
......@@ -3500,6 +3539,22 @@ GSF_XML_IN_NODE_FULL (START, DRAWING, XL_NS_SS_DRAW, "wsDr", GSF_XML_NO_CONTENT,
GSF_XML_IN_NODE (ONE_CELL, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, &xlsx_drawing_ext, NULL),
GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ONE_CELL, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (DRAWING, ABSOLUTE, XL_NS_SS_DRAW, "absoluteAnchor", GSF_XML_NO_CONTENT,
&xlsx_draw_anchor_start, &xlsx_drawing_absoluteAnchor_end),
GSF_XML_IN_NODE (ABSOLUTE, ABSOLUTE_POS, XL_NS_SS_DRAW, "pos", GSF_XML_NO_CONTENT, &xlsx_drawing_anchor_pos, NULL),
GSF_XML_IN_NODE (ABSOLUTE, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE (ABSOLUTE, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
GSF_XML_IN_NODE_END
};
......@@ -3796,7 +3851,7 @@ xlsx_vml_client_data_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
}
r.end.row = pos;
coords[3] = (state->chart_pos[3] - sum) / size;
sheet_object_anchor_init (&anchor, &r, coords, state->so_direction);
sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
sheet_object_set_anchor (state->so, &anchor);
if (GNM_IS_SOW_LIST (state->so) ||
GNM_IS_SOW_COMBO (state->so))
......
......@@ -196,6 +196,7 @@ typedef struct {
gint64 drawing_pos[8];
int drawing_pos_flags;
GODrawingAnchorDir so_direction;
GnmSOAnchorMode so_anchor_mode;
GnmExprTop const *link_texpr;
/* Legacy drawing state */
......
......@@ -1359,11 +1359,41 @@ xlsx_write_drawing_objects (XLSXWriteState *state, GsfOutput *sheet_part,
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
gsf_xml_out_start_element (xml, "xdr:twoCellAnchor");
xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
res_pts[0], res_pts[1]);
xlsx_write_object_anchor (xml, &anchor->cell_bound.end, "xdr:to",
res_pts[2], res_pts[3]);
switch (anchor->mode) {
case GNM_SO_ANCHOR_TWO_CELLS:
gsf_xml_out_start_element (xml, "xdr:twoCellAnchor");
xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
res_pts[0], res_pts[1]);
xlsx_write_object_anchor (xml, &anchor->cell_bound.end, "xdr:to",
res_pts[2], res_pts[3]);
break;
case GNM_SO_ANCHOR_ONE_CELL:
gsf_xml_out_start_element (xml, "xdr:oneCellAnchor");
xlsx_write_object_anchor (xml, &anchor->cell_bound.start, "xdr:from",
res_pts[0], res_pts[1]);
gsf_xml_out_start_element (xml, "xdr:ext");
gsf_xml_out_add_int (xml, "cx",
xlsx_pts_to_emu (anchor->offset[2]));
gsf_xml_out_add_int (xml, "cy",
xlsx_pts_to_emu (anchor->offset[3]));
gsf_xml_out_end_element (xml);
break;
case GNM_SO_ANCHOR_ABSOLUTE:
gsf_xml_out_start_element (xml, "xdr:absoluteAnchor");
gsf_xml_out_start_element (xml, "xdr:pos");
gsf_xml_out_add_int (xml, "x",
xlsx_pts_to_emu (anchor->offset[0]));
gsf_xml_out_add_int (xml, "y",
xlsx_pts_to_emu (anchor->offset[1]));
gsf_xml_out_end_element (xml);
gsf_xml_out_start_element (xml, "xdr:ext");
gsf_xml_out_add_int (xml, "cx",
xlsx_pts_to_emu (anchor->offset[2]));
gsf_xml_out_add_int (xml, "cy",
xlsx_pts_to_emu (anchor->offset[3]));
gsf_xml_out_end_element (xml);
break;
}
if (GNM_IS_SO_GRAPH (so)) {
char *tmp;
......
2015-03-30 Jean Brefort <jean.brefort@normalesup.org>
* openoffice-read.c (odf_shapes), (odf_shapes_end), (oo_table_end),
(od_draw_frame_start), (odf_line): support absolute sheet object anchoring.
* openoffice-write.c (odf_write_frame_size), (odf_write_line),
(odf_sheet_objects_get), (odf_write_content): ditto.
2015-03-22 Andreas J. Guelzow <aguelzow@pyrshep.ca>
* openoffice-write.c (-odf_write_circle_axes_styles): deleted
......
......@@ -2474,6 +2474,20 @@ oo_table_start (GsfXMLIn *xin, xmlChar const **attrs)
}
}
static void
odf_shapes (GsfXMLIn *xin, xmlChar const **attrs)
{
OOParseState *state = (OOParseState *)xin->user_state;
state->pos.eval.col = -1; /* we use that to know that objects have absolute anchors */
}
static void
odf_shapes_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
{
OOParseState *state = (OOParseState *)xin->user_state;
state->pos.eval.col = 0;
}
static void
odf_init_pp (GnmParsePos *pp, GsfXMLIn *xin, gchar const *base)
{
......@@ -2969,7 +2983,6 @@ odf_validation_help_message_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
odf_pop_text_p (state);
}
static void
odf_adjust_offsets_col (OOParseState *state, int *col, double *x, gboolean absolute)
{
......@@ -3185,12 +3198,16 @@ oo_table_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
SheetObjectAnchor const *old = sheet_object_get_anchor (ob_off->so);
GnmRange cell_base = *sheet_object_get_range (ob_off->so);
odf_adjust_offsets (state, &cell_base.start, &ob_off->frame_offset[0],
&ob_off->frame_offset[1], ob_off->absolute_distance);
odf_adjust_offsets (state, &cell_base.end, &ob_off->frame_offset[2],
&ob_off->frame_offset[3], ob_off->absolute_distance);
if (old->mode != GNM_SO_ANCHOR_ABSOLUTE) {
odf_adjust_offsets (state, &cell_base.start, &ob_off->frame_offset[0],
&ob_off->frame_offset[1], ob_off->absolute_distance);
if (old->mode == GNM_SO_ANCHOR_TWO_CELLS)
odf_adjust_offsets (state, &cell_base.end, &ob_off->frame_offset[2],
&ob_off->frame_offset[3], ob_off->absolute_distance);
}
sheet_object_anchor_init (&new, &cell_base, ob_off->frame_offset,
old->base.direction);
old->base.direction,
old->mode);
sheet_object_set_anchor (ob_off->so, &new);
sheet_object_set_sheet (ob_off->so, state->pos.sheet);
......@@ -7933,9 +7950,9 @@ od_draw_frame_start (GsfXMLIn *xin, xmlChar const **attrs)
GnmRange cell_base;
double frame_offset[4];
gdouble height = 0., width = 0., x = 0., y = 0., end_x = 0., end_y = 0.;
ColRowInfo const *col, *row;
GnmExprTop const *texpr = NULL;
int z = -1;
GnmSOAnchorMode mode;
height = width = x = y = 0.;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2){
......@@ -7964,39 +7981,43 @@ od_draw_frame_start (GsfXMLIn *xin, xmlChar const **attrs)
;
}
cell_base.start.col = cell_base.end.col = state->pos.eval.col;
cell_base.start.row = cell_base.end.row = state->pos.eval.row;
col = sheet_col_get_info (state->pos.sheet, state->pos.eval.col);
row = sheet_row_get_info (state->pos.sheet, state->pos.eval.row);
frame_offset[0] = x;
frame_offset[1] = y;
if (state->pos.eval.col >= 0) {
cell_base.start.col = cell_base.end.col = state->pos.eval.col;
cell_base.start.row = cell_base.end.row = state->pos.eval.row;
if (texpr == NULL || (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)) {
cell_base.end.col = cell_base.start.col;
cell_base.end.row = cell_base.start.row;
frame_offset[2] = width;
frame_offset[3] = height;
mode = GNM_SO_ANCHOR_ONE_CELL;
if (texpr == NULL || (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)) {
frame_offset[2] = x+width;
frame_offset[3] = y+height;
} else {
GnmCellRef const *ref = &texpr->expr->cellref.ref;
cell_base.end.col = ref->col;
cell_base.end.row = ref->row;
frame_offset[2] = end_x;
frame_offset[3] = end_y ;
mode = GNM_SO_ANCHOR_TWO_CELLS;
}
if (texpr)
gnm_expr_top_unref (texpr);
} else {
GnmCellRef const *ref = &texpr->expr->cellref.ref;
cell_base.end.col = ref->col;
cell_base.end.row = ref->row;
frame_offset[2] = end_x;
frame_offset[3] = end_y ;
cell_base.end.col = cell_base.start.col =
cell_base.end.row = cell_base.start.row = 0; /* actually not needed */
frame_offset[2] = width;
frame_offset[3] = height;
mode = GNM_SO_ANCHOR_ABSOLUTE;
}
odf_draw_frame_store_location (state, frame_offset,
(height > 0) ? height : go_nan,
(width > 0) ? width : go_nan);
frame_offset[0] /= col->size_pts;
frame_offset[1] /= row->size_pts;
frame_offset[2] /= col->size_pts;
frame_offset[3] /= row->size_pts;
if (texpr)
gnm_expr_top_unref (texpr);
sheet_object_anchor_init (&state->chart.anchor, &cell_base, frame_offset,
GOD_ANCHOR_DIR_DOWN_RIGHT);
GOD_ANCHOR_DIR_DOWN_RIGHT, mode);
state->chart.so = NULL;
state->chart.z_index = z;
}
......@@ -10496,16 +10517,16 @@ odf_line (GsfXMLIn *xin, xmlChar const **attrs)
{
OOParseState *state = (OOParseState *)xin->user_state;
gnm_float x1 = 0., x2 = 0., y1 = 0., y2 = 0.;
ColRowInfo const *col, *row;
GODrawingAnchorDir direction;
GnmRange cell_base;
double frame_offset[4];
char const *style_name = NULL;
gdouble height, width;
int z = -1;
cell_base.start.col = cell_base.end.col = state->pos.eval.col;
cell_base.start.row = cell_base.end.row = state->pos.eval.row;
GnmSOAnchorMode mode;
cell_base.start.col = state->pos.eval.col;
cell_base.start.row = state->pos.eval.row;
cell_base.end.col = cell_base.end.row = -1;
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]),
......@@ -10567,20 +10588,31 @@ odf_line (GsfXMLIn *xin, xmlChar const **attrs)
height = y1 - y2;
}
if (state->pos.eval.col >= 0) {
if (cell_base.end.col >= 0) {
mode = GNM_SO_ANCHOR_TWO_CELLS;
} else {
cell_base.end.col = cell_base.start.col;
cell_base.end.row = cell_base.start.row;
frame_offset[2] = width;
frame_offset[3] = height;
mode = GNM_SO_ANCHOR_ONE_CELL;
}
} else {
cell_base.end.col = cell_base.start.col =
cell_base.end.row = cell_base.start.row = 0; /* actually not needed */
frame_offset[2] = width;
frame_offset[3] = height;
mode = GNM_SO_ANCHOR_ABSOLUTE;
}
odf_draw_frame_store_location (state, frame_offset,
height, width);
col = sheet_col_get_info (state->pos.sheet, cell_base.start.col);
row = sheet_row_get_info (state->pos.sheet, cell_base.start.row);
frame_offset[0] /= col->size_pts;
frame_offset[1] /= row->size_pts;
frame_offset[2] /= col->size_pts;
frame_offset[3] /= row->size_pts;
sheet_object_anchor_init (&state->chart.anchor, &cell_base,
frame_offset,
direction);
direction,
mode);
state->chart.so = g_object_new (GNM_SO_LINE_TYPE, NULL);
if (style_name != NULL) {
......@@ -11954,7 +11986,7 @@ static GsfXMLInNode const opendoc_content_dtd [] =
GSF_XML_IN_NODE (TABLE, SHEET_SELECTIONS, OO_GNUM_NS_EXT, "selections", GSF_XML_NO_CONTENT, &odf_selection, &odf_selection_end),
GSF_XML_IN_NODE (SHEET_SELECTIONS, SELECTION, OO_GNUM_NS_EXT, "selection", GSF_XML_NO_CONTENT, &odf_selection_range, NULL),
GSF_XML_IN_NODE (TABLE, TABLE_SOURCE, OO_NS_TABLE, "table-source", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (TABLE, TABLE_SHAPES, OO_NS_TABLE, "shapes", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (TABLE, TABLE_SHAPES, OO_NS_TABLE, "shapes", GSF_XML_NO_CONTENT, &odf_shapes, &odf_shapes_end),
GSF_XML_IN_NODE (TABLE_SHAPES, DRAW_FRAME, OO_NS_DRAW, "frame", GSF_XML_NO_CONTENT, &od_draw_frame_start, &od_draw_frame_end),
GSF_XML_IN_NODE (TABLE_SHAPES, DRAW_CAPTION, OO_NS_DRAW, "caption", GSF_XML_NO_CONTENT, &odf_caption, &od_draw_text_frame_end),
GSF_XML_IN_NODE (DRAW_CAPTION, TEXT_CONTENT, OO_NS_TEXT, "p", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd def */
......
......@@ -2840,25 +2840,40 @@ odf_write_frame_size (GnmOOExport *state, SheetObject *so)
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
odf_add_pt (state->xml, SVG "x", res_pts[0]);
odf_add_pt (state->xml, SVG "y", res_pts[1]);
odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
/* The next 3 lines should not be needed, but older versions of Gnumeric used the */
/* width and height. */
sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
odf_add_pt (state->xml, SVG "width", res_pts[2] - res_pts[0]);
odf_add_pt (state->xml, SVG "height", res_pts[3] - res_pts[1]);
gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
parse_pos_init_sheet (&pp, state->sheet);
formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
gnm_expr_top_unref (texpr);
gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
odf_strip_brackets (formula));
g_free (formula);
switch (anchor->mode) {
case GNM_SO_ANCHOR_TWO_CELLS:
odf_add_pt (state->xml, SVG "x", res_pts[0]);
odf_add_pt (state->xml, SVG "y", res_pts[1]);
odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
/* The next 3 lines should not be needed, but older versions of Gnumeric used the */
/* width and height. */
sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
odf_add_pt (state->xml, SVG "width", res_pts[2] - res_pts[0]);
odf_add_pt (state->xml, SVG "height", res_pts[3] - res_pts[1]);
gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
parse_pos_init_sheet (&pp, state->sheet);
formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
gnm_expr_top_unref (texpr);
gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
odf_strip_brackets (formula));
g_free (formula);
break;
case GNM_SO_ANCHOR_ONE_CELL:
odf_add_pt (state->xml, SVG "x", res_pts[0]);
odf_add_pt (state->xml, SVG "y", res_pts[1]);
odf_add_pt (state->xml, SVG "width", anchor->offset[2]);
odf_add_pt (state->xml, SVG "height", anchor->offset[3]);
break;
case GNM_SO_ANCHOR_ABSOLUTE:
odf_add_pt (state->xml, SVG "x", anchor->offset[0]);
odf_add_pt (state->xml, SVG "y", anchor->offset[1]);
odf_add_pt (state->xml, SVG "width", anchor->offset[2]);
odf_add_pt (state->xml, SVG "height", anchor->offset[3]);
break;
}
sheet = sheet_object_get_sheet (so);
if (sheet) {
......@@ -3186,9 +3201,6 @@ odf_write_line (GnmOOExport *state, SheetObject *so)
sheet_object_get_stacking (so);
gsf_xml_out_add_int (state->xml, DRAW "z-index", z);
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
sheet_object_anchor_to_pts (anchor, state->sheet, res_pts);
switch (anchor->base.direction) {
......@@ -3225,14 +3237,20 @@ odf_write_line (GnmOOExport *state, SheetObject *so)
odf_add_pt (state->xml, SVG "x2", x2);
odf_add_pt (state->xml, SVG "y2", y2);
gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
parse_pos_init_sheet (&pp, state->sheet);
formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
gnm_expr_top_unref (texpr);
gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
odf_strip_brackets (formula));
g_free (formula);
if (anchor->mode == GNM_SO_ANCHOR_TWO_CELLS) {
sheet_object_anchor_to_offset_pts (anchor, state->sheet, res_pts);
odf_add_pt (state->xml, TABLE "end-x", res_pts[2]);
odf_add_pt (state->xml, TABLE "end-y", res_pts[3]);
gnm_cellref_init (&ref, (Sheet *) state->sheet, r->end.col, r->end.row, TRUE);
texpr = gnm_expr_top_new (gnm_expr_new_cellref (&ref));
parse_pos_init_sheet (&pp, state->sheet);
formula = gnm_expr_top_as_string (texpr, &pp, state->conv);
gnm_expr_top_unref (texpr);
gsf_xml_out_add_cstr (state->xml, TABLE "end-cell-address",
odf_strip_brackets (formula));
g_free (formula);
}
gsf_xml_out_end_element (state->xml); /* DRAW "line" */
}
......@@ -3710,7 +3728,10 @@ odf_sheet_objects_get (Sheet const *sheet, GnmCellPos const *pos)
for (ptr = sheet->sheet_objects; ptr != NULL ; ptr = ptr->next ) {
SheetObject *so = GNM_SO (ptr->data);
SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
if (gnm_cellpos_equal (&anchor->cell_bound.start, pos))
if (anchor->mode == GNM_SO_ANCHOR_ABSOLUTE) {
if (pos == NULL)
res = g_slist_prepend (res, so);
} else if (pos && gnm_cellpos_equal (&anchor->cell_bound.start, pos))
res = g_slist_prepend (res, so);
}
return res;
......@@ -4855,6 +4876,7 @@ odf_write_content (GnmOOExport *state, GsfOutput *child)
int graph_n = 1;
int image_n = 1;
gboolean has_autofilters = FALSE;
GSList *objects;
state->xml = create_new_xml_child (state, child);
gsf_xml_out_set_doc_type (state->xml, "\n");