From c24be9ff0a1c408dd0f10933d20e9ddb96d2ff2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20I=C3=9Fbr=C3=BCcker?= Date: Thu, 14 Nov 2024 17:21:45 +0100 Subject: [PATCH] handle indexed and rgb colors --- .../spreadsheet/ColorConverterUtil.java | 11 ++- .../spreadsheet/XSSFColorConverter.java | 22 +++-- .../tests/XSSFColorConverterTest.java | 89 +++++++++++++++++++ 3 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/test/java/com/vaadin/flow/component/spreadsheet/tests/XSSFColorConverterTest.java diff --git a/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/ColorConverterUtil.java b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/ColorConverterUtil.java index 9211fff6e94..32bef8a9a92 100644 --- a/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/ColorConverterUtil.java +++ b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/ColorConverterUtil.java @@ -14,16 +14,19 @@ public class ColorConverterUtil implements Serializable { public static String toRGBA(byte[] argb) { int rgba[] = new int[3]; - for (int i = 1; i < argb.length; i++) { + boolean hasAlpha = argb.length == 4; + float alpha = hasAlpha ? argb[0] : 1.0f; + int channelOffset = hasAlpha ? 1 : 0; + + for (int i = channelOffset; i < argb.length; i++) { int x = argb[i]; if (x < 0) { x += 256; } - rgba[i - 1] = x; + rgba[i - channelOffset] = x; } - float x = argb[0]; - return buildRgba(rgba, x); + return buildRgba(rgba, alpha); } public static String toRGBA(String hexARGB) { diff --git a/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/XSSFColorConverter.java b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/XSSFColorConverter.java index 7e1e0fd4635..9c325cd1ef4 100644 --- a/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/XSSFColorConverter.java +++ b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/main/java/com/vaadin/flow/component/spreadsheet/XSSFColorConverter.java @@ -14,6 +14,7 @@ import org.apache.poi.ss.usermodel.BorderFormatting; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.xssf.model.ThemesTable; import org.apache.poi.xssf.usermodel.XSSFBorderFormatting; import org.apache.poi.xssf.usermodel.XSSFCellStyle; @@ -24,7 +25,6 @@ import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder.BorderSide; import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; -import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; @@ -288,6 +288,11 @@ public String getBackgroundColorCSS(ConditionalFormattingRule rule) { // CF rules have tint in bgColor but not the XSSFColor. return styleColor(themeColor, bgColor.getTint()); + } else if (bgColor.isSetIndexed()) { + XSSFColor mappedColor = new XSSFColor( + IndexedColors.fromInt((int) bgColor.getIndexed()), + workbook.getStylesSource().getIndexedColors()); + return styleColor(mappedColor, bgColor.getTint()); } else { byte[] rgb = bgColor.getRgb(); return rgb == null ? null : ColorConverterUtil.toRGBA(rgb); @@ -320,6 +325,11 @@ public String getFontColorCSS(ConditionalFormattingRule rule) { .getThemeColor((int) ctColor.getTheme()); return styleColor(themeColor, ctColor.getTint()); + } else if (ctColor.isSetIndexed()) { + XSSFColor mappedColor = new XSSFColor( + IndexedColors.fromInt((int) ctColor.getIndexed()), + workbook.getStylesSource().getIndexedColors()); + return styleColor(mappedColor, ctColor.getTint()); } else { byte[] rgb = ctColor.getRgb(); return rgb == null ? null : ColorConverterUtil.toRGBA(rgb); @@ -405,16 +415,12 @@ private byte applyTint(int lum, double tint) { */ private CTDxf getXMLColorDataWithReflection( XSSFConditionalFormattingRule rule) { - CTCfRule realRule = null; - Method declaredMethod = null; try { - declaredMethod = rule.getClass().getDeclaredMethod("getCTCfRule"); + declaredMethod = rule.getClass().getDeclaredMethod("getDxf", + boolean.class); declaredMethod.setAccessible(true); - realRule = (CTCfRule) declaredMethod.invoke(rule); - CTDxf dxf = workbook.getStylesSource().getCTStylesheet().getDxfs() - .getDxfArray((int) realRule.getDxfId()); - return dxf; + return (CTDxf) declaredMethod.invoke(rule, false); } catch (Exception e) { LOGGER.debug(e.getMessage()); return null; diff --git a/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/test/java/com/vaadin/flow/component/spreadsheet/tests/XSSFColorConverterTest.java b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/test/java/com/vaadin/flow/component/spreadsheet/tests/XSSFColorConverterTest.java new file mode 100644 index 00000000000..c5324094a52 --- /dev/null +++ b/vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow/src/test/java/com/vaadin/flow/component/spreadsheet/tests/XSSFColorConverterTest.java @@ -0,0 +1,89 @@ +/** + * Copyright 2000-2024 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * See {@literal } for the full + * license. + */ +package com.vaadin.flow.component.spreadsheet.tests; + +import org.apache.poi.ss.usermodel.ComparisonOperator; +import org.apache.poi.ss.usermodel.ConditionalFormattingRule; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.xssf.usermodel.XSSFColor; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.flow.component.spreadsheet.Spreadsheet; +import com.vaadin.flow.component.spreadsheet.XSSFColorConverter; + +public class XSSFColorConverterTest { + + private Spreadsheet spreadsheet; + private XSSFColorConverter converter; + + @Before + public void setUp() { + spreadsheet = new Spreadsheet(); + converter = new XSSFColorConverter( + (XSSFWorkbook) spreadsheet.getWorkbook()); + } + + @Test + public void getFontColorCSS_withIndexedColor() { + var rule = createRule(); + var font = rule.createFontFormatting(); + font.setFontColorIndex(IndexedColors.RED.index); + + var cssColor = converter.getFontColorCSS(rule); + + Assert.assertEquals("rgba(255, 0, 0, 1.0);", cssColor); + } + + @Test + public void getFontColorCSS_withRgbColor() { + var rule = createRule(); + var font = rule.createFontFormatting(); + var color = new XSSFColor( + new byte[] { (byte) 255, (byte) 128, (byte) 64 }); + font.setFontColor(color); + + var cssColor = converter.getFontColorCSS(rule); + + Assert.assertEquals("rgba(255, 128, 64, 1.0);", cssColor); + } + + @Test + public void getBackgroundColorCSS_withIndexedColor() { + var rule = createRule(); + var pattern = rule.createPatternFormatting(); + pattern.setFillBackgroundColor(IndexedColors.RED.index); + + var cssColor = converter.getBackgroundColorCSS(rule); + + Assert.assertEquals("rgba(255, 0, 0, 1.0);", cssColor); + } + + @Test + public void getBackgroundColorCSS_withRgbColor() { + var rule = createRule(); + var pattern = rule.createPatternFormatting(); + var color = new XSSFColor( + new byte[] { (byte) 255, (byte) 128, (byte) 64 }); + pattern.setFillBackgroundColor(color); + + var cssColor = converter.getBackgroundColorCSS(rule); + + Assert.assertEquals("rgba(255, 128, 64, 1.0);", cssColor); + } + + private ConditionalFormattingRule createRule() { + var conditionalFormatting = spreadsheet.getActiveSheet() + .getSheetConditionalFormatting(); + return conditionalFormatting + .createConditionalFormattingRule(ComparisonOperator.LT, "0"); + } +}