| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.xssf.usermodel; |
| |
| import static org.apache.poi.ss.usermodel.FontCharset.*; |
| import static org.junit.jupiter.api.Assertions.*; |
| |
| import java.io.IOException; |
| import java.util.stream.Stream; |
| |
| import org.apache.poi.common.usermodel.fonts.FontCharset; |
| import org.apache.poi.ooxml.POIXMLException; |
| import org.apache.poi.ss.usermodel.BaseTestFont; |
| import org.apache.poi.ss.usermodel.Font; |
| import org.apache.poi.ss.usermodel.FontFamily; |
| import org.apache.poi.ss.usermodel.FontScheme; |
| import org.apache.poi.ss.usermodel.FontUnderline; |
| import org.apache.poi.ss.usermodel.IndexedColors; |
| import org.apache.poi.ss.usermodel.Workbook; |
| import org.apache.poi.ss.util.SheetUtil; |
| import org.apache.poi.util.LocaleUtil; |
| import org.apache.poi.xssf.XSSFITestDataProvider; |
| import org.apache.poi.xssf.XSSFTestDataSamples; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.params.provider.Arguments; |
| import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STVerticalAlignRun; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBooleanProperty; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontFamily; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontName; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontScheme; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFontSize; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTIntProperty; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTUnderlineProperty; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTVerticalAlignFontProperty; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.STFontScheme; |
| import org.openxmlformats.schemas.spreadsheetml.x2006.main.STUnderlineValues; |
| |
| public final class TestXSSFFont extends BaseTestFont { |
| |
| public TestXSSFFont() { |
| super(XSSFITestDataProvider.instance); |
| } |
| |
| @SuppressWarnings("unused") |
| public static Stream<Arguments> defaultFont() { |
| return Stream.of(Arguments.of("Calibri", (short) 220, IndexedColors.BLACK.getIndex())); |
| } |
| |
| @Test |
| void testConstructor() { |
| XSSFFont xssfFont=new XSSFFont(); |
| assertNotNull(xssfFont.getCTFont()); |
| } |
| |
| @Test |
| void testBold() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTBooleanProperty bool=ctFont.addNewB(); |
| bool.setVal(false); |
| ctFont.setBArray(0,bool); |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertFalse(xssfFont.getBold()); |
| |
| |
| xssfFont.setBold(true); |
| assertEquals(1,ctFont.sizeOfBArray()); |
| assertTrue(ctFont.getBArray(0).getVal()); |
| } |
| |
| @SuppressWarnings("deprecation") |
| @Test |
| void testCharSetWithDeprecatedFontCharset() throws IOException { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTIntProperty prop=ctFont.addNewCharset(); |
| prop.setVal(ANSI.getValue()); |
| |
| ctFont.setCharsetArray(0,prop); |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(Font.ANSI_CHARSET,xssfFont.getCharSet()); |
| |
| xssfFont.setCharSet(DEFAULT); |
| assertEquals(DEFAULT.getValue(),ctFont.getCharsetArray(0).getVal()); |
| |
| // Try with a few less usual ones: |
| // Set with the Charset itself |
| xssfFont.setCharSet(RUSSIAN); |
| assertEquals(RUSSIAN.getValue(), xssfFont.getCharSet()); |
| // And set with the Charset index |
| xssfFont.setCharSet(ARABIC.getValue()); |
| assertEquals(ARABIC.getValue(), xssfFont.getCharSet()); |
| xssfFont.setCharSet((byte)(ARABIC.getValue())); |
| assertEquals(ARABIC.getValue(), xssfFont.getCharSet()); |
| |
| // This one isn't allowed |
| assertNull(valueOf(9999)); |
| assertThrows(POIXMLException.class, () -> xssfFont.setCharSet(9999), |
| "Shouldn't be able to set an invalid charset"); |
| |
| // Now try with a few sample files |
| |
| // Normal charset |
| try (XSSFWorkbook wb1 = XSSFTestDataSamples.openSampleWorkbook("Formatting.xlsx")) { |
| assertEquals(0, |
| wb1.getSheetAt(0).getRow(0).getCell(0).getCellStyle().getFont().getCharSet() |
| ); |
| } |
| |
| // GB2312 charset |
| try (XSSFWorkbook wb2 = XSSFTestDataSamples.openSampleWorkbook("49273.xlsx")) { |
| assertEquals(134, |
| wb2.getSheetAt(0).getRow(0).getCell(0).getCellStyle().getFont().getCharSet() |
| ); |
| } |
| } |
| |
| @Test |
| void testCharSet() throws IOException { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTIntProperty prop=ctFont.addNewCharset(); |
| prop.setVal(FontCharset.ANSI.getNativeId()); |
| |
| ctFont.setCharsetArray(0,prop); |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(Font.ANSI_CHARSET,xssfFont.getCharSet()); |
| |
| xssfFont.setCharSet(FontCharset.DEFAULT); |
| assertEquals(FontCharset.DEFAULT.getNativeId(),ctFont.getCharsetArray(0).getVal()); |
| |
| // Try with a few less usual ones: |
| // Set with the Charset itself |
| xssfFont.setCharSet(FontCharset.RUSSIAN); |
| assertEquals(FontCharset.RUSSIAN.getNativeId(), xssfFont.getCharSet()); |
| // And set with the Charset index |
| xssfFont.setCharSet(FontCharset.ARABIC.getNativeId()); |
| assertEquals(FontCharset.ARABIC.getNativeId(), xssfFont.getCharSet()); |
| xssfFont.setCharSet((byte)(FontCharset.ARABIC.getNativeId())); |
| assertEquals(FontCharset.ARABIC.getNativeId(), xssfFont.getCharSet()); |
| |
| // This one isn't allowed |
| assertNull(FontCharset.valueOf(9999)); |
| assertThrows(POIXMLException.class, () -> xssfFont.setCharSet(9999), "Shouldn't be able to set an invalid charset"); |
| |
| // Now try with a few sample files |
| |
| // Normal charset |
| try (XSSFWorkbook wb1 = XSSFTestDataSamples.openSampleWorkbook("Formatting.xlsx")) { |
| assertEquals(0, |
| wb1.getSheetAt(0).getRow(0).getCell(0).getCellStyle().getFont().getCharSet() |
| ); |
| } |
| |
| // GB2312 charset |
| try (XSSFWorkbook wb2 = XSSFTestDataSamples.openSampleWorkbook("49273.xlsx")) { |
| assertEquals(134, |
| wb2.getSheetAt(0).getRow(0).getCell(0).getCellStyle().getFont().getCharSet() |
| ); |
| } |
| } |
| |
| @Test |
| void testFontName() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTFontName fname=ctFont.addNewName(); |
| fname.setVal("Arial"); |
| ctFont.setNameArray(0,fname); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals("Arial", xssfFont.getFontName()); |
| |
| xssfFont.setFontName("Courier"); |
| assertEquals("Courier",ctFont.getNameArray(0).getVal()); |
| } |
| |
| @Test |
| void testItalic() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTBooleanProperty bool=ctFont.addNewI(); |
| bool.setVal(false); |
| ctFont.setIArray(0,bool); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertFalse(xssfFont.getItalic()); |
| |
| xssfFont.setItalic(true); |
| assertEquals(1,ctFont.sizeOfIArray()); |
| assertTrue(ctFont.getIArray(0).getVal()); |
| assertTrue(ctFont.getIArray(0).getVal()); |
| } |
| |
| @Test |
| void testStrikeout() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTBooleanProperty bool=ctFont.addNewStrike(); |
| bool.setVal(false); |
| ctFont.setStrikeArray(0,bool); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertFalse(xssfFont.getStrikeout()); |
| |
| xssfFont.setStrikeout(true); |
| assertEquals(1,ctFont.sizeOfStrikeArray()); |
| assertTrue(ctFont.getStrikeArray(0).getVal()); |
| assertTrue(ctFont.getStrikeArray(0).getVal()); |
| } |
| |
| @Test |
| void testFontHeight() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTFontSize size=ctFont.addNewSz(); |
| size.setVal(11); |
| ctFont.setSzArray(0,size); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(11,xssfFont.getFontHeightInPoints()); |
| |
| xssfFont.setFontHeight(20); |
| assertEquals(20.0, ctFont.getSzArray(0).getVal(), 0.0); |
| } |
| |
| @Test |
| void testFontHeightInPoint() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTFontSize size=ctFont.addNewSz(); |
| size.setVal(14); |
| ctFont.setSzArray(0,size); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(14,xssfFont.getFontHeightInPoints()); |
| |
| xssfFont.setFontHeightInPoints((short)20); |
| assertEquals(20.0, ctFont.getSzArray(0).getVal(), 0.0); |
| } |
| |
| @Test |
| void testUnderline() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTUnderlineProperty underlinePropr=ctFont.addNewU(); |
| underlinePropr.setVal(STUnderlineValues.SINGLE); |
| ctFont.setUArray(0,underlinePropr); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(Font.U_SINGLE, xssfFont.getUnderline()); |
| |
| xssfFont.setUnderline(Font.U_DOUBLE); |
| assertEquals(1, ctFont.sizeOfUArray()); |
| assertSame(STUnderlineValues.DOUBLE,ctFont.getUArray(0).getVal()); |
| |
| xssfFont.setUnderline(FontUnderline.DOUBLE_ACCOUNTING); |
| assertEquals(1, ctFont.sizeOfUArray()); |
| assertSame(STUnderlineValues.DOUBLE_ACCOUNTING,ctFont.getUArray(0).getVal()); |
| } |
| |
| @Test |
| void testColor() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTColor color=ctFont.addNewColor(); |
| color.setIndexed(XSSFFont.DEFAULT_FONT_COLOR); |
| ctFont.setColorArray(0,color); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(IndexedColors.BLACK.getIndex(),xssfFont.getColor()); |
| |
| xssfFont.setColor(IndexedColors.RED.getIndex()); |
| assertEquals(IndexedColors.RED.getIndex(), ctFont.getColorArray(0).getIndexed()); |
| } |
| |
| @Test |
| void testRgbColor() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTColor color=ctFont.addNewColor(); |
| |
| color.setRgb(Integer.toHexString(0xFFFFFF).getBytes(LocaleUtil.CHARSET_1252)); |
| ctFont.setColorArray(0,color); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(ctFont.getColorArray(0).getRgb()[0],xssfFont.getXSSFColor().getRGB()[0]); |
| assertEquals(ctFont.getColorArray(0).getRgb()[1],xssfFont.getXSSFColor().getRGB()[1]); |
| assertEquals(ctFont.getColorArray(0).getRgb()[2],xssfFont.getXSSFColor().getRGB()[2]); |
| assertEquals(ctFont.getColorArray(0).getRgb()[3],xssfFont.getXSSFColor().getRGB()[3]); |
| |
| xssfFont.setColor((short)23); |
| |
| byte[] bytes = Integer.toHexString(0xF1F1F1).getBytes(LocaleUtil.CHARSET_1252); |
| color.setRgb(bytes); |
| XSSFColor newColor = XSSFColor.from(color); |
| xssfFont.setColor(newColor); |
| assertEquals(ctFont.getColorArray(0).getRgb()[2],newColor.getRGB()[2]); |
| |
| assertArrayEquals(bytes, xssfFont.getXSSFColor().getRGB()); |
| assertEquals(0, xssfFont.getColor()); |
| } |
| |
| @Test |
| void testThemeColor() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTColor color=ctFont.addNewColor(); |
| color.setTheme(1); |
| ctFont.setColorArray(0,color); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(ctFont.getColorArray(0).getTheme(),xssfFont.getThemeColor()); |
| |
| xssfFont.setThemeColor(IndexedColors.RED.getIndex()); |
| assertEquals(IndexedColors.RED.getIndex(),ctFont.getColorArray(0).getTheme()); |
| } |
| |
| @Test |
| void testFamily() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTFontFamily family=ctFont.addNewFamily(); |
| family.setVal(FontFamily.MODERN.getValue()); |
| ctFont.setFamilyArray(0,family); |
| |
| XSSFFont xssfFont=new XSSFFont(ctFont); |
| assertEquals(FontFamily.MODERN.getValue(),xssfFont.getFamily()); |
| } |
| |
| @Test |
| void testScheme() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTFontScheme scheme=ctFont.addNewScheme(); |
| scheme.setVal(STFontScheme.MAJOR); |
| ctFont.setSchemeArray(0,scheme); |
| |
| XSSFFont font=new XSSFFont(ctFont); |
| assertEquals(FontScheme.MAJOR,font.getScheme()); |
| |
| font.setScheme(FontScheme.NONE); |
| assertSame(STFontScheme.NONE,ctFont.getSchemeArray(0).getVal()); |
| } |
| |
| @Test |
| void testTypeOffset() { |
| CTFont ctFont=CTFont.Factory.newInstance(); |
| CTVerticalAlignFontProperty valign=ctFont.addNewVertAlign(); |
| valign.setVal(STVerticalAlignRun.BASELINE); |
| ctFont.setVertAlignArray(0,valign); |
| |
| XSSFFont font=new XSSFFont(ctFont); |
| assertEquals(Font.SS_NONE,font.getTypeOffset()); |
| |
| font.setTypeOffset(XSSFFont.SS_SUPER); |
| assertSame(STVerticalAlignRun.SUPERSCRIPT,ctFont.getVertAlignArray(0).getVal()); |
| } |
| |
| // store test from TestSheetUtil here as it uses XSSF |
| @Test |
| void testCanComputeWidthXSSF() throws IOException { |
| try (Workbook wb = new XSSFWorkbook()) { |
| // cannot check on result because on some machines we get back false here! |
| assertDoesNotThrow(() -> SheetUtil.canComputeColumnWidth(wb.getFontAt(0))); |
| } |
| } |
| |
| // store test from TestSheetUtil here as it uses XSSF |
| @Test |
| void testCanComputeWidthInvalidFont() { |
| Font font = new XSSFFont(CTFont.Factory.newInstance()); |
| font.setFontName("some non existing font name"); |
| |
| // Even with invalid fonts we still get back useful data most of the time... |
| assertDoesNotThrow(() -> SheetUtil.canComputeColumnWidth(font)); |
| } |
| |
| /** |
| * Test that fonts get added properly |
| */ |
| @Test |
| void testFindFont() throws IOException { |
| try (XSSFWorkbook wb = new XSSFWorkbook()) { |
| assertEquals(1, wb.getNumberOfFonts()); |
| |
| XSSFSheet s = wb.createSheet(); |
| s.createRow(0); |
| s.createRow(1); |
| s.getRow(0).createCell(0); |
| s.getRow(1).createCell(0); |
| |
| assertEquals(1, wb.getNumberOfFonts()); |
| |
| XSSFFont f1 = wb.getFontAt(0); |
| assertFalse(f1.getBold()); |
| |
| // Check that asking for the same font |
| // multiple times gives you the same thing. |
| // Otherwise, our tests wouldn't work! |
| assertSame(wb.getFontAt(0), wb.getFontAt(0)); |
| assertEquals( |
| wb.getFontAt(0), |
| wb.getFontAt(0) |
| ); |
| |
| // Look for a new font we have |
| // yet to add |
| assertNull( |
| wb.findFont( |
| false, IndexedColors.INDIGO.getIndex(), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| assertNull( |
| wb.getStylesSource().findFont( |
| false, new XSSFColor(IndexedColors.INDIGO, new DefaultIndexedColorMap()), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| |
| XSSFFont nf = wb.createFont(); |
| assertEquals(2, wb.getNumberOfFonts()); |
| |
| assertEquals(1, nf.getIndex()); |
| assertEquals(nf, wb.getFontAt(1)); |
| |
| nf.setBold(false); |
| nf.setColor(IndexedColors.INDIGO.getIndex()); |
| nf.setFontHeight((short) 22); |
| nf.setFontName("Thingy"); |
| nf.setItalic(false); |
| nf.setStrikeout(true); |
| nf.setTypeOffset((short) 2); |
| nf.setUnderline((byte) 2); |
| |
| assertEquals(2, wb.getNumberOfFonts()); |
| assertEquals(nf, wb.getFontAt(1)); |
| |
| assertNotSame(wb.getFontAt(0), wb.getFontAt(1)); |
| |
| // Find it now |
| assertNotNull( |
| wb.findFont( |
| false, IndexedColors.INDIGO.getIndex(), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| assertNotNull( |
| wb.getStylesSource().findFont( |
| false, new XSSFColor(IndexedColors.INDIGO, new DefaultIndexedColorMap()), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| |
| XSSFFont font = wb.findFont( |
| false, IndexedColors.INDIGO.getIndex(), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ); |
| assertNotNull(font); |
| assertEquals( |
| 1, |
| font.getIndex() |
| ); |
| assertEquals(nf, |
| wb.findFont( |
| false, IndexedColors.INDIGO.getIndex(), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| assertEquals(nf, |
| wb.getStylesSource().findFont( |
| false, new XSSFColor(IndexedColors.INDIGO, new DefaultIndexedColorMap()), (short) 22, |
| "Thingy", false, true, (short) 2, (byte) 2 |
| ) |
| ); |
| |
| } |
| } |
| |
| @Test |
| void testEquals() { |
| XSSFFont font = new XSSFFont(); |
| XSSFFont equ = new XSSFFont(); |
| XSSFFont notequ = new XSSFFont(); |
| notequ.setItalic(true); |
| |
| assertEquals(equ, font); |
| assertNotEquals(font, notequ); |
| |
| notequ.setItalic(false); |
| notequ.setThemeColor((short)123); |
| assertNotEquals(font, notequ); |
| } |
| } |