1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* $Id: AFPBorderPainter.java 1802793 2017-07-24 11:49:40Z ssteiner $ */ 19 20 package org.apache.fop.afp; 21 22 import java.awt.geom.AffineTransform; 23 24 import org.apache.fop.fo.Constants; 25 import org.apache.fop.render.intermediate.BorderPainter; 26 import org.apache.fop.util.ColorUtil; 27 28 /** 29 * Handles the drawing of borders/lines in AFP 30 */ 31 public class AFPBorderPainter extends AbstractAFPPainter { 32 33 /** 34 * Main constructor 35 * 36 * @param paintingState the AFP painting state converter 37 * @param dataStream the AFP datastream 38 */ AFPBorderPainter(AFPPaintingState paintingState, DataStream dataStream)39 public AFPBorderPainter(AFPPaintingState paintingState, DataStream dataStream) { 40 super(paintingState, dataStream); 41 } 42 43 /** {@inheritDoc} */ paint(PaintingInfo paintInfo)44 public void paint(PaintingInfo paintInfo) { 45 Integer bytesAvailable = dataStream.getCurrentPage().getPresentationTextObject().getBytesAvailable(); 46 if (bytesAvailable != null && bytesAvailable < 1024) { 47 dataStream.getCurrentPage().endPresentationObject(); 48 } 49 50 BorderPaintingInfo borderPaintInfo = (BorderPaintingInfo)paintInfo; 51 float w = borderPaintInfo.getX2() - borderPaintInfo.getX1(); 52 float h = borderPaintInfo.getY2() - borderPaintInfo.getY1(); 53 if ((w < 0) || (h < 0)) { 54 log.error("Negative extent received. Border won't be painted."); 55 return; 56 } 57 58 int pageWidth = dataStream.getCurrentPage().getWidth(); 59 int pageHeight = dataStream.getCurrentPage().getHeight(); 60 AFPUnitConverter unitConv = paintingState.getUnitConverter(); 61 AffineTransform at = paintingState.getData().getTransform(); 62 63 float x1 = unitConv.pt2units(borderPaintInfo.getX1()); 64 float y1 = unitConv.pt2units(borderPaintInfo.getY1()); 65 float x2 = unitConv.pt2units(borderPaintInfo.getX2()); 66 float y2 = unitConv.pt2units(borderPaintInfo.getY2()); 67 68 switch (paintingState.getRotation()) { 69 case 90: 70 x1 += at.getTranslateY(); 71 y1 += (float) (pageWidth - at.getTranslateX()); 72 x2 += at.getTranslateY(); 73 y2 += (float) (pageWidth - at.getTranslateX()); 74 break; 75 case 180: 76 x1 += (float) (pageWidth - at.getTranslateX()); 77 y1 += (float) (pageHeight - at.getTranslateY()); 78 x2 += (float) (pageWidth - at.getTranslateX()); 79 y2 += (float) (pageHeight - at.getTranslateY()); 80 break; 81 case 270: 82 x1 = (float) (pageHeight - at.getTranslateY()); 83 y1 += (float) at.getTranslateX(); 84 x2 += x1; 85 y2 += (float) at.getTranslateX(); 86 break; 87 case 0: 88 default: 89 x1 += at.getTranslateX(); 90 y1 += at.getTranslateY(); 91 x2 += at.getTranslateX(); 92 y2 += at.getTranslateY(); 93 break; 94 } 95 96 AFPLineDataInfo lineDataInfo = new AFPLineDataInfo(); 97 lineDataInfo.setColor(borderPaintInfo.getColor()); 98 lineDataInfo.setRotation(paintingState.getRotation()); 99 lineDataInfo.setX1(Math.round(x1)); 100 lineDataInfo.setY1(Math.round(y1)); 101 float thickness; 102 if (borderPaintInfo.isHorizontal()) { 103 thickness = y2 - y1; 104 } else { 105 thickness = x2 - x1; 106 } 107 lineDataInfo.setThickness(Math.round(thickness)); 108 109 // handle border-*-style 110 switch (borderPaintInfo.getStyle()) { 111 case Constants.EN_DOUBLE: 112 int thickness3 = (int)Math.floor(thickness / 3f); 113 lineDataInfo.setThickness(thickness3); 114 if (borderPaintInfo.isHorizontal()) { 115 lineDataInfo.setX2(Math.round(x2)); 116 lineDataInfo.setY2(lineDataInfo.getY1()); 117 dataStream.createLine(lineDataInfo); 118 int distance = thickness3 * 2; 119 lineDataInfo = new AFPLineDataInfo(lineDataInfo); 120 lineDataInfo.setY1(lineDataInfo.getY1() + distance); 121 lineDataInfo.setY2(lineDataInfo.getY2() + distance); 122 dataStream.createLine(lineDataInfo); 123 } else { 124 lineDataInfo.setX2(lineDataInfo.getX1()); 125 lineDataInfo.setY2(Math.round(y2)); 126 dataStream.createLine(lineDataInfo); 127 int distance = thickness3 * 2; 128 lineDataInfo = new AFPLineDataInfo(lineDataInfo); 129 lineDataInfo.setX1(lineDataInfo.getX1() + distance); 130 lineDataInfo.setX2(lineDataInfo.getX2() + distance); 131 dataStream.createLine(lineDataInfo); 132 } 133 break; 134 case Constants.EN_DASHED: 135 if (borderPaintInfo.isHorizontal()) { 136 int dashWidth = (int) unitConv.pt2units(BorderPainter.dashWidthCalculator(w, h)); 137 lineDataInfo.setX2(lineDataInfo.getX1() + dashWidth); 138 lineDataInfo.setY2(lineDataInfo.getY1()); 139 int ex2 = Math.round(x2); 140 int spaceWidth = (int) (BorderPainter.DASHED_BORDER_SPACE_RATIO * dashWidth); 141 while (lineDataInfo.getX2() <= ex2 && dashWidth > 0) { 142 dataStream.createLine(lineDataInfo); 143 lineDataInfo.setX1(lineDataInfo.getX2() + spaceWidth); 144 lineDataInfo.setX2(lineDataInfo.getX1() + dashWidth); 145 } 146 } else { 147 int dashWidth = (int) unitConv.pt2units(BorderPainter.dashWidthCalculator(h, w)); 148 lineDataInfo.setX2(lineDataInfo.getX1()); 149 lineDataInfo.setY2(lineDataInfo.getY1() + dashWidth); 150 int ey2 = Math.round(y2); 151 int spaceWidth = (int) (BorderPainter.DASHED_BORDER_SPACE_RATIO * dashWidth); 152 while (lineDataInfo.getY2() <= ey2 && dashWidth > 0) { 153 dataStream.createLine(lineDataInfo); 154 lineDataInfo.setY1(lineDataInfo.getY2() + spaceWidth); 155 lineDataInfo.setY2(lineDataInfo.getY1() + dashWidth); 156 } 157 } 158 break; 159 case Constants.EN_DOTTED: 160 if (borderPaintInfo.isHorizontal()) { 161 lineDataInfo.setX2(lineDataInfo.getX1() + lineDataInfo.getThickness()); 162 lineDataInfo.setY2(lineDataInfo.getY1()); 163 int ex2 = Math.round(x2); 164 while (lineDataInfo.getX1() + lineDataInfo.getThickness() < ex2) { 165 dataStream.createLine(lineDataInfo); 166 lineDataInfo.setX1(lineDataInfo.getX1() + 3 * lineDataInfo.getThickness()); 167 lineDataInfo.setX2(lineDataInfo.getX1() + lineDataInfo.getThickness()); 168 } 169 } else { 170 lineDataInfo.setX2(lineDataInfo.getX1()); 171 lineDataInfo.setY2(lineDataInfo.getY1() + lineDataInfo.getThickness()); 172 int ey2 = Math.round(y2); 173 while (lineDataInfo.getY1() + lineDataInfo.getThickness() < ey2) { 174 dataStream.createLine(lineDataInfo); 175 lineDataInfo.setY1(lineDataInfo.getY1() + 3 * lineDataInfo.getThickness()); 176 lineDataInfo.setY2(lineDataInfo.getY1() + lineDataInfo.getThickness()); 177 } 178 } 179 break; 180 case Constants.EN_GROOVE: 181 case Constants.EN_RIDGE: 182 //TODO 183 int yNew; 184 lineDataInfo.setX2(Math.round(x2)); 185 float colFactor = (borderPaintInfo.getStyle() == Constants.EN_GROOVE ? 0.4f : -0.4f); 186 float h3 = (y2 - y1) / 3; 187 lineDataInfo.setColor( 188 ColorUtil.lightenColor(borderPaintInfo.getColor(), -colFactor)); 189 lineDataInfo.setThickness(Math.round(h3)); 190 yNew = Math.round(y1); 191 lineDataInfo.setY1(yNew); 192 lineDataInfo.setY2(yNew); 193 dataStream.createLine(lineDataInfo); 194 lineDataInfo.setColor(borderPaintInfo.getColor()); 195 yNew = Math.round(y1 + h3); 196 lineDataInfo.setY1(yNew); 197 lineDataInfo.setY2(yNew); 198 dataStream.createLine(lineDataInfo); 199 lineDataInfo.setColor(ColorUtil.lightenColor(borderPaintInfo.getColor(), colFactor)); 200 yNew = Math.round(y1 + h3 + h3); 201 lineDataInfo.setY1(yNew); 202 lineDataInfo.setY2(yNew); 203 dataStream.createLine(lineDataInfo); 204 break; 205 case Constants.EN_HIDDEN: 206 break; 207 case Constants.EN_INSET: 208 case Constants.EN_OUTSET: 209 case Constants.EN_SOLID: 210 default: 211 if (borderPaintInfo.isHorizontal()) { 212 lineDataInfo.setX2(Math.round(x2)); 213 lineDataInfo.setY2(lineDataInfo.getY1()); 214 } else { 215 lineDataInfo.setX2(lineDataInfo.getX1()); 216 lineDataInfo.setY2(Math.round(y2)); 217 } 218 dataStream.createLine(lineDataInfo); 219 } 220 } 221 222 } 223