void addColumnStyles(
      final ImageElementContext context,
      final Section columns,
      final int columnPos,
      final int colSpan) {
    final Node[] columnDefs = columns.getNodeArray();
    int columnCounter = 0;
    for (Node columnDef : columnDefs) {
      final Element column = (Element) columnDef;

      if (!ObjectUtilities.equal(column.getNamespace(), OfficeNamespaces.TABLE_NS)
          || !ObjectUtilities.equal(column.getType(), OfficeToken.TABLE_COLUMN)) {
        continue;
      }
      if (columnCounter >= columnPos) {
        final String colStyle =
            (String) column.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
        context.setColStyle(columnCounter - columnPos, colStyle);
      }

      columnCounter += 1;

      if (columnCounter >= (columnPos + colSpan)) {
        break;
      }
    }
  }
 private LayoutController findParentCell() {
   LayoutController parent = getParent();
   while (parent != null) {
     final Object node = parent.getNode();
     if (node instanceof Element) {
       final Element element = (Element) node;
       if (OfficeNamespaces.TABLE_NS.equals(element.getNamespace())
           && "table-cell".equals(element.getType())) {
         return parent;
       }
     }
     parent = parent.getParent();
   }
   return null;
 }
  void addRowStyles(
      final ImageElementContext context, final Section table, final int rowPos, final int rowSpan) {
    final Node[] rows = table.getNodeArray();
    int rowCounter = 0;
    for (Node row1 : rows) {
      final Element row = (Element) row1;

      if (!ObjectUtilities.equal(row.getNamespace(), OfficeNamespaces.TABLE_NS)
          || !ObjectUtilities.equal(row.getType(), OfficeToken.TABLE_ROW)) {
        continue;
      }
      if (rowCounter >= rowPos) {
        final String rowStyle =
            (String) row.getAttribute(OfficeNamespaces.TABLE_NS, OfficeToken.STYLE_NAME);
        context.setRowStyle(rowCounter - rowPos, rowStyle);
      }

      rowCounter += 1;

      if (rowCounter >= (rowPos + rowSpan)) {
        break;
      }
    }
  }
  private int findNodeInSection(
      final Section tableRow, final Element tableCell, final String secondType) {
    int retval = 0;
    final Node[] nodes = tableRow.getNodeArray();
    final String namespace = tableCell.getNamespace();
    final String type = tableCell.getType();
    for (final Node node : nodes) {
      if (!(node instanceof Element)) {
        continue;
      }
      final Element child = (Element) node;
      if (!ObjectUtilities.equal(child.getNamespace(), namespace)
          || (!ObjectUtilities.equal(child.getType(), type)
              && (secondType == null || !ObjectUtilities.equal(child.getType(), secondType)))) {
        continue;
      }

      if (node == tableCell) {
        return retval;
      }
      retval += 1;
    }
    return -1;
  }
  protected ImageElementContext createContext() {
    if (context == null) {

      // Step 1: Find the parent cell.
      final LayoutController cellController = findParentCell();
      if (cellController == null) {
        LOGGER.warn("Image is not contained in a table. Unable to calculate the image-size.");
        return null;
      }
      final Element tableCell = (Element) cellController.getNode();
      final int rowSpan =
          TextUtilities.parseInt(
              (String) tableCell.getAttribute(OfficeNamespaces.TABLE_NS, "number-rows-spanned"), 1);
      final int colSpan =
          TextUtilities.parseInt(
              (String) tableCell.getAttribute(OfficeNamespaces.TABLE_NS, "number-columns-spanned"),
              1);
      if (rowSpan < 1 || colSpan < 1) {
        LOGGER.warn("Rowspan or colspan for image-size calculation was invalid.");
        return null;
      }

      final LayoutController rowController = cellController.getParent();
      if (rowController == null) {
        LOGGER.warn("Table-Cell has no parent. Unable to calculate the image-size.");
        return null;
      }
      final Section tableRow = (Section) rowController.getNode();
      // we are now making the assumption, that the row is a section, that contains the table-cell.
      // This breaks the ability to return nodes or to construct reports on the fly, but the
      // OO-report format
      // is weird anyway and won't support such advanced techniques for the next few centuries...
      final int columnPos = findNodeInSection(tableRow, tableCell, OfficeToken.COVERED_TABLE_CELL);
      if (columnPos == -1) {
        LOGGER.warn(
            "Table-Cell is not a direct child of the table-row. Unable to calculate the image-size.");
        return null;
      }

      final LayoutController tableController = rowController.getParent();
      if (tableController == null) {
        LOGGER.warn("Table-Row has no Table. Unable to calculate the image-size.");
        return null;
      }

      final Section table = (Section) tableController.getNode();
      // ok, we got a table, so as next we have to search for the columns now.
      final Section columns =
          (Section) table.findFirstChild(OfficeNamespaces.TABLE_NS, OfficeToken.TABLE_COLUMNS);
      if (columns.getNodeCount() <= columnPos + colSpan) {
        // the colspan is to large. The table definition is therefore invalid. We do not try to fix
        // this.
        LOGGER.warn(
            "The Table's defined columns do not match the col-span or col-position. Unable to calculate the image-size.");
        return null;
      }

      final ImageElementContext context = new ImageElementContext(colSpan, rowSpan);
      addColumnStyles(context, columns, columnPos, colSpan);
      // finally search the styles for the row now.
      final int rowPos = findNodeInSection(table, tableRow, null);
      if (rowPos == -1) {
        LOGGER.warn(
            "Table-Cell is not a direct child of the table-row. Unable to calculate the image-size.");
        return null;
      }

      addRowStyles(context, table, rowPos, rowSpan);
      this.context = context;
    }
    return this.context;
  }