| /* ==================================================================== |
| 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.hwmf.record; |
| |
| import java.awt.BasicStroke; |
| import java.util.Map; |
| import java.util.function.Supplier; |
| |
| import org.apache.poi.common.Duplicatable; |
| import org.apache.poi.common.usermodel.GenericRecord; |
| import org.apache.poi.util.BitField; |
| import org.apache.poi.util.BitFieldFactory; |
| import org.apache.poi.util.GenericRecordJsonWriter; |
| import org.apache.poi.util.GenericRecordUtil; |
| |
| /** |
| * The 16-bit PenStyle Enumeration is used to specify different types of pens |
| * that can be used in graphics operations. |
| * |
| * Various styles can be combined by using a logical OR statement, one from |
| * each subsection of Style, EndCap, Join, and Type (Cosmetic). |
| * |
| * The defaults in case the other values of the subsection aren't set are |
| * solid, round end caps, round joins and cosmetic type. |
| */ |
| public class HwmfPenStyle implements Duplicatable, GenericRecord { |
| public enum HwmfLineCap { |
| /** Rounded ends */ |
| ROUND(0, BasicStroke.CAP_ROUND), |
| /** Square protrudes by half line width */ |
| SQUARE(1, BasicStroke.CAP_SQUARE), |
| /** Line ends at end point*/ |
| FLAT(2, BasicStroke.CAP_BUTT); |
| |
| public final int wmfFlag; |
| public final int awtFlag; |
| HwmfLineCap(int wmfFlag, int awtFlag) { |
| this.wmfFlag = wmfFlag; |
| this.awtFlag = awtFlag; |
| } |
| |
| static HwmfLineCap valueOf(int wmfFlag) { |
| for (HwmfLineCap hs : values()) { |
| if (hs.wmfFlag == wmfFlag) return hs; |
| } |
| return null; |
| } |
| } |
| |
| public enum HwmfLineJoin { |
| /**Line joins are round. */ |
| ROUND(0, BasicStroke.JOIN_ROUND), |
| /** Line joins are beveled. */ |
| BEVEL(1, BasicStroke.JOIN_BEVEL), |
| /** |
| * Line joins are mitered when they are within the current limit set by the |
| * SETMITERLIMIT META_ESCAPE record. A join is beveled when it would exceed the limit |
| */ |
| MITER(2, BasicStroke.JOIN_MITER); |
| |
| public final int wmfFlag; |
| public final int awtFlag; |
| HwmfLineJoin(int wmfFlag, int awtFlag) { |
| this.wmfFlag = wmfFlag; |
| this.awtFlag = awtFlag; |
| } |
| |
| static HwmfLineJoin valueOf(int wmfFlag) { |
| for (HwmfLineJoin hs : values()) { |
| if (hs.wmfFlag == wmfFlag) return hs; |
| } |
| return null; |
| } |
| } |
| |
| public enum HwmfLineDash { |
| /** |
| * The pen is solid. |
| */ |
| SOLID(0x0000, null), |
| /** |
| * The pen is dashed. (-----) |
| */ |
| DASH(0x0001, 10, 8), |
| /** |
| * The pen is dotted. (.....) |
| */ |
| DOT(0x0002, 2, 4), |
| /** |
| * The pen has alternating dashes and dots. (_._._._) |
| */ |
| DASHDOT(0x0003, 10, 8, 2, 8), |
| /** |
| * The pen has dashes and double dots. (_.._.._) |
| */ |
| DASHDOTDOT(0x0004, 10, 4, 2, 4, 2, 4), |
| /** |
| * The pen is invisible. |
| */ |
| NULL(0x0005, null), |
| /** |
| * The pen is solid. When this pen is used in any drawing record that takes a |
| * bounding rectangle, the dimensions of the figure are shrunk so that it fits |
| * entirely in the bounding rectangle, taking into account the width of the pen. |
| */ |
| INSIDEFRAME(0x0006, null), |
| /** |
| * The pen uses a styling array supplied by the user. |
| * (this is currently not supported and drawn as solid ... no idea where the user |
| * styling is supposed to come from ...) |
| */ |
| USERSTYLE(0x0007, null); |
| |
| |
| public final int wmfFlag; |
| public final float[] dashes; |
| |
| HwmfLineDash(int wmfFlag, float... dashes) { |
| this.wmfFlag = wmfFlag; |
| this.dashes = dashes; |
| } |
| |
| static HwmfLineDash valueOf(int wmfFlag) { |
| for (HwmfLineDash hs : values()) { |
| if (hs.wmfFlag == wmfFlag) return hs; |
| } |
| return null; |
| } |
| } |
| |
| protected static final BitField SUBSECTION_DASH = BitFieldFactory.getInstance(0x00007); |
| protected static final BitField SUBSECTION_ALTERNATE = BitFieldFactory.getInstance(0x00008); |
| protected static final BitField SUBSECTION_ENDCAP = BitFieldFactory.getInstance(0x00300); |
| protected static final BitField SUBSECTION_JOIN = BitFieldFactory.getInstance(0x03000); |
| protected static final BitField SUBSECTION_GEOMETRIC = BitFieldFactory.getInstance(0x10000); |
| |
| protected int flag; |
| |
| public HwmfPenStyle(int flag) { |
| this.flag = flag; |
| } |
| |
| public HwmfPenStyle(HwmfPenStyle other) { |
| flag = other.flag; |
| } |
| |
| public static HwmfPenStyle valueOf(int flag) { |
| return new HwmfPenStyle(flag); |
| } |
| |
| public HwmfLineCap getLineCap() { |
| return HwmfLineCap.valueOf(SUBSECTION_ENDCAP.getValue(flag)); |
| } |
| |
| public HwmfLineJoin getLineJoin() { |
| return HwmfLineJoin.valueOf(SUBSECTION_JOIN.getValue(flag)); |
| } |
| |
| public HwmfLineDash getLineDash() { |
| return HwmfLineDash.valueOf(SUBSECTION_DASH.getValue(flag)); |
| } |
| |
| /** |
| * Convienence method which should be used instead of accessing {@link HwmfLineDash#dashes} |
| * directly, so an subclass can provide user-style dashes |
| * |
| * @return the dash pattern |
| */ |
| public float[] getLineDashes() { |
| return getLineDash().dashes; |
| } |
| |
| /** |
| * The pen sets every other pixel (this style is applicable only for cosmetic pens). |
| */ |
| public boolean isAlternateDash() { |
| return SUBSECTION_ALTERNATE.isSet(flag); |
| } |
| |
| /** |
| * A pen type that specifies a line with a width that is measured in logical units |
| * and a style that can contain any of the attributes of a brush. |
| */ |
| public boolean isGeometric() { |
| return SUBSECTION_GEOMETRIC.isSet(flag); |
| } |
| |
| |
| @Override |
| public HwmfPenStyle copy() { |
| return new HwmfPenStyle(this); |
| } |
| |
| @Override |
| public String toString() { |
| return GenericRecordJsonWriter.marshal(this); |
| } |
| |
| @Override |
| public Map<String, Supplier<?>> getGenericProperties() { |
| return GenericRecordUtil.getGenericProperties( |
| "lineCap", this::getLineCap, |
| "lineJoin", this::getLineJoin, |
| "lineDash", this::getLineDash, |
| "lineDashes", this::getLineDashes, |
| "alternateDash", this::isAlternateDash, |
| "geometric", this::isGeometric |
| ); |
| } |
| } |