text: import pivotTable from '../controllers/pivotTable';
  import conditionformat from '../controllers/conditionformat';
  import alternateformat from '../controllers/alternateformat';
  import luckysheetSparkline from '../controllers/sparkline';
  import menuButton from '../controllers/menuButton';
  import dataVerificationCtrl from '../controllers/dataVerificationCtrl';
  import { luckysheetdefaultstyle, luckysheet_CFiconsImg,luckysheetdefaultFont } from '../controllers/constant';
  import { luckysheet_searcharray } from '../controllers/sheetSearch';
  import { dynamicArrayCompute } from './dynamicArray';
  import browser from './browser';
  import { isRealNull, isRealNum } from './validate';
  import { getMeasureText,getCellTextInfo } from './getRowlen';
  import { getRealCellValue } from './getdata';
  import { getBorderInfoComputeRange } from './border';
  import { getSheetIndex } from '../methods/get';
  import { getObjType, chatatABC, luckysheetfontformat } from '../utils/util';
  import { isInlineStringCell } from '../controllers/inlineString';
  import method from './method';
  import Store from '../store';
  import locale from '../locale/locale';
  import sheetmanage from '../controllers/sheetmanage';
  
  function luckysheetDrawgridRowTitle(scrollHeight, drawHeight, offsetTop) {
      if (scrollHeight == null) {
          scrollHeight = $("#luckysheet-cell-main").scrollTop();
      }
  
      if (drawHeight == null) {
          drawHeight = Store.luckysheetTableContentHW[1];
      }
  
      if (offsetTop == null) {
          offsetTop = Store.columnHeaderHeight;
      }
      
      let luckysheetTableContent = $("#luckysheetTableContent").get(0).getContext("2d");
      luckysheetTableContent.save();
      luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);
  
      luckysheetTableContent.clearRect(
          0,
          offsetTop ,
          (Store.rowHeaderWidth - 1) ,
          drawHeight
      );
  
      luckysheetTableContent.font = luckysheetdefaultFont();
      luckysheetTableContent.textBaseline = luckysheetdefaultstyle.textBaseline; //基准线 垂直居中
      luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;
  
      let dataset_row_st, dataset_row_ed;
      dataset_row_st = luckysheet_searcharray(Store.visibledatarow, scrollHeight);
      dataset_row_ed = luckysheet_searcharray(Store.visibledatarow, scrollHeight + drawHeight);
  
      if (dataset_row_st == -1) {
          dataset_row_st = 0;
      }
      if (dataset_row_ed == -1) {
          dataset_row_ed = Store.visibledatarow.length - 1;
      }
      
  
      luckysheetTableContent.save();
      luckysheetTableContent.beginPath();
      luckysheetTableContent.rect(0, offsetTop-1, Store.rowHeaderWidth -1, drawHeight-2);
      luckysheetTableContent.clip();
  
      let end_r, start_r;
      let bodrder05 = 0.5;//Default 0.5
      let preEndR;
      for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
          if (r == 0) {
              start_r = -scrollHeight - 1;
          }
          else {
              start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
          }
          end_r = Store.visibledatarow[r] - scrollHeight;
  
          //若超出绘制区域终止
          // if(end_r > scrollHeight + drawHeight){
          //     break;
          // }
          let firstOffset = (dataset_row_st==r)?-2:0;
          let lastOffset = (dataset_row_ed==r)?-2:0;
          //列标题单元格渲染前触发，return false 则不渲染该单元格
          if(!method.createHookFunction("rowTitleCellRenderBefore", r+1, {
              r:r,
              top:(start_r + offsetTop + firstOffset),
              width:Store.rowHeaderWidth -1,
              height:(end_r - start_r + 1+lastOffset-firstOffset)
          }, luckysheetTableContent)){ continue; }
  
          if (Store.config["rowhidden"] != null && Store.config["rowhidden"][r] != null) {
  
          }
          else {
              luckysheetTableContent.fillStyle = "#ffffff";
              luckysheetTableContent.fillRect(
                  0,
                  (start_r + offsetTop + firstOffset) , 
                  Store.rowHeaderWidth -1,
                  (end_r - start_r + 1+lastOffset-firstOffset) 
              )
              luckysheetTableContent.fillStyle = "#000000";
  
              //行标题栏序列号
              luckysheetTableContent.save();//save scale before draw text
              luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio);
              let textMetrics = getMeasureText(r+1, luckysheetTableContent); 
              //luckysheetTableContent.measureText(r + 1);
  
              let horizonAlignPos = (Store.rowHeaderWidth  - textMetrics.width) / 2;
              let verticalAlignPos = (start_r + (end_r - start_r) / 2 + offsetTop) ;
  
              luckysheetTableContent.fillText(r + 1, horizonAlignPos/Store.zoomRatio, verticalAlignPos/Store.zoomRatio);
              luckysheetTableContent.restore();//restore scale after draw text
          }
  
          //vertical
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
              (Store.rowHeaderWidth - 2 + bodrder05) ,
               (start_r + offsetTop - 2)
          );
          luckysheetTableContent.lineTo(
              (Store.rowHeaderWidth - 2 + bodrder05) ,
               (end_r + offsetTop - 2)
          );
          luckysheetTableContent.lineWidth = 1;
  
          luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
          luckysheetTableContent.stroke();
          luckysheetTableContent.closePath();
  
          //行标题栏横线,horizen
          if (Store.config["rowhidden"] != null && Store.config["rowhidden"][r] == null && Store.config["rowhidden"][r+1] != null) {
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  -1,
                  (end_r + offsetTop - 4 + bodrder05) 
              );
              luckysheetTableContent.lineTo(
                  (Store.rowHeaderWidth - 1) ,
                  (end_r + offsetTop - 4 + bodrder05) 
              );
              // luckysheetTableContent.lineWidth = 1;
              // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
          }
          else if(Store.config["rowhidden"]==null || Store.config["rowhidden"][r] == null){
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  -1,
                  (end_r + offsetTop - 2 + bodrder05) 
              );
              luckysheetTableContent.lineTo(
                  (Store.rowHeaderWidth - 1) ,
                  (end_r + offsetTop - 2 + bodrder05) 
              );
  
              // luckysheetTableContent.lineWidth = 1;
              // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
  
          }
  
          if (Store.config["rowhidden"] != null && Store.config["rowhidden"][r-1] != null && preEndR!=null) {
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  -1,
                  (preEndR + offsetTop + bodrder05) 
              );
              luckysheetTableContent.lineTo(
                  (Store.rowHeaderWidth - 1) ,
                  (preEndR + offsetTop + bodrder05) 
              );
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
          }
  
          preEndR = end_r;
  
          //列标题单元格渲染前触发，return false 则不渲染该单元格
          method.createHookFunction("rowTitleCellRenderAfter", r+1, {
              r:r,
              top:(start_r + offsetTop + firstOffset),
              width:Store.rowHeaderWidth -1,
              height:(end_r - start_r + 1+lastOffset-firstOffset)
          }, luckysheetTableContent)
  
      }
  
      //行标题栏竖线
      // luckysheetTableContent.beginPath();
      // luckysheetTableContent.moveTo(
      //     (Store.rowHeaderWidth - 2 + 0.5) ,
      //     (offsetTop - 1) 
      // );
      // luckysheetTableContent.lineTo(
      //     (Store.rowHeaderWidth - 2 + 0.5) ,
      //     (Store.rh_height + offsetTop) 
      // );
      // luckysheetTableContent.lineWidth = 1;
      // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
      // luckysheetTableContent.closePath();
      // luckysheetTableContent.stroke();
  
  
      //清除canvas左上角区域 防止列标题栏序列号溢出显示
      // luckysheetTableContent.clearRect(0, 0, Store.rowHeaderWidth , Store.columnHeaderHeight );
  
      // Must be restored twice, otherwise it will be enlarged under window.devicePixelRatio = 1.5
      luckysheetTableContent.restore();
      luckysheetTableContent.restore();
      
  }
  
  function luckysheetDrawgridColumnTitle(scrollWidth, drawWidth, offsetLeft) {
      if (scrollWidth == null) {
          scrollWidth = $("#luckysheet-cell-main").scrollLeft();
      }
  
      if (drawWidth == null) {
          drawWidth = Store.luckysheetTableContentHW[0];
      }
  
      if (offsetLeft == null) {
          offsetLeft = Store.rowHeaderWidth;
      }
      
      let luckysheetTableContent = $("#luckysheetTableContent").get(0).getContext("2d");
      luckysheetTableContent.save();
      luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);
      luckysheetTableContent.clearRect(
          offsetLeft ,
          0,
          drawWidth ,
          (Store.columnHeaderHeight - 1) 
      );
  
  
      luckysheetTableContent.font = luckysheetdefaultFont();
      luckysheetTableContent.textBaseline = luckysheetdefaultstyle.textBaseline; //基准线 垂直居中
      luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;
  
      let dataset_col_st, dataset_col_ed;
      dataset_col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth);
      dataset_col_ed = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth + drawWidth);
  
      if (dataset_col_st == -1) {
          dataset_col_st = 0;
      }
      if (dataset_col_ed == -1) {
          dataset_col_ed = Store.visibledatacolumn.length - 1;
      }
      
      luckysheetTableContent.save();
      luckysheetTableContent.beginPath();
      luckysheetTableContent.rect(offsetLeft-1, 0, drawWidth, Store.columnHeaderHeight -1);
      luckysheetTableContent.clip();
  
      // console.log(offsetLeft, 0, drawWidth, Store.columnHeaderHeight -1);
  
      let end_c, start_c;
      let bodrder05 = 0.5;//Default 0.5
      let preEndC;
      for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
          if (c == 0) {
              start_c = -scrollWidth;
          }
          else {
              start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
          }
          end_c = Store.visibledatacolumn[c] - scrollWidth;
  
          //若超出绘制区域终止
          // if(end_c > scrollWidth + drawWidth+1){
          //     break;
          // }
          let abc = chatatABC(c);
          //列标题单元格渲染前触发，return false 则不渲染该单元格
          if(!method.createHookFunction("columnTitleCellRenderBefore", abc, {
              c:c,
              left:(start_c + offsetLeft - 1),
              width:(end_c - start_c),
              height:Store.columnHeaderHeight -1
          }, luckysheetTableContent)){ continue; }
          
          if (Store.config["colhidden"] != null && Store.config["colhidden"][c] != null) {
  
          }
          else {
              luckysheetTableContent.fillStyle = "#ffffff";
              luckysheetTableContent.fillRect(
                  (start_c + offsetLeft - 1) , 
                  0, 
                  (end_c - start_c) ,
                  Store.columnHeaderHeight -1
              )
              luckysheetTableContent.fillStyle = "#000000";
  
              //列标题栏序列号
              luckysheetTableContent.save();//save scale before draw text
              luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio);
              
              let textMetrics = getMeasureText(abc, luckysheetTableContent);
              //luckysheetTableContent.measureText(abc);
  
              let horizonAlignPos = Math.round((start_c + (end_c - start_c) / 2 + offsetLeft)  - textMetrics.width / 2);
              let verticalAlignPos = Math.round(Store.columnHeaderHeight / 2 );
              
              luckysheetTableContent.fillText(abc, horizonAlignPos/Store.zoomRatio, verticalAlignPos/Store.zoomRatio);
              luckysheetTableContent.restore();//restore scale after draw text
          }
  
          //列标题栏竖线 vertical
          if (Store.config["colhidden"] != null && Store.config["colhidden"][c] == null && Store.config["colhidden"][c+1] != null) {
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  (end_c + offsetLeft - 4 + bodrder05) ,
                  0
              );
              luckysheetTableContent.lineTo(
                  (end_c + offsetLeft - 4 + bodrder05) ,
                  (Store.columnHeaderHeight - 2) 
              );
              luckysheetTableContent.lineWidth = 1;
              luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
          }
          else if(Store.config["colhidden"]==null || Store.config["colhidden"][c] == null) {
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  (end_c + offsetLeft - 2 + bodrder05) ,
                  0
              );
              luckysheetTableContent.lineTo(
                  (end_c + offsetLeft - 2 + bodrder05) ,
                  (Store.columnHeaderHeight - 2) 
              );
  
              luckysheetTableContent.lineWidth = 1;
              luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
          }
  
          if (Store.config["colhidden"] != null && Store.config["colhidden"][c-1] != null && preEndC!=null) {
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                  (preEndC + offsetLeft + bodrder05) ,
                  0
              );
              luckysheetTableContent.lineTo(
                  (preEndC + offsetLeft + bodrder05) ,
                  (Store.columnHeaderHeight - 2) 
              );
              // luckysheetTableContent.lineWidth = 1;
              // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.closePath();
              luckysheetTableContent.stroke();
          }
  
  
          //horizen
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
               (start_c + offsetLeft - 1), 
              (Store.columnHeaderHeight - 2 + bodrder05) 
          );
          luckysheetTableContent.lineTo(
               (end_c + offsetLeft - 1), 
              (Store.columnHeaderHeight - 2 + bodrder05) 
          );
          // luckysheetTableContent.lineWidth = 1;
  
          // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;        
          luckysheetTableContent.stroke();
          luckysheetTableContent.closePath();
  
          preEndC = end_c;
  
          method.createHookFunction("columnTitleCellRenderAfter", abc, {
              c:c,
              left:(start_c + offsetLeft - 1),
              width:(end_c - start_c),
              height:Store.columnHeaderHeight -1
          }, luckysheetTableContent)
      }
  
      //列标题栏横线
      // luckysheetTableContent.beginPath();
      // luckysheetTableContent.moveTo(
      //     (offsetLeft - 1) ,
      //     (Store.columnHeaderHeight - 2 + 0.5) 
      // );
      // luckysheetTableContent.lineTo(
      //     (Store.ch_width + offsetLeft - 2) ,
      //     (Store.columnHeaderHeight - 2 + 0.5) 
      // );
      // luckysheetTableContent.lineWidth = 1;
      // luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
      // luckysheetTableContent.closePath();
      // luckysheetTableContent.stroke();
  
      //清除canvas左上角区域 防止列标题栏序列号溢出显示
      // luckysheetTableContent.clearRect(0, 0, Store.rowHeaderWidth , Store.columnHeaderHeight );
  
      // Must be restored twice, otherwise it will be enlarged under window.devicePixelRatio = 1.5
      luckysheetTableContent.restore();
      luckysheetTableContent.restore();
  
  }
  
  function luckysheetDrawMain(scrollWidth, scrollHeight, drawWidth, drawHeight, offsetLeft, offsetTop, columnOffsetCell, rowOffsetCell, mycanvas) {
  
      if(Store.flowdata == null){
          return;
      }
  
      let sheetFile = sheetmanage.getSheetByIndex();
  
      // console.trace();
      clearTimeout(Store.measureTextCacheTimeOut);
      
      //参数未定义处理
      if (scrollWidth == null) {
          scrollWidth = $("#luckysheet-cell-main").scrollLeft();
      }
      if (scrollHeight == null) {
          scrollHeight = $("#luckysheet-cell-main").scrollTop();
      }
  
      if (drawWidth == null) {
          drawWidth = Store.luckysheetTableContentHW[0];
      }
      if (drawHeight == null) {
          drawHeight = Store.luckysheetTableContentHW[1];
      }
  
      if (offsetLeft == null) {
          offsetLeft = Store.rowHeaderWidth;
      }
      if (offsetTop == null) {
          offsetTop = Store.columnHeaderHeight;
      }
  
      if (columnOffsetCell == null) {
          columnOffsetCell = 0;
      }
      if (rowOffsetCell == null) {
          rowOffsetCell = 0;
      }
  
      //表格canvas
      let luckysheetTableContent = null;
      if(mycanvas == null){
          luckysheetTableContent = $("#luckysheetTableContent").get(0).getContext("2d");
      }
      else {
          if(getObjType(mycanvas) == "object"){
              try{
                  luckysheetTableContent = mycanvas.get(0).getContext("2d");
              }
              catch(err){
                  luckysheetTableContent = mycanvas;
              }
          }
          else{
              luckysheetTableContent = $("#" + mycanvas).get(0).getContext("2d");
          }
      }
  
      luckysheetTableContent.save();
      luckysheetTableContent.scale(Store.devicePixelRatio, Store.devicePixelRatio);
      
      luckysheetTableContent.clearRect(
          0, 
          0, 
          Store.luckysheetTableContentHW[0],
          Store.luckysheetTableContentHW[1]
      );
  
      //表格渲染区域 起止行列下标
      let dataset_row_st, 
          dataset_row_ed, 
          dataset_col_st, 
          dataset_col_ed;
  
      dataset_row_st = luckysheet_searcharray(Store.visibledatarow, scrollHeight);
      dataset_row_ed = luckysheet_searcharray(Store.visibledatarow, scrollHeight + drawHeight);
  
      if (dataset_row_st == -1) {
          dataset_row_st = 0;
      }
  
      dataset_row_st += rowOffsetCell;
  
      if (dataset_row_ed == -1) {
          dataset_row_ed = Store.visibledatarow.length - 1;
      }
  
      dataset_row_ed += rowOffsetCell;
  
      if (dataset_row_ed >= Store.visibledatarow.length) {
          dataset_row_ed = Store.visibledatarow.length - 1;
      }
  
      dataset_col_st = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth);
      dataset_col_ed = luckysheet_searcharray(Store.visibledatacolumn, scrollWidth + drawWidth);
      
      if (dataset_col_st == -1) {
          dataset_col_st = 0;
      }
  
      dataset_col_st += columnOffsetCell;
  
      if (dataset_col_ed == -1) {
          dataset_col_ed = Store.visibledatacolumn.length - 1;
      }
  
      dataset_col_ed += columnOffsetCell;
  
      if (dataset_col_ed >= Store.visibledatacolumn.length) {
          dataset_col_ed = Store.visibledatacolumn.length - 1;
      }
  
      //表格渲染区域 起止行列坐标
      let fill_row_st, 
          fill_row_ed, 
          fill_col_st, 
          fill_col_ed;
  
      if(dataset_row_st == 0){
          fill_row_st = 0;
      }
      else{
          fill_row_st = Store.visibledatarow[dataset_row_st - 1];
      }
  
      fill_row_ed = Store.visibledatarow[dataset_row_ed];
  
      if(dataset_col_st == 0){
          fill_col_st = 0;
      }
      else{
          fill_col_st = Store.visibledatacolumn[dataset_col_st - 1];
      }
  
      fill_col_ed = Store.visibledatacolumn[dataset_col_ed];
  
      //表格canvas 初始化处理
      luckysheetTableContent.fillStyle = "#ffffff";
      luckysheetTableContent.fillRect(
          (offsetLeft - 1) , 
          (offsetTop - 1) , 
          (fill_col_ed - scrollWidth) , 
          (fill_row_ed - scrollHeight)
      );
      luckysheetTableContent.font = luckysheetdefaultFont();
      // luckysheetTableContent.textBaseline = "top";
      luckysheetTableContent.fillStyle = luckysheetdefaultstyle.fillStyle;
  
      //表格渲染区域 非空单元格行列 起止坐标
      let cellupdate = [];
      let mergeCache = {};
      let borderOffset = {};
  
      let bodrder05 = 0.5;//Default 0.5
  
      // 钩子函数
      method.createHookFunction("cellAllRenderBefore",Store.flowdata,sheetFile,luckysheetTableContent);
      
      for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
          let start_r;
          if (r == 0) {
              start_r = -scrollHeight - 1;
          }
          else {
              start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
          }
  
          let end_r = Store.visibledatarow[r] - scrollHeight;
  
          if (Store.config["rowhidden"] != null && Store.config["rowhidden"][r] != null) {
              continue;
          }
          
          for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
              let start_c;
              if (c == 0) {
                  start_c = -scrollWidth;
              }
              else {
                  start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
              }
  
              let end_c = Store.visibledatacolumn[c] - scrollWidth;
              
              if (Store.config["colhidden"] != null && Store.config["colhidden"][c] != null) {
                  continue
              }
              
              let firstcolumnlen = Store.defaultcollen;
              if (Store.config["columnlen"] != null && Store.config["columnlen"][c] != null) {
                  firstcolumnlen = Store.config["columnlen"][c];
              }
  
  
  
              if (Store.flowdata[r] != null && Store.flowdata[r][c] != null) {
                  let value = Store.flowdata[r][c];
  
                  if(getObjType(value) == "object" && ("mc" in value)){
                      borderOffset[r + "_" + c] = { 
                          "start_r": start_r,
                          "start_c": start_c, 
                          "end_r": end_r, 
                          "end_c": end_c 
                      };
  
                      if("rs" in value["mc"]){
                          let key = "r"+ r + "c" + c;
                          mergeCache[key] = cellupdate.length;
                      }
                      else{
                          let key = "r"+ value["mc"].r + "c" + value["mc"].c;
                          let margeMain = cellupdate[mergeCache[key]];
  
                          if(margeMain == null){
                              mergeCache[key] = cellupdate.length;
                              cellupdate.push({
                                  "r": r, 
                                  "c": c, 
                                  "start_c": start_c, 
                                  "start_r": start_r, 
                                  "end_r": end_r, 
                                  "end_c": end_c, 
                                  "firstcolumnlen": firstcolumnlen, 
                              });
                          }
                          else{
                              if(margeMain.c == c){
                                  margeMain.end_r += (end_r - start_r - 1);
                              }
                              
                              if(margeMain.r == r){
                                  margeMain.end_c += (end_c - start_c);
                                  margeMain.firstcolumnlen += firstcolumnlen;
                              }
                          }
  
                          continue;
                      }
                  }
              }
              else{
                  //空单元格渲染前
                  if(!method.createHookFunction("cellRenderBefore", Store.flowdata[r][c], {
                      r:r,
                      c:c,
                      "start_r": start_r,
                      "start_c": start_c, 
                      "end_r": end_r, 
                      "end_c": end_c 
                  }, sheetFile,luckysheetTableContent)){ continue; }
              }
  
  
              cellupdate.push({
                  "r": r, 
                  "c": c, 
                  "start_r": start_r, 
                  "start_c": start_c, 
                  "end_r": end_r, 
                  "end_c": end_c, 
                  "firstcolumnlen": firstcolumnlen, 
              });
              borderOffset[r + "_" + c] = { 
                  "start_r": start_r, 
                  "start_c": start_c, 
                  "end_r": end_r, 
                  "end_c": end_c 
              };
          }
      }
  
      //动态数组公式计算
      let dynamicArray_compute = dynamicArrayCompute(Store.luckysheetfile[getSheetIndex(Store.currentSheetIndex)]["dynamicArray"]);
  
      //交替颜色计算
      let af_compute = alternateformat.getComputeMap();
  
      //条件格式计算
      let cf_compute = conditionformat.getComputeMap();
  
      //表格渲染区域 溢出单元格配置保存
      let cellOverflowMap = getCellOverflowMap(luckysheetTableContent, dataset_col_st, dataset_col_ed,dataset_row_st,dataset_row_ed);
  
      let mcArr = [];
  
      for(let cud = 0; cud < cellupdate.length; cud++){
          let item = cellupdate[cud];
          let r = item.r, 
              c = item.c, 
              start_r = item.start_r, 
              start_c = item.start_c, 
              end_r = item.end_r, 
              end_c = item.end_c;
          let firstcolumnlen = item.firstcolumnlen;
  
          if(Store.flowdata[r] == null){
              continue;
          }
  
          //有值单元格渲染前
          if(!method.createHookFunction("cellRenderBefore", Store.flowdata[r][c], {
              r:r,
              c:c,
              "start_r": start_r,
              "start_c": start_c, 
              "end_r": end_r, 
              "end_c": end_c 
          }, sheetFile,luckysheetTableContent)){ continue; }
          
          if(Store.flowdata[r][c] == null){ //空单元格
              nullCellRender(r, c, start_r, start_c, end_r, end_c,luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05);
          }
          else{
              let cell = Store.flowdata[r][c];
              let value = null;
  
              if((typeof cell == "object") && "mc" in cell){
                  mcArr.push(cellupdate[cud]);
                  // continue;
              }
              else{
                  value = getRealCellValue(r,c);
              }  
  
              if(value == null || value.toString().length == 0){
                  nullCellRender(r, c, start_r, start_c, end_r, end_c,luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05);
                  
                  //sparklines渲染
                  let borderfix = menuButton.borderfix(Store.flowdata, r, c);
                  let cellsize = [
                       (start_c + offsetLeft + borderfix[0]), 
                       (start_r + offsetTop + borderfix[1]), 
                       (end_c - start_c - 3 + borderfix[2]), 
                       (end_r - start_r - 3 - 1 + borderfix[3])
                  ];
                  sparklinesRender(r, c, cellsize[0], cellsize[1], "luckysheetTableContent", luckysheetTableContent);
              }
              else{
                  if((r + "_" + c) in dynamicArray_compute){//动态数组公式
                      value = dynamicArray_compute[r + "_" + c].v;
                  }
                  
                  cellRender(r, c, start_r, start_c, end_r, end_c, value,luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05);
              }
          }
  
          method.createHookFunction("cellRenderAfter", Store.flowdata[r][c], {
              r:r,
              c:c,
              "start_r": start_r,
              "start_c": start_c, 
              "end_r": end_r, 
              "end_c": end_c 
          }, sheetFile,luckysheetTableContent)
      }
  
      //合并单元格再处理
      for(let m = 0; m < mcArr.length; m++){
          let item = mcArr[m];
          let r = item.r, 
              c = item.c, 
              start_r = item.start_r, 
              start_c = item.start_c, 
              end_r = item.end_r-1, 
              end_c = item.end_c-1;
          let firstcolumnlen = item.firstcolumnlen;
  
          let cell = Store.flowdata[r][c];
          let value = null;
  
          let margeMaindata = cell["mc"];
  
          value = getRealCellValue(margeMaindata.r,margeMaindata.c);
  
          r = margeMaindata.r;
          c = margeMaindata.c;
  
          let mainCell = Store.flowdata[r][c];
  
          if (c == 0) {
              start_c = -scrollWidth;
          }
          else {
              start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
          }
  
          if (r == 0) {
              start_r = -scrollHeight - 1;
          }
          else {
              start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
          }
  
          end_r = Store.visibledatarow[r+mainCell["mc"].rs-1] - scrollHeight;
          end_c = Store.visibledatacolumn[c+mainCell["mc"].cs-1] - scrollWidth;
  
          if(value == null || value.toString().length == 0){
              nullCellRender(r, c, start_r, start_c, end_r, end_c,luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05, true);
              
              //sparklines渲染
              let borderfix = menuButton.borderfix(Store.flowdata, r, c);
              let cellsize = [
                   (start_c + offsetLeft + borderfix[0]), 
                   (start_r + offsetTop + borderfix[1]), 
                   (end_c - start_c - 3 + borderfix[2]), 
                   (end_r - start_r - 3 - 1  + borderfix[3])
              ];
              sparklinesRender(r, c, cellsize[0], cellsize[1], "luckysheetTableContent", luckysheetTableContent);
          }
          else{
              if((r + "_" + c) in dynamicArray_compute){//动态数组公式
                  value = dynamicArray_compute[r + "_" + c].v;
              }
              cellRender(r, c, start_r, start_c, end_r, end_c, value, luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05, true);
          }
      }
  
      //数据透视表边框渲染
      for (let r = dataset_row_st; r <= dataset_row_ed; r++) {
          let start_r;
          if (r == 0) {
              start_r = -scrollHeight - 1;
          }
          else {
              start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
          }
  
          let end_r = Store.visibledatarow[r] - scrollHeight;
          
          for (let c = dataset_col_st; c <= dataset_col_ed; c++) {
              let start_c;
              if (c == 0) {
                  start_c = -scrollWidth;
              }
              else {
                  start_c = Store.visibledatacolumn[c - 1] - scrollWidth;
              }
  
              let end_c = Store.visibledatacolumn[c] - scrollWidth;
  
  
              //数据透视表
              if (!!Store.luckysheetcurrentisPivotTable && pivotTable.drawPivotTable) {
                  if ((c == 0 || c == 5) && r <= 11) {
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                           (end_c - 2 + bodrder05 + offsetLeft), 
                           (start_r + offsetTop)
                      );
                      luckysheetTableContent.lineTo(
                           (end_c - 2 + bodrder05 + offsetLeft), 
                           (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = "#000000";
                      luckysheetTableContent.closePath();
                      luckysheetTableContent.stroke();
                  }
  
                  if ((r == 2 || r == 11) && c <= 5) {
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                           (start_c - 1 + offsetLeft), 
                           (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineTo(
                           (end_c - 2 + bodrder05 + offsetLeft), 
                           (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = "#000000";
                      luckysheetTableContent.closePath();
                      luckysheetTableContent.stroke();
                  }
  
                  if (r == 6 && c == 3) {
                      luckysheetTableContent.save();
                      luckysheetTableContent.font="bold 30px Arial";
                      luckysheetTableContent.fillStyle = "#626675";
                      luckysheetTableContent.textAlign="center";  
                      luckysheetTableContent.fillText(
                          locale().pivotTable.title, 
                           (start_c + (end_c - start_c) / 2 + 4 + offsetLeft), 
                          (start_r + (end_r - start_r) / 2 - 1 + offsetTop)
                      );
                      luckysheetTableContent.restore();
                  }
              }
              else if (!!Store.luckysheetcurrentisPivotTable) {
                  if (c < pivotTable.pivotTableBoundary[1] && r < pivotTable.pivotTableBoundary[0]) {
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                          (end_c - 2 + bodrder05 + offsetLeft), 
                          (start_r + offsetTop)
                      );
                      luckysheetTableContent.lineTo(
                          (end_c - 2 + bodrder05 + offsetLeft), 
                          (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = "#000000";
                      luckysheetTableContent.closePath();
                      luckysheetTableContent.stroke();
  
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                          (start_c - 1 + offsetLeft), 
                          (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineTo(
                          (end_c - 2 + offsetLeft), 
                          (end_r - 2 + bodrder05 + offsetTop)
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = "#000000";
                      luckysheetTableContent.closePath();
                      luckysheetTableContent.stroke();
                  }
              }
          }
      }
  
      //边框单独渲染
      if(Store.config["borderInfo"] != null && Store.config["borderInfo"].length > 0){
          //边框渲染
          let borderLeftRender = function(style, color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, canvas){
              let linetype = style;
  
              let m_st =  (start_c - 2 + bodrder05 + offsetLeft);
              let m_ed =  (start_r + offsetTop-1);
              let line_st =  (start_c - 2 + bodrder05 + offsetLeft);
              let line_ed =  (end_r - 2 + bodrder05 + offsetTop);
              canvas.save();
              menuButton.setLineDash(canvas, linetype, "v", m_st, m_ed, line_st, line_ed);
  
              canvas.strokeStyle = color;
              
              canvas.stroke();
              canvas.closePath();
              canvas.restore();
          }
  
          let borderRightRender = function(style, color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, canvas){
              let linetype = style;
  
              let m_st =  (end_c - 2 + bodrder05 + offsetLeft);
              let m_ed =  (start_r + offsetTop-1);
              let line_st =  (end_c - 2 + bodrder05 + offsetLeft);
              let line_ed =  (end_r - 2 + bodrder05 + offsetTop);
              canvas.save();
              menuButton.setLineDash(canvas, linetype, "v", m_st, m_ed, line_st, line_ed);
  
              canvas.strokeStyle = color;
              
              canvas.stroke();
              canvas.closePath();
              canvas.restore();
          }
  
          let borderBottomRender = function(style, color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, canvas){
              let linetype = style;
  
              let m_st =  (start_c - 2 + bodrder05 + offsetLeft);
              let m_ed =  (end_r - 2 + bodrder05 + offsetTop);
              let line_st =  (end_c - 2 + bodrder05 + offsetLeft);
              let line_ed =  (end_r - 2 + bodrder05 + offsetTop);
              canvas.save();
              menuButton.setLineDash(canvas, linetype, "h", m_st, m_ed, line_st, line_ed);
  
              canvas.strokeStyle = color;
              
              canvas.stroke();
              canvas.closePath();
              canvas.restore();
          }
  
          let borderTopRender = function(style, color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, canvas){
              let linetype = style;
  
              let m_st =  (start_c - 2 + bodrder05 + offsetLeft);
              let m_ed =  (start_r - 1 + bodrder05 + offsetTop);
              let line_st =  (end_c - 2 + bodrder05 + offsetLeft);
              let line_ed =  (start_r - 1 + bodrder05 + offsetTop);
              canvas.save();
              menuButton.setLineDash(canvas, linetype, "h", m_st, m_ed, line_st, line_ed);
  
              canvas.strokeStyle = color;
              
              canvas.stroke();
              canvas.closePath();
              canvas.restore();
          }
  
          let borderInfoCompute = getBorderInfoComputeRange(dataset_row_st,dataset_row_ed,dataset_col_st,dataset_col_ed);
          
          for(let x in borderInfoCompute){
              //let bd_r = x.split("_")[0], bd_c = x.split("_")[1];
  
              let bd_r = x.substr(0, x.indexOf('_'));
              let bd_c = x.substr(x.indexOf('_') + 1);
  
              // if(bd_r < dataset_row_st || bd_r > dataset_row_ed || bd_c < dataset_col_st || bd_c > dataset_col_ed){
              //     continue;
              // }
  
              if(borderOffset[bd_r + "_" + bd_c]){
                  let start_r = borderOffset[bd_r + "_" + bd_c].start_r;
                  let start_c = borderOffset[bd_r + "_" + bd_c].start_c;
                  let end_r = borderOffset[bd_r + "_" + bd_c].end_r;
                  let end_c = borderOffset[bd_r + "_" + bd_c].end_c;
  
                  let cellOverflow_colInObj = cellOverflow_colIn(cellOverflowMap, bd_r, bd_c, dataset_col_st, dataset_col_ed);
  
                  let borderLeft = borderInfoCompute[x].l;
                  if(borderLeft != null && (!cellOverflow_colInObj.colIn || cellOverflow_colInObj.stc == bd_c)){
                      borderLeftRender(borderLeft.style, borderLeft.color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, luckysheetTableContent);
                  }
  
                  let borderRight = borderInfoCompute[x].r;
                  if(borderRight != null && (!cellOverflow_colInObj.colIn || cellOverflow_colInObj.colLast)){
                      borderRightRender(borderRight.style, borderRight.color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, luckysheetTableContent);
                  }
  
                  let borderTop = borderInfoCompute[x].t;
                  if(borderTop != null){
                      borderTopRender(borderTop.style, borderTop.color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, luckysheetTableContent);
                  }
  
                  let borderBottom = borderInfoCompute[x].b;
                  if(borderBottom != null){
                      borderBottomRender(borderBottom.style, borderBottom.color, start_r, start_c, end_r, end_c, offsetLeft, offsetTop, luckysheetTableContent);
                  }
              }
          }
      }
  
      //渲染表格时有尾列时，清除右边灰色区域，防止表格有值溢出
      if(dataset_col_ed == Store.visibledatacolumn.length - 1){
          luckysheetTableContent.clearRect(
              (fill_col_ed - scrollWidth + offsetLeft) - 1 , 
              (offsetTop) - 1 , 
              (Store.ch_width - Store.visibledatacolumn[dataset_col_ed]) , 
              (fill_row_ed - scrollHeight)
          );
      }
  
      luckysheetTableContent.restore();
  
      Store.measureTextCacheTimeOut = setTimeout(() => {
          Store.measureTextCache = {};
          Store.measureTextCellInfoCache = {};
          Store.cellOverflowMapCache = {};
      }, 100);
  
  }
  
  
  //sparklines渲染
  let sparklinesRender = function(r, c, offsetX, offsetY, canvasid, ctx){
      if(Store.flowdata[r] == null || Store.flowdata[r][c] == null){
          return;
      }
  
      let sparklines = Store.flowdata[r][c].spl;
      if(sparklines != null){
          if(typeof sparklines == "string"){
              sparklines = new Function("return " + sparklines)();
          }
  
          if(getObjType(sparklines) == "object"){
              let temp1 = sparklines;
              let x = temp1.offsetX;
              let y = temp1.offsetY;
              x = x == null ? 0 : x;
              y = y == null ? 0 : y;
              luckysheetSparkline.render(
                  temp1.shapeseq, 
                  temp1.shapes, 
                  offsetX + x, 
                  offsetY + y, 
                  temp1.pixelWidth, 
                  temp1.pixelHeight, 
                  canvasid, 
                  ctx
              );
          }
          else if(getObjType(sparklines) == "array" && getObjType(sparklines[0]) == "object"){
              for(let i = 0; i < sparklines.length; i++){
                  let temp1 = sparklines[i];
                  let x = temp1.offsetX;
                  let y = temp1.offsetY;
                  x = x == null ? 0 : x;
                  y = y == null ? 0 : y;
                  luckysheetSparkline.render(
                      temp1.shapeseq, 
                      temp1.shapes, 
                      offsetX + x, 
                      offsetY + y, 
                      temp1.pixelWidth, 
                      temp1.pixelHeight, 
                      canvasid, 
                      ctx
                  );
              }
          }
      }
  }
  
  //空白单元格渲染 
  let nullCellRender = function(r, c, start_r, start_c, end_r, end_c,luckysheetTableContent,af_compute,cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05,isMerge){
      let checksAF = alternateformat.checksAF(r, c, af_compute); //交替颜色
      let checksCF = conditionformat.checksCF(r, c, cf_compute); //条件格式
  
      let borderfix = menuButton.borderfix(Store.flowdata, r, c);
  
      //背景色
      let fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "bg");
  
      if(checksAF != null && checksAF[1] != null){//交替颜色 
          fillStyle = checksAF[1];
      }
  
      if(checksCF != null && checksCF["cellColor"] != null){//条件格式 
          fillStyle = checksCF["cellColor"];
      }
  
      if(Store.flowdata[r][c] != null && Store.flowdata[r][c].tc != null){//标题色
          fillStyle = Store.flowdata[r][c].tc;
      }
  
      if(fillStyle==null){
          luckysheetTableContent.fillStyle = "#FFFFFF";
      }
      else{
          luckysheetTableContent.fillStyle = fillStyle;
      }
      
  
      let cellsize = [
           (start_c + offsetLeft + borderfix[0]), 
           (start_r + offsetTop  + borderfix[1]), 
           (end_c - start_c + borderfix[2]-(!!isMerge?1:0)), 
           (end_r - start_r + borderfix[3])
      ];
      luckysheetTableContent.fillRect(cellsize[0], cellsize[1], cellsize[2], cellsize[3]);
  
      if((r + "_" + c) in dynamicArray_compute){
          let value = dynamicArray_compute[r + "_" + c].v;
  
          luckysheetTableContent.fillStyle = "#000000";
          //文本宽度和高度
          let fontset = luckysheetdefaultFont();
          luckysheetTableContent.font = fontset;
  
          //水平对齐 (默认为1，左对齐)
          let horizonAlignPos = (start_c + 4 + offsetLeft) ;
  
          //垂直对齐 (默认为2，下对齐)
          let verticalFixed = browser.luckysheetrefreshfixed();
          let verticalAlignPos = (end_r + offsetTop - 2) ; 
          luckysheetTableContent.textBaseline = 'bottom';
          
          luckysheetTableContent.fillText(value == null ? "" : value, horizonAlignPos, verticalAlignPos);
      }
  
      //若单元格有批注
      if(Store.flowdata[r][c] != null && Store.flowdata[r][c].ps != null){
          let ps_w = 8*Store.zoomRatio, ps_h = 8*Store.zoomRatio; 
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo( (end_c + offsetLeft - 1- ps_w),  (start_r + offsetTop));
          luckysheetTableContent.lineTo( (end_c + offsetLeft - 1),  (start_r + offsetTop));
          luckysheetTableContent.lineTo( (end_c + offsetLeft - 1),  (start_r + offsetTop + ps_h));
          luckysheetTableContent.fillStyle = "#FC6666";
          luckysheetTableContent.fill();
          luckysheetTableContent.closePath();
      }
  
      //此单元格 与  溢出单元格关系
      let cellOverflow_colInObj = cellOverflow_colIn(cellOverflowMap, r, c, dataset_col_st, dataset_col_ed);
  
      //此单元格 为 溢出单元格渲染范围最后一列，绘制溢出单元格内容
      if(cellOverflow_colInObj.colLast){
          cellOverflowRender(
              cellOverflow_colInObj.rowIndex,
              cellOverflow_colInObj.colIndex,
              cellOverflow_colInObj.stc,
              cellOverflow_colInObj.edc,
              luckysheetTableContent,
              scrollHeight,
              scrollWidth,
              offsetLeft,offsetTop,af_compute, cf_compute
          );
      }
  
      //即溢出单元格跨此单元格，此单元格不绘制右边框
      if(!cellOverflow_colInObj.colIn || cellOverflow_colInObj.colLast){
          //右边框
          if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                   (end_c + offsetLeft - 2 + bodrder05), 
                   (start_r + offsetTop)
              );
              luckysheetTableContent.lineTo(
                   (end_c + offsetLeft - 2 + bodrder05), 
                   (end_r + offsetTop)
              );
              luckysheetTableContent.lineWidth = 1;
  
              luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.stroke();
              luckysheetTableContent.closePath();
          }
      }
  
      //下边框
      if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
               (start_c + offsetLeft - 1), 
               (end_r + offsetTop - 2 + bodrder05)
          );
          luckysheetTableContent.lineTo(
               (end_c + offsetLeft - 1), 
               (end_r + offsetTop - 2 + bodrder05)
          );
          luckysheetTableContent.lineWidth = 1;
  
          luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;        
          luckysheetTableContent.stroke();
          luckysheetTableContent.closePath();
      }
  }
  
  
  let cellRender = function(r, c, start_r, start_c, end_r, end_c, value, luckysheetTableContent,af_compute, cf_compute,offsetLeft,offsetTop,dynamicArray_compute,cellOverflowMap, dataset_col_st, dataset_col_ed,scrollHeight,scrollWidth,bodrder05,isMerge){
      let cell = Store.flowdata[r][c];
      let cellWidth = end_c - start_c - 2;
      let cellHeight = end_r - start_r - 2;
      let space_width = 2, space_height = 2; //宽高方向 间隙
  
      //水平对齐
      let horizonAlign = menuButton.checkstatus(Store.flowdata, r, c, "ht");
      //垂直对齐
      let verticalAlign = menuButton.checkstatus(Store.flowdata, r, c, "vt");
  
      //交替颜色
      let checksAF = alternateformat.checksAF(r, c, af_compute); 
      //条件格式
      let checksCF = conditionformat.checksCF(r, c, cf_compute); 
  
      //单元格 背景颜色
      let fillStyle = menuButton.checkstatus(Store.flowdata, r, c, "bg");
      if(checksAF != null && checksAF[1] != null){ //若单元格有交替颜色 背景颜色
          fillStyle = checksAF[1];
      }
      if(checksCF != null && checksCF["cellColor"] != null){ //若单元格有条件格式 背景颜色
          fillStyle = checksCF["cellColor"];
      }
      // luckysheetTableContent.textBaseline = 'top';
      if(fillStyle==null){
          luckysheetTableContent.fillStyle = "#FFFFFF";
      }
      else{
          luckysheetTableContent.fillStyle = fillStyle;
      }
  
      let borderfix = menuButton.borderfix(Store.flowdata, r, c);
      // console.log(value, fillStyle,borderfix);
      let cellsize = [
          (start_c + offsetLeft + borderfix[0]), 
          (start_r + offsetTop  + borderfix[1]), 
          (end_c - start_c + borderfix[2]-(!!isMerge?1:0)), 
          (end_r - start_r + borderfix[3])
      ];
      luckysheetTableContent.fillRect(cellsize[0], cellsize[1], cellsize[2], cellsize[3]);
  
      let dataVerification = dataVerificationCtrl.dataVerification;
  
      if(dataVerification != null && dataVerification[r + '_' + c] != null && !dataVerificationCtrl.validateCellData(value, dataVerification[r + '_' + c])){
          //单元格左上角红色小三角标示
          let dv_w = 5 * Store.zoomRatio, dv_h = 5 * Store.zoomRatio; //红色小三角宽高
  
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
              (start_c + offsetLeft), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (start_c + offsetLeft + dv_w), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (start_c + offsetLeft), 
              (start_r + offsetTop + dv_h)
          );
          luckysheetTableContent.fillStyle = "#FC6666";
          luckysheetTableContent.fill();
          luckysheetTableContent.closePath();
      }
  
      //若单元格有批注（单元格右上角红色小三角标示）
      if(cell.ps != null){
          let ps_w = 8*Store.zoomRatio, ps_h = 8*Store.zoomRatio; //红色小三角宽高
  
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
              (end_c + offsetLeft - ps_w), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (end_c + offsetLeft), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (end_c + offsetLeft), 
              (start_r + offsetTop + ps_h)
          );
          luckysheetTableContent.fillStyle = "#FC6666";
          luckysheetTableContent.fill();
          luckysheetTableContent.closePath();
      }
  
      //若单元格强制为字符串，则显示绿色小三角
      if(cell.qp==1 && isRealNum(cell.v)){
          let ps_w = 6*Store.zoomRatio, ps_h = 6*Store.zoomRatio; //红色小三角宽高
  
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
              (start_c + offsetLeft + ps_w-1), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (start_c + offsetLeft-1), 
              (start_r + offsetTop)
          );
          luckysheetTableContent.lineTo(
              (start_c + offsetLeft-1), 
              (start_r + offsetTop + ps_h)
          );
          luckysheetTableContent.fillStyle = "#487f1e";
          luckysheetTableContent.fill();
          luckysheetTableContent.closePath();
      }
  
      //溢出单元格
      let cellOverflow_bd_r_render = true; //溢出单元格右边框是否需要绘制
      let cellOverflow_colInObj = cellOverflow_colIn(cellOverflowMap, r, c, dataset_col_st, dataset_col_ed);
  
      if(cell.tb == '1' && cellOverflow_colInObj.colIn){
          //此单元格 为 溢出单元格渲染范围最后一列，绘制溢出单元格内容
          if(cellOverflow_colInObj.colLast){
              cellOverflowRender(
                  cellOverflow_colInObj.rowIndex,
                  cellOverflow_colInObj.colIndex,
                  cellOverflow_colInObj.stc,
                  cellOverflow_colInObj.edc,
                  luckysheetTableContent,
                  scrollHeight,
                  scrollWidth,offsetLeft,offsetTop,af_compute, cf_compute
              );
          }
          else{
              cellOverflow_bd_r_render = false;
          }
      }
      //数据验证 复选框
      else if(dataVerification != null && dataVerification[r + '_' + c] != null && dataVerification[r + '_' + c].type == 'checkbox'){
          let pos_x = start_c + offsetLeft;
          let pos_y = start_r + offsetTop + 1;
  
          luckysheetTableContent.save();
          luckysheetTableContent.beginPath();
          luckysheetTableContent.rect(pos_x, pos_y, cellWidth, cellHeight);
          luckysheetTableContent.clip();
          luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio);
          
          let measureText = getMeasureText(value, luckysheetTableContent);
          let textMetrics = measureText.width + 14;
          let oneLineTextHeight = measureText.actualBoundingBoxDescent + measureText.actualBoundingBoxAscent;
  
          let horizonAlignPos = (pos_x + space_width) ; //默认为1，左对齐
          if(horizonAlign == "0"){ //居中对齐
              horizonAlignPos = (pos_x + cellWidth / 2)  - (textMetrics / 2);
          }
          else if(horizonAlign == "2"){ //右对齐
              horizonAlignPos = (pos_x + cellWidth - space_width)  - textMetrics;
          }
          
          let verticalCellHeight = cellHeight > oneLineTextHeight ? cellHeight : oneLineTextHeight;
  
          let verticalAlignPos_text = (pos_y + verticalCellHeight - space_height) ; //文本垂直方向基准线
          luckysheetTableContent.textBaseline = "bottom";
          let verticalAlignPos_checkbox = verticalAlignPos_text - 13 * Store.zoomRatio;
  
          if(verticalAlign == "0"){ //居中对齐 
              verticalAlignPos_text = (pos_y + verticalCellHeight / 2);
              luckysheetTableContent.textBaseline = "middle";
              verticalAlignPos_checkbox = verticalAlignPos_text - 6 * Store.zoomRatio;
          }
          else if(verticalAlign == "1"){ //上对齐
              verticalAlignPos_text = (pos_y + space_height);
              luckysheetTableContent.textBaseline = "top";
              verticalAlignPos_checkbox = verticalAlignPos_text + 1 * Store.zoomRatio;
          }
  
          horizonAlignPos = horizonAlignPos / Store.zoomRatio;
          verticalAlignPos_text = verticalAlignPos_text / Store.zoomRatio;
          verticalAlignPos_checkbox = verticalAlignPos_checkbox / Store.zoomRatio;
  
          //复选框
          luckysheetTableContent.lineWidth = 1;
          luckysheetTableContent.strokeStyle = "#000";
          luckysheetTableContent.strokeRect(horizonAlignPos, verticalAlignPos_checkbox, 10, 10);
  
          if(dataVerification[r + '_' + c].checked){
              luckysheetTableContent.beginPath();
              luckysheetTableContent.lineTo(
                  horizonAlignPos + 1, 
                  verticalAlignPos_checkbox + 6
              );
              luckysheetTableContent.lineTo(
                  horizonAlignPos + 4, 
                  verticalAlignPos_checkbox + 9
              );
              luckysheetTableContent.lineTo(
                  horizonAlignPos + 9, 
                  verticalAlignPos_checkbox + 2
              );
              luckysheetTableContent.stroke();
              luckysheetTableContent.closePath();
          }
  
          //文本
          luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc");
          luckysheetTableContent.fillText(value == null ? "" : value, horizonAlignPos + 14, verticalAlignPos_text);
          
          luckysheetTableContent.restore();
      }
      else{
          //若单元格有条件格式数据条
          if(checksCF != null && checksCF["dataBar"] != null){
              let x =  (start_c + offsetLeft + space_width);
              let y =  (start_r + offsetTop + space_height);
              let w =  (cellWidth - space_width * 2);
              let h =  (cellHeight - space_height * 2);
  
              let valueType = checksCF["dataBar"]["valueType"];
              let valueLen = checksCF["dataBar"]["valueLen"];
              let format = checksCF["dataBar"]["format"];
  
              if(valueType == 'minus'){
                  //负数
                  let minusLen = checksCF["dataBar"]["minusLen"];
                  
                  if(format.length > 1){
                      //渐变
                      let my_gradient = luckysheetTableContent.createLinearGradient(
                          x + w * minusLen * (1 - valueLen), 
                          y, 
                          x + w * minusLen, 
                          y
                      );
                      my_gradient.addColorStop(0, "#ffffff");
                      my_gradient.addColorStop(1, "#ff0000");
  
                      luckysheetTableContent.fillStyle = my_gradient;
                  }
                  else{
                      //单色
                      luckysheetTableContent.fillStyle = "#ff0000";
                  }
                  
                  luckysheetTableContent.fillRect(
                      x + w * minusLen * (1 - valueLen), 
                      y, 
                      w * minusLen * valueLen, 
                      h
                  );
  
                  luckysheetTableContent.beginPath();
                  luckysheetTableContent.moveTo(
                      x + w * minusLen * (1 - valueLen), 
                      y
                  );
                  luckysheetTableContent.lineTo(
                      x + w * minusLen * (1 - valueLen), 
                      y + h
                  );
                  luckysheetTableContent.lineTo(
                      x + w * minusLen, 
                      y + h
                  );
                  luckysheetTableContent.lineTo(
                      x + w * minusLen, 
                      y
                  );
                  luckysheetTableContent.lineTo(
                      x + w * minusLen * (1 - valueLen), 
                      y
                  );
                  luckysheetTableContent.lineWidth = 1;
                  luckysheetTableContent.strokeStyle = "#ff0000";
                  luckysheetTableContent.stroke();
                  luckysheetTableContent.closePath();
              }
              else if(valueType == 'plus'){
                  //正数
                  let plusLen = checksCF["dataBar"]["plusLen"];
  
                  if(plusLen == 1){
                      if(format.length > 1){
                          //渐变
                          let my_gradient = luckysheetTableContent.createLinearGradient(
                              x, 
                              y, 
                              x + w * valueLen, 
                              y
                          );
                          my_gradient.addColorStop(0, format[0]);
                          my_gradient.addColorStop(1, format[1]);
      
                          luckysheetTableContent.fillStyle = my_gradient;
                      }
                      else{
                          //单色
                          luckysheetTableContent.fillStyle = format[0];
                      }
                      
                      luckysheetTableContent.fillRect(
                          x, 
                          y, 
                          w * valueLen, 
                          h
                      );
  
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                          x, 
                          y
                      );
                      luckysheetTableContent.lineTo(
                          x, 
                          y + h
                      );
                      luckysheetTableContent.lineTo(
                          x + w * valueLen, 
                          y + h
                      );
                      luckysheetTableContent.lineTo(
                          x + w * valueLen, 
                          y
                      );
                      luckysheetTableContent.lineTo(
                          x, 
                          y
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = format[0];
                      luckysheetTableContent.stroke();
                      luckysheetTableContent.closePath();
                  }
                  else{
                      let minusLen = checksCF["dataBar"]["minusLen"];
  
                      if(format.length > 1){
                          //渐变
                          let my_gradient = luckysheetTableContent.createLinearGradient(
                              x + w * minusLen, 
                              y, 
                              x + w * minusLen + w * plusLen * valueLen, 
                              y
                          );
                          my_gradient.addColorStop(0, format[0]);
                          my_gradient.addColorStop(1, format[1]);
      
                          luckysheetTableContent.fillStyle = my_gradient;
                      }
                      else{
                          //单色
                          luckysheetTableContent.fillStyle = format[0];
                      }
                      
                      luckysheetTableContent.fillRect(
                          x + w * minusLen, 
                          y, 
                          w * plusLen * valueLen, 
                          h
                      );
  
                      luckysheetTableContent.beginPath();
                      luckysheetTableContent.moveTo(
                          x + w * minusLen, 
                          y
                      );
                      luckysheetTableContent.lineTo(
                          x + w * minusLen, 
                          y + h
                      );
                      luckysheetTableContent.lineTo(
                          x + w * minusLen + w * plusLen * valueLen, 
                          y + h
                      );
                      luckysheetTableContent.lineTo(
                          x + w * minusLen + w * plusLen * valueLen, 
                          y
                      );
                      luckysheetTableContent.lineTo(
                          x + w * minusLen, 
                          y
                      );
                      luckysheetTableContent.lineWidth = 1;
                      luckysheetTableContent.strokeStyle = format[0];
                      luckysheetTableContent.stroke();
                      luckysheetTableContent.closePath();
                  }
              }
          }
  
          let pos_x = start_c + offsetLeft;
          let pos_y = start_r + offsetTop + 1;
  
          luckysheetTableContent.save();
          luckysheetTableContent.beginPath();
          luckysheetTableContent.rect(pos_x , pos_y, cellWidth , cellHeight );
          luckysheetTableContent.clip();
          luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio);
  
  
          let textInfo = getCellTextInfo(cell , luckysheetTableContent, {
              cellWidth:cellWidth,
              cellHeight:cellHeight,
              space_width:space_width,
              space_height:space_height,
              r:r,
              c:c
          });
  
          //若单元格有条件格式图标集
          if(checksCF != null && checksCF["icons"] != null && textInfo.type=="plain"){
              let l = checksCF["icons"]["left"];
              let t = checksCF["icons"]["top"];
              
              let value = textInfo.values[0]
              let horizonAlignPos = pos_x +  value.left;
              let verticalAlignPos = pos_y + value.top- textInfo.textHeightAll;
  
              if(verticalAlign == "0"){ //居中对齐 
                  verticalAlignPos = pos_y + cellHeight/2 - textInfo.textHeightAll/2;
              }
              else if(verticalAlign == "1"){ //上对齐
                  verticalAlignPos = pos_y;
              }
              else if(verticalAlign == "2"){ //下对齐
                  verticalAlignPos =verticalAlignPos - textInfo.desc;
              }
  
              verticalAlignPos = verticalAlignPos/Store.zoomRatio;
              horizonAlignPos = horizonAlignPos/Store.zoomRatio;
  
              luckysheetTableContent.drawImage(
                  luckysheet_CFiconsImg, 
                  l * 42, 
                  t * 32, 
                  32, 
                  32, 
                  pos_x/Store.zoomRatio , 
                  verticalAlignPos,  
                  textInfo.textHeightAll/Store.zoomRatio, 
                  textInfo.textHeightAll/Store.zoomRatio
              );
              
              if(horizonAlign != "0" && horizonAlign != "2"){ //左对齐时 文本渲染空出一个图标的距离
                  horizonAlignPos = horizonAlignPos + textInfo.textHeightAll/Store.zoomRatio;
              }
          }
  
          //单元格 文本颜色
          luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc");
          
          //若单元格有交替颜色 文本颜色
          if(checksAF != null && checksAF[0] != null){ 
              luckysheetTableContent.fillStyle = checksAF[0];
          }
          //若单元格有条件格式 文本颜色
          if(checksCF != null && checksCF["textColor"] != null){ 
              luckysheetTableContent.fillStyle = checksCF["textColor"];
          }
  
  
          cellTextRender(
              textInfo,
              luckysheetTableContent,
              {
                  pos_x:pos_x,
                  pos_y:pos_y,
              }
          );
  
  
          luckysheetTableContent.restore();
      }
  
      if(cellOverflow_bd_r_render){
          //右边框
          if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){
              luckysheetTableContent.beginPath();
              luckysheetTableContent.moveTo(
                   (end_c + offsetLeft - 2 + bodrder05), 
                   (start_r + offsetTop)
              );
              luckysheetTableContent.lineTo(
                   (end_c + offsetLeft - 2 + bodrder05), 
                   (end_r + offsetTop)
              );
              luckysheetTableContent.lineWidth = 1;
              luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
              luckysheetTableContent.stroke();
              luckysheetTableContent.closePath();
          }
      }
  
      //下边框
      if(!Store.luckysheetcurrentisPivotTable && !fillStyle && Store.showGridLines){
          luckysheetTableContent.beginPath();
          luckysheetTableContent.moveTo(
               (start_c + offsetLeft - 1), 
               (end_r + offsetTop - 2 + bodrder05)
          );
          luckysheetTableContent.lineTo(
               (end_c + offsetLeft - 1), 
               (end_r + offsetTop - 2 + bodrder05)
          );
          luckysheetTableContent.lineWidth = 1;
          luckysheetTableContent.strokeStyle = luckysheetdefaultstyle.strokeStyle;
          luckysheetTableContent.stroke();
          luckysheetTableContent.closePath();
      }
  }
  
  //溢出单元格渲染
  let cellOverflowRender = function(r, c, stc, edc,luckysheetTableContent,scrollHeight,scrollWidth,offsetLeft,offsetTop,af_compute, cf_compute){
      //溢出单元格 起止行列坐标
      let start_r;
      if (r == 0) {
          start_r = -scrollHeight - 1;
      }
      else {
          start_r = Store.visibledatarow[r - 1] - scrollHeight - 1;
      }
  
      let end_r = Store.visibledatarow[r] - scrollHeight;
  
      let start_c;
      if (stc == 0) {
          start_c = -scrollWidth;
      }
      else {
          start_c = Store.visibledatacolumn[stc - 1] - scrollWidth;
      }
  
      let end_c = Store.visibledatacolumn[edc] - scrollWidth;
  
      //
      let cell = Store.flowdata[r][c];
      let cellWidth = end_c - start_c - 2;
      let cellHeight = end_r - start_r - 2;
      let space_width = 2, space_height = 2; //宽高方向 间隙
  
      let pos_x = start_c + offsetLeft;
      let pos_y = start_r + offsetTop + 1;
  
      let fontset = luckysheetfontformat(cell);
      luckysheetTableContent.font = fontset;
  
      luckysheetTableContent.save();
      luckysheetTableContent.beginPath();
      luckysheetTableContent.rect(pos_x , pos_y, cellWidth , cellHeight );
      luckysheetTableContent.clip();
      luckysheetTableContent.scale(Store.zoomRatio,Store.zoomRatio);
      
  
      let textInfo = getCellTextInfo(cell , luckysheetTableContent, {
          cellWidth:cellWidth,
          cellHeight:cellHeight,
          space_width:space_width,
          space_height:space_height,
          r:r,
          c:c
      });
  
      //交替颜色
      let checksAF = alternateformat.checksAF(r, c, af_compute); 
      //条件格式
      let checksCF = conditionformat.checksCF(r, c, cf_compute); 
  
      //单元格 文本颜色
      luckysheetTableContent.fillStyle = menuButton.checkstatus(Store.flowdata, r, c , "fc");
          
      //若单元格有交替颜色 文本颜色
      if(checksAF != null && checksAF[0] != null){ 
          luckysheetTableContent.fillStyle = checksAF[0];
      }
      //若单元格有条件格式 文本颜色
      if(checksCF != null && checksCF["textColor"] != null){ 
          luckysheetTableContent.fillStyle = checksCF["textColor"];
      }
  
      cellTextRender(
          textInfo,
          luckysheetTableContent,
          {
              pos_x:pos_x,
              pos_y:pos_y,
          }
      );
  
      luckysheetTableContent.restore();
  
  }
  
  //获取表格渲染范围 溢出单元格 
  function getCellOverflowMap(canvas, col_st, col_ed, row_st, row_end){
      let map = {};
  
      let data = Store.flowdata;
  
      for(let r = row_st; r <= row_end; r++){
          if(data[r]==null){
              continue;
          }
  
          if(Store.cellOverflowMapCache[r]!=null){
              map[r] = Store.cellOverflowMapCache[r];
              continue;
          }
  
          let hasCellOver = false;
  
          for(let c = 0; c < data[r].length; c++){
              let cell = data[r][c];
  
              // if(Store.cellOverflowMapCache[r + '_' + c]!=null){
              //     map[r + '_' + c] = Store.cellOverflowMapCache[r + '_' + c];
              //     continue;
              // }
  
              if (Store.config["colhidden"] != null && Store.config["colhidden"][c] != null) {
                  continue
              }
  
              if(cell != null && (!isRealNull(cell.v) || isInlineStringCell(cell) ) && cell.mc == null && cell.tb == '1'){
  
                  //水平对齐
                  let horizonAlign = menuButton.checkstatus(data, r, c, "ht");
  
                  
                  let textMetricsObj = getCellTextInfo(cell, canvas,{
                      r:r,
                      c:c,
                  });
                  let textMetrics = 0;
                  if(textMetricsObj!=null){
                      textMetrics = textMetricsObj.textWidthAll;
                  }
  
                  //canvas.measureText(value).width;
  
                  let start_c = c - 1 < 0 ? 0 : Store.visibledatacolumn[c - 1];
                  let end_c = Store.visibledatacolumn[c];
  
                  let stc, edc;
  
                  if((end_c - start_c) < textMetrics){
                      if(horizonAlign == '0'){//居中对齐
                          let trace_forward = cellOverflow_trace(r, c, c - 1, 'forward', horizonAlign, textMetrics);
                          let trace_backward = cellOverflow_trace(r, c, c + 1, 'backward', horizonAlign, textMetrics);
                      
                          if(trace_forward.success){
                              stc = trace_forward.c;
                          }
                          else{
                              stc = trace_forward.c + 1;
                          }
  
                          if(trace_backward.success){
                              edc = trace_backward.c;
                          }
                          else{
                              edc = trace_backward.c - 1;
                          }
                      }
                      else if(horizonAlign == '1'){//左对齐
                          let trace = cellOverflow_trace(r, c, c + 1, 'backward', horizonAlign, textMetrics);
                          stc = c;
  
                          if(trace.success){
                              edc = trace.c;
                          }
                          else{
                              edc = trace.c - 1;
                          }
                      }
                      else if(horizonAlign == '2'){//右对齐
                          let trace = cellOverflow_trace(r, c, c - 1, 'forward', horizonAlign, textMetrics);
                          edc = c;
  
                          if(trace.success){
                              stc = trace.c;
                          }
                          else{
                              stc = trace.c + 1;
                          }
                      }
                  }
                  else{
                      stc = c;
                      edc = c;
                  }
  
                  // if(((stc >= col_st && stc <= col_ed) || (edc >= col_st && edc <= col_ed)) && stc < edc){
                  if(((stc <= col_ed) || (edc >= col_st)) && stc < edc){
                      let item = {
                          r: r,
                          stc: stc,
                          edc: edc 
                      }
  
                      if(map[r]==null){
                          map[r] = {};
                      }
  
                      map[r][c] = item;
  
                      // Store.cellOverflowMapCache[r + '_' + c] = item;
  
                      hasCellOver = true;
                  }
              }
          }
  
          if(hasCellOver){
              Store.cellOverflowMapCache[r] = map[r];
          }
  
      }
  
      return map;
  }
  
  function cellOverflow_trace(r, curC, traceC, traceDir, horizonAlign, textMetrics){
      let data = Store.flowdata; 
  
      //追溯单元格列超出数组范围 则追溯终止
      if(traceDir == 'forward' && traceC < 0){
          return {
              success: false,
              r: r,
              c: traceC
          }; 
      }
      
      if(traceDir == 'backward' && traceC > data[r].length - 1){
          return {
              success: false,
              r: r,
              c: traceC
          };
      }
  
      //追溯单元格是 非空单元格或合并单元格 则追溯终止
      let cell = data[r][traceC];
      if(cell != null && (!isRealNull(cell.v) || cell.mc != null)){
          return {
              success: false,
              r: r,
              c: traceC
          };
      }
  
      let start_curC = curC - 1 < 0 ? 0 : Store.visibledatacolumn[curC - 1];
      let end_curC = Store.visibledatacolumn[curC];
  
      let w = textMetrics - (end_curC - start_curC);
  
      if(horizonAlign == '0'){//居中对齐
          start_curC -= w / 2;
          end_curC += w / 2;
      }
      else if(horizonAlign == '1'){//左对齐
          end_curC += w;
      }
      else if(horizonAlign == '2'){//右对齐
          start_curC -= w;
      }
  
      let start_traceC = traceC - 1 < 0 ? 0 : Store.visibledatacolumn[traceC - 1];
      let end_traceC = Store.visibledatacolumn[traceC];
  
      if(traceDir == 'forward'){
          if(start_curC < start_traceC){
              return cellOverflow_trace(r, curC, traceC - 1, traceDir, horizonAlign, textMetrics);
          }
          else if(start_curC < end_traceC){
              return {
                  success: true,
                  r: r,
                  c: traceC
              }
          }
          else{
              return {
                  success: false,
                  r: r,
                  c: traceC
              }
          }
      }
      
      if(traceDir == 'backward'){
          if(end_curC > end_traceC){
              return cellOverflow_trace(r, curC, traceC + 1, traceDir, horizonAlign, textMetrics);
          }
          else if(end_curC > start_traceC){
              return {
                  success: true,
                  r: r,
                  c: traceC
              }
          }
          else{
              return {
                  success: false,
                  r: r,
                  c: traceC
              }
          }
      }
  }
  
  function cellOverflow_colIn(map, r, c, col_st, col_ed){
      let colIn = false, //此单元格 是否在 某个溢出单元格的渲染范围
          colLast = false, //此单元格 是否是 某个溢出单元格的渲染范围的最后一列
          rowIndex, //溢出单元格 行下标 
          colIndex, //溢出单元格 列下标
          stc,
          edc;
  
      for(let rkey in map){
          for(let ckey in map[rkey]){
              rowIndex = rkey;
              colIndex = ckey;
              // rowIndex = key.substr(0, key.indexOf('_'));
              // colIndex = key.substr(key.indexOf('_') + 1);
              let mapItem = map[rkey][ckey];
              stc = mapItem.stc;
              edc = mapItem.edc;
  
              if(rowIndex == r){
                  if(c >= stc && c <= edc){
                      colIn = true;
  
                      if(c == edc || c == col_ed){
                          colLast = true;
                          break;
                      }
                  }
              }
          }
  
          if(colLast){
              break;
          }
      }
  
      return {
          colIn: colIn,
          colLast: colLast,
          rowIndex: rowIndex,
          colIndex: colIndex,
          stc: stc,
          edc: edc
      }
  }
  
  function cellTextRender(textInfo, ctx, option){
      if(textInfo==null){
          return
      }
      let values = textInfo.values;
      let pos_x = option.pos_x, pos_y = option.pos_y;
      if(values==null){
          return;
      }
      // console.log(textInfo, pos_x, pos_y, values[0].width, values[0].left, ctx);
  
      // for(let i=0;i<values.length;i++){
      //     let word = values[i];
      //     ctx.font = word.style;
      //     ctx.fillText(word.content, (pos_x + word.left)/Store.zoomRatio, (pos_y+word.top)/Store.zoomRatio);
      // }
  
      // ctx.fillStyle = "rgba(255,255,0,0.2)";
      // ctx.fillRect((pos_x + values[0].left)/Store.zoomRatio, (pos_y+values[0].top-values[0].asc)/Store.zoomRatio, textInfo.textWidthAll, textInfo.textHeightAll)
  
      if(textInfo.rotate!=0 && textInfo.type!="verticalWrap"){
          ctx.save();
          ctx.translate((pos_x+textInfo.textLeftAll)/Store.zoomRatio, (pos_y+textInfo.textTopAll)/Store.zoomRatio);
          ctx.rotate(-textInfo.rotate * Math.PI / 180);
          ctx.translate(-(textInfo.textLeftAll+pos_x)/Store.zoomRatio, -(pos_y+textInfo.textTopAll)/Store.zoomRatio);
      }
  
      // ctx.fillStyle = "rgb(0,0,0)";
      for(let i=0;i<values.length;i++){
          let word = values[i];
          if(word.inline===true && word.style!=null){
              ctx.font = word.style.fontset;
              ctx.fillStyle = word.style.fc;
          }
          else{
              ctx.font = word.style;
          }
          
          ctx.fillText(word.content, (pos_x + word.left)/Store.zoomRatio, (pos_y+word.top)/Store.zoomRatio);
          
          if(word.cancelLine!=null){
              let c = word.cancelLine;
              ctx.beginPath();
              ctx.moveTo(
                  Math.floor((pos_x +c.startX)/Store.zoomRatio)+0.5 ,
                  Math.floor((pos_y+c.startY)/Store.zoomRatio)+0.5 ,
              );
              ctx.lineTo(
                  Math.floor((pos_x +c.endX)/Store.zoomRatio)+0.5 ,
                  Math.floor((pos_y+c.endY)/Store.zoomRatio)+0.5 ,
              );
              ctx.lineWidth = Math.floor(c.fs/9);
              ctx.strokeStyle = ctx.fillStyle;
              ctx.stroke();
              ctx.closePath();
          }
  
          if(word.underLine!=null){
              let underLines = word.underLine;
              for(let a=0;a<underLines.length;a++){
                  let item = underLines[a];
                  ctx.beginPath();
                  ctx.moveTo(
                      Math.floor((pos_x +item.startX)/Store.zoomRatio)+0.5 ,
                      Math.floor((pos_y+item.startY)/Store.zoomRatio)
                  );
                  ctx.lineTo(
                      Math.floor((pos_x +item.endX)/Store.zoomRatio)+0.5,
                      Math.floor((pos_y+ item.endY)/Store.zoomRatio)+0.5
                  );
                  ctx.lineWidth = Math.floor(item.fs/9);
                  ctx.strokeStyle = ctx.fillStyle;
                  ctx.stroke();
                  ctx.closePath();
              }
          }
      }
      // ctx.fillStyle = "rgba(0,0,0,0.2)";
      // ctx.fillRect((pos_x + values[0].left)/Store.zoomRatio, (pos_y+values[0].top-values[0].asc)/Store.zoomRatio, textInfo.textWidthAll, textInfo.textHeightAll)
      // ctx.fillStyle = "rgba(255,0,0,1)";
      // ctx.fillRect(pos_x+textInfo.textLeftAll-2, pos_y+textInfo.textTopAll-2, 4,4);
      if(textInfo.rotate!=0 && textInfo.type!="verticalWrap"){
          ctx.restore();
      }
  }
  
  
  export {
      luckysheetDrawgridRowTitle,
      luckysheetDrawgridColumnTitle,
      luckysheetDrawMain,
  }