Java 使用lineTo和curveTo的apache pdfBox问题

Java 使用lineTo和curveTo的apache pdfBox问题,java,pdfbox,Java,Pdfbox,我正在使用Apache的PDFBox版本2.0.4,但在使用lineTo和curveTo时遇到问题。我的函数获取弧度、起始度和结束度的参数,然后使用lineTo和curveTo生成饼图的切片 mContents.setNonStrokingColor(color); mContents.moveTo(0, 0); List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(en

我正在使用Apache的PDFBox版本2.0.4,但在使用lineTo和curveTo时遇到问题。我的函数获取弧度、起始度和结束度的参数,然后使用lineTo和curveTo生成饼图的切片

mContents.setNonStrokingColor(color);
mContents.moveTo(0, 0);
List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));
mContents.lineTo(smallArc.get(0), smallArc.get(1));
mContents.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));
mContents.closePath();
mContents.fill();
当pi图表包含在生成的pdf中时,页脚和图像不在pdf中。截短代码以生成饼图,页脚将显示包含的图像

当前必须在生成页面后添加指定特定坐标的饼图,否则饼图下面的其他行不会显示

curveTo和lineTo生成的输出是否会大于导致这些问题的显示值

编辑-在绘制图形之前在页脚中添加图像,并且图像、图形和文本都会出现

感谢你的指点

完整代码:

import com.google.code.geocoder.Geocoder;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;
import org.apache.tomcat.jni.Address;
import org.slf4j.Logger;

import java.awt.*;
import java.io.IOException; 
import java.text.DecimalFormat; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.List; 
import java.util.Locale;

/**  * Created by tim on 7/6/2017.  */
public class ReportDataPDFBox {
    private PDDocument mDoc = null;
    private PDPage mPage = null;
    private PDImageXObject pdImage = null;
    private PDFont mHeaderFont = PDType1Font.HELVETICA_BOLD;

    private final int FONT_SIZE_HDR1 = 16;
    private final int FONT_SIZE_HDR2 = 14;
    private final int FONT_SIZE_REG = 12;
    private final int HDR_INDENT = 30;
    private final int BODY_INDENT_1 = 55;
    private final int BODY_INDENT_2 = 65;
    private final int BODY_INDENT_3 = 75;

    private PDFont mRegFont = PDType1Font.HELVETICA;
    PDPageContentStream mContents = null;

    private String mReportName = null;
    private String mFullImagePath = null;
    private String mMonth = null;
    private boolean mReportDone = true;
    private int mHorizonVal = 700;
    private int mHorizonGrph = 0;
    private long[] mDayPercent;

    private Calendar mCurrentCalendar = null;
    ProcessFrequencyData pfd = null;
    ProcessWeatherData pwd = null;
    ProcessPerformanceData ppd = null;
    Logger log = null;
    Color[] mColor = {Color.PINK,Color.YELLOW,Color.CYAN, Color.BLUE,Color.RED,Color.GREEN,Color.ORANGE,Color.LIGHT_GRAY};

    public ReportDataPDFBox(Logger logger, ProcessFrequencyData pfd, ProcessWeatherData pwd, ProcessPerformanceData ppd){
        this.log = logger;
        this.pfd = pfd;
        this.pwd = pwd;
        this.ppd = ppd;
        initializeDoc();
    }

    public void initializeDoc(){
        mDoc = new PDDocument();
        mPage = new PDPage();
        mDoc.addPage(mPage);
        mFullImagePath = "logo.png";
        mCurrentCalendar = Calendar.getInstance();
        mMonth = mCurrentCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
        mReportName = mMonth + ".pdf";
        try{
            mContents = new PDPageContentStream(mDoc, mPage);
        }catch(IOException e){System.out.println("Error setting content stream - "+e.getLocalizedMessage());}
    }

    public boolean writeTheReport(){
        addHeader();
        addFooter();

        generateReportContent();

//        addFooter();
        cleanUpALlDone();
        return mReportDone;
    }

    private void addHeader(){
        try {
            mContents.beginText();
            mContents.setFont(mHeaderFont,FONT_SIZE_HDR1);
            mContents.newLineAtOffset(200, 740);
            mContents.showText(mMonth + " - ActoTracker Report - " + mCurrentCalendar.get(Calendar.YEAR));
            mContents.endText();
        }catch (IOException io){System.out.println("Error with text content screen");}
    }

    private void generateReportContent(){
        addNumberRunInfo();
        addLocationRunInfo();
        addWeekDayInfo();
        addWeekInfo();
        addFrequencyData();
        pukeMeAChart();
           // generateDailyChart();
    }

    private void addNumberRunInfo(){
        int daysActive = Utility.getDaysBetweenDates(Utility.getOldestDate(pfd.getFirstDate(),
    pwd.getFirstDate()), Calendar.getInstance().getTimeInMillis());
        writeLine(mHeaderFont, FONT_SIZE_HDR2,HDR_INDENT, "Frequency Information");
        long percentActiveIdle = (pfd.getTotalDaysRun()*100/daysActive);
        String line = "Number of Runs - " + pfd.getTotalDaysRun() + "    Number of days ActoTracker active - " + daysActive + "   Percent run =
    "+percentActiveIdle;
        writeLine(mRegFont, FONT_SIZE_REG, BODY_INDENT_1, line);
    }

    private void addLocationRunInfo(){
        String line = "Number of locations run = " + pfd.getLocationRun();
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        for (int i=1; i<=pfd.getLocationRun();i++){
            String[] locationInfo = pfd.getLocationInfo(i);
            long percent = pfd.getRunsByLocation(i)*100/pfd.getTotalDaysRun();
            String line2= new String( locationInfo[0] + " - " + locationInfo[1] +" , "+locationInfo[2]+ "  Number of runs = " +
    pfd.getRunsByLocation(i) + "  Percent of runs = " +percent );
            writeLine(mRegFont, FONT_SIZE_REG,BODY_INDENT_2,line2);
        }
    }

    private void addWeekDayInfo(){
        int totDaysRunning = pfd.getTotalRunDay();
        int leastCnt = 0;
        int mostCnt = 0;
        mHorizonGrph = mHorizonVal - 90;
        mDayPercent = new long[8];
        String mostDay = " most common day";
        String leastDay = " least common day";
        DayFrequencyResults frequency = pfd.getDayDistribution();
        int[] leastDays = frequency.getLessDays();
        int[] mostDays = frequency.getMostDays();
        StringBuilder leastString = new StringBuilder();
        StringBuilder mostString = new StringBuilder();
        for (int i=0; i< leastDays.length;i++){
            if (leastDays[i] != 0) {
                leastString.append(Utility.getDayName(leastDays[i])).append(" ");
                leastCnt++;
            }
        }
        for (int j=0; j< mostDays.length;j++){
            if (mostDays[j] != 0) {
                mostString.append(Utility.getDayName(j+1)).append(" ");
                mostCnt++;
            }
        }
        if (leastCnt > 1){leastDay += "s";}
        if (mostCnt > 1) {mostDay +="s";}
        String line = mostString.toString()+mostDay+ " to run"+ "     "+leastString.toString()+leastDay+" to run";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        for (int i=1;i<8;i++){
            String day = new String(Utility.getDayName(i)+"  " + pfd.getRweekDayCount(i) + " runs "+" 
    "+pfd.getRweekDayCount(i)*100/totDaysRunning)+ "%";
            writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_2,day);
            double x = pfd.getRweekDayCount(i) / (double)pfd.getTotalDaysRun();
            mDayPercent[i] = Math.round(360*x);
        }
        System.out.println("BreakPoint");
    }

    private void addWeekInfo(){
        String line;
        Integer[] largestWeekTotals = {0,0,0,0,0,0,0};
        double largestDistance = 0D;
        double firstHalfDist = 0D;
        double secondHalfDist = 0D;
        DecimalFormat df = new DecimalFormat("####.##");

        int[] distFreq = pfd.getMonthlySummaryInfo();
        if (distFreq[0] > distFreq[1]){
            line = "Ran more in first half of months run.   "+ distFreq[0] + " times versus "+ distFreq[1]+" times";
        }else{
            line = "Ran more in second half of months run.   " + distFreq[1] + " times versus " + distFreq[0]+" times";
        }
        writeLine(mRegFont,FONT_SIZE_REG, BODY_INDENT_1, line);

        for (int i = 1; i<7;i++){
            if (i<4){
                firstHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
            }else{
                secondHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
            }
        }
        if (firstHalfDist > secondHalfDist){
            line = new String ("Ran further in the first half of the month " + df.format(firstHalfDist) + " miles versus " +
    df.format(secondHalfDist) + " miles");
        }else{
            line = new String ("Ran further in the second half of the month " + df.format(secondHalfDist) + " miles versus " +
    df.format(firstHalfDist)+ " miles");
        }
            writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1, line);
        }

        private void addFrequencyData(){

        int greatestFreq = 0;
        int leastDiff = 0;
        int greatestDiff = 0;
        int leastFreq = 0;
        for (int i=0; i<30; i++){
            int cnt = ppd.getRunsByFrequentcy(i);
            if (cnt > greatestFreq){
                greatestFreq = cnt;
                greatestDiff = i;
            }
            else{
                if (cnt > 0 && i>leastDiff){
                    leastDiff = i;
                    leastFreq = cnt;
                }
            }

            log.info("Frequency?? = " + cnt + " index = "+i);
        }
        String line = greatestDiff + " days is the most common frequency between runs "+greatestFreq+" times";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        String line2 = leastDiff + " days longest time between runs " + leastFreq + " times";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line2);
    }

    private void writeLine(PDFont font, int fontSize, int indent, String text){
        mHorizonVal -= 20;
        try {
            mContents.beginText();
            mContents.setFont(font, fontSize);
            mContents.newLineAtOffset(indent,mHorizonVal);
            mContents.showText(text);
            mContents.endText();
        }catch(IOException e){}
    }

    private void addFooter(){
        log.info("IN addFooter");
        mPage = new PDPage();
        mDoc.addPage(mPage);
        try {
            pdImage = PDImageXObject.createFromFile(mFullImagePath, mDoc);
        }catch(IOException ie){System.out.println("Error opening image file - "+ie.getMessage());}
        try {
            mContents.drawImage(pdImage,250,5,pdImage.getWidth()/2,pdImage.getHeight()/2);
        }catch(IOException e){log.error("Error adding image file - "+ e.getLocalizedMessage());}
    }

    private void cleanUpALlDone(){
        try {
            mContents.close();
            mDoc.save(mReportName);
            mDoc.close();
        }catch (IOException ie){System.out.println("Error closing PDF document - " + ie.getMessage());}
    }

    private void generateDailyChart(){
        int totalVal = 0;
        try {
            mContents.transform(Matrix.getTranslateInstance(375, 525));
        }catch(IOException e){}

        for (int i=1; i< 8;i++){
            totalVal += mDayPercent[i];
            writeTheChart(mDayPercent[i-1], totalVal,mColor[i]);
            log.info("Color selected = " +mColor[i] +"Index = "+i);
        }
    }

    private void writeTheChart(long beg, long end, Color color){
        try {
            log.info("Color received = " + color);
            drawSlice(color, 60,beg, end);
        }catch(IOException e){}
    }

    private void pukeMeAChart(){
        try {
            mContents.transform(Matrix.getTranslateInstance(375,525));
            drawSlice(Color.YELLOW, 60, 0, 69);
            mContents.fill();
            drawSlice(Color.BLUE, 60, 69, 117);
            drawSlice(Color.RED, 60, 117, 181);
            mContents.fill();
            drawSlice(Color.WHITE, 60, 181, 208);
            mContents.fill();
            drawSlice(Color.GREEN, 60, 208, 272);
            mContents.fill();
            drawSlice(Color.YELLOW, 60, 272, 336);
            drawSlice(Color.BLUE, 60, 336, 360);
            mContents.fill();
        } catch(IOException e ){}
    }

    private void drawSlice(Color color, float rad, float startDeg, float endDeg) throws IOException
    {
        mContents.setNonStrokingColor(color);
        mContents.moveTo(0, 0);
        List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));
        mContents.lineTo(smallArc.get(0), smallArc.get(1));
        mContents.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));
        mContents.closePath();
        mContents.fill();
    }

    private List<Float> createSmallArc(double r, double a1, double a2)
    {
        // Compute all four points for an arc that subtends the same total angle
        // but is centered on the X-axis
        double a = (a2 - a1) / 2;
        double x4 = r * Math.cos(a);
        double y4 = r * Math.sin(a);
        double x1 = x4;
        double y1 = -y4;
        double q1 = x1*x1 + y1*y1;

        double q2 = q1 + x1*x4 + y1*y4;
        double k2 = 4/3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
        double x2 = x1 - k2 * y1;
        double y2 = y1 + k2 * x1;
        double x3 = x2;
        double y3 = -y2;

        // Find the arc points' actual locations by computing x1,y1 and x4,y4
        // and rotating the control points by a + a1

        double ar = a + a1;
        double cos_ar = Math.cos(ar);
        double sin_ar = Math.sin(ar);

        List<Float> list = new ArrayList<Float>();
        list.add((float) (r * Math.cos(a1)));
        list.add((float) (r * Math.sin(a1)));
        list.add((float) (x2 * cos_ar - y2 * sin_ar));
        list.add((float) (x2 * sin_ar + y2 * cos_ar));
        list.add((float) (x3 * cos_ar - y3 * sin_ar));
        list.add((float) (x3 * sin_ar + y3 * cos_ar));
        list.add((float) (r * Math.cos(a2)));
        list.add((float) (r * Math.sin(a2)));
        return list;
    }
}
import com.google.code.geocoder.geocoder;
导入org.apache.pdfbox.pdmodel.PDDocument;
导入org.apache.pdfbox.pdmodel.PDPage;
导入org.apache.pdfbox.pdmodel.PDPageContentStream;
导入org.apache.pdfbox.pdmodel.font.PDFont;
导入org.apache.pdfbox.pdmodel.font.PDType1Font;
导入org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
导入org.apache.pdfbox.util.Matrix;
导入org.apache.tomcat.jni.Address;
导入org.slf4j.Logger;
导入java.awt.*;
导入java.io.IOException;
导入java.text.DecimalFormat;
导入java.util.ArrayList;
导入java.util.Calendar;
导入java.util.List;
导入java.util.Locale;
/***由tim于2017年7月6日创建*/
公共类ReportDataPDFBox{
私有PDDocument mDoc=null;
私有PDPage mPage=null;
私有PDImageXObject pdImage=null;
私有PDFont mHeaderFont=PDType1Font.HELVETICA_BOLD;
专用最终整数字体大小HDR1=16;
私有最终整数字体大小HDR2=14;
私人最终整数字体大小注册=12;
私人最终int HDR_缩进=30;
私有最终整数正文缩进1=55;
私有最终整数正文缩进2=65;
私有最终整数正文\u缩进\u 3=75;
私有PDFont mRegFont=PDType1Font.HELVETICA;
PDPageContentStream mContents=null;
私有字符串mReportName=null;
私有字符串mFullImagePath=null;
私有字符串mMonth=null;
私有布尔值mReportDone=true;
私有int mHorizonVal=700;
私有int mHorizonGrph=0;
私人长[]日百分比;
私有日历mCurrentCalendar=null;
ProcessFrequencyData pfd=null;
ProcessWeatherData pwd=null;
ProcessPerformanceData ppd=null;
记录器日志=空;
Color[]mColor={Color.粉红色,Color.黄色,Color.青色,Color.蓝色,Color.红色,Color.绿色,Color.橙色,Color.浅灰色};
公共报告数据PDFBox(记录器记录器、ProcessFrequencyData pfd、ProcessWeatherData pwd、ProcessPerformanceData ppd){
this.log=记录器;
this.pfd=pfd;
this.pwd=pwd;
this.ppd=ppd;
初始化为c();
}
public void initializeDoc(){
mDoc=新的PDDocument();
mPage=新的PDPage();
mDoc.addPage(mPage);
mfullmagepath=“logo.png”;
mCurrentCalendar=Calendar.getInstance();
mMonth=mccurrentcalendar.getDisplayName(Calendar.MONTH、Calendar.LONG、Locale.getDefault());
mReportName=mMonth+“.pdf”;
试一试{
mContents=新的PDPageContentStream(mDoc,mPage);
}catch(IOException e){System.out.println(“设置内容流时出错-”+e.getLocalizedMessage());}
}
公共布尔写以太网端口(){
addHeader();
addFooter();
generateReportContent();
//addFooter();
cleanUpALlDone();
返回mReportDone;
}
私有void addHeader(){
试一试{
mContents.beginText();
mContents.setFont(mHeaderFont,FONT\u SIZE\u HDR1);
mContents.newlineatofset(200740);
mContents.showText(mMonth+“-ActoTracker报告-”+mCurrentCalendar.get(Calendar.YEAR));
mContents.endText();
}catch(IOException io){System.out.println(“文本内容屏幕错误”);}
}
私有void generateReportContent(){
addNumberRunInfo();
addLocationRunInfo();
addWeekDayInfo();
addWeekInfo();
addFrequencyData();
pukeMeAChart();
//generateDailyChart();
}
私有void addNumberRunInfo(){
int daysActive=Utility.getdaysbetween日期(Utility.getOldestDate(pfd.getFirstDate()),
pwd.getFirstDate()),Calendar.getInstance().getTimeInMillis();
writeLine(mHeaderFont,字体大小HDR2,HDR缩进,“频率信息”);
长百分比活动空闲=(pfd.getTotalDaysRun()*100/天活动);
String line=“运行次数-”+pfd.getTotalDaysRun()+“ActTracker活动天数-“+DaysActivity+”运行百分比=
“+闲置百分比;
书写线(mRegFont、字体大小、正文缩进、行);
}
私有void addLocationRunInfo(){
String line=“运行的位置数=“+pfd.getLocationRun();
书写线(mRegFont、字体大小、正文缩进、行);
对于(inti=1;i1){leastDay+=“s”}
如果(mostCnt>1){mostDay+=“s”}
字符串行=mostString.toString()+mostDay+“运行”+“”+leastString.toString()+leastDay+“运行”;
书写线(mRegFont、字体大小、正文缩进、行);
对于(int i=1;i distFreq[1]){
line=“在运行的前半个月运行了更多。”+distFreq[0]+“次,而不是“+distFreq[1]+”次”;
}否则{
line=“在运行的下半个月运行了更多。”+distFreq[1]+“次,而“+distFreq[0]+”次;
}
书写线(mRegFont、字体大小、正文缩进、行);
对于(int i=1;i 0&&i>leastDiff){
leastDiff=i;
leastFreq=cnt;
}
}
log.info(“频率=”
import com.google.code.geocoder.Geocoder;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;
import org.apache.tomcat.jni.Address;
import org.slf4j.Logger;

import java.awt.*;
import java.io.IOException; 
import java.text.DecimalFormat; 
import java.util.ArrayList; 
import java.util.Calendar; 
import java.util.List; 
import java.util.Locale;

/**  * Created by tim on 7/6/2017.  */
public class ReportDataPDFBox {
    private PDDocument mDoc = null;
    private PDPage mPage = null;
    private PDImageXObject pdImage = null;
    private PDFont mHeaderFont = PDType1Font.HELVETICA_BOLD;

    private final int FONT_SIZE_HDR1 = 16;
    private final int FONT_SIZE_HDR2 = 14;
    private final int FONT_SIZE_REG = 12;
    private final int HDR_INDENT = 30;
    private final int BODY_INDENT_1 = 55;
    private final int BODY_INDENT_2 = 65;
    private final int BODY_INDENT_3 = 75;

    private PDFont mRegFont = PDType1Font.HELVETICA;
    PDPageContentStream mContents = null;

    private String mReportName = null;
    private String mFullImagePath = null;
    private String mMonth = null;
    private boolean mReportDone = true;
    private int mHorizonVal = 700;
    private int mHorizonGrph = 0;
    private long[] mDayPercent;

    private Calendar mCurrentCalendar = null;
    ProcessFrequencyData pfd = null;
    ProcessWeatherData pwd = null;
    ProcessPerformanceData ppd = null;
    Logger log = null;
    Color[] mColor = {Color.PINK,Color.YELLOW,Color.CYAN, Color.BLUE,Color.RED,Color.GREEN,Color.ORANGE,Color.LIGHT_GRAY};

    public ReportDataPDFBox(Logger logger, ProcessFrequencyData pfd, ProcessWeatherData pwd, ProcessPerformanceData ppd){
        this.log = logger;
        this.pfd = pfd;
        this.pwd = pwd;
        this.ppd = ppd;
        initializeDoc();
    }

    public void initializeDoc(){
        mDoc = new PDDocument();
        mPage = new PDPage();
        mDoc.addPage(mPage);
        mFullImagePath = "logo.png";
        mCurrentCalendar = Calendar.getInstance();
        mMonth = mCurrentCalendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
        mReportName = mMonth + ".pdf";
        try{
            mContents = new PDPageContentStream(mDoc, mPage);
        }catch(IOException e){System.out.println("Error setting content stream - "+e.getLocalizedMessage());}
    }

    public boolean writeTheReport(){
        addHeader();
        addFooter();

        generateReportContent();

//        addFooter();
        cleanUpALlDone();
        return mReportDone;
    }

    private void addHeader(){
        try {
            mContents.beginText();
            mContents.setFont(mHeaderFont,FONT_SIZE_HDR1);
            mContents.newLineAtOffset(200, 740);
            mContents.showText(mMonth + " - ActoTracker Report - " + mCurrentCalendar.get(Calendar.YEAR));
            mContents.endText();
        }catch (IOException io){System.out.println("Error with text content screen");}
    }

    private void generateReportContent(){
        addNumberRunInfo();
        addLocationRunInfo();
        addWeekDayInfo();
        addWeekInfo();
        addFrequencyData();
        pukeMeAChart();
           // generateDailyChart();
    }

    private void addNumberRunInfo(){
        int daysActive = Utility.getDaysBetweenDates(Utility.getOldestDate(pfd.getFirstDate(),
    pwd.getFirstDate()), Calendar.getInstance().getTimeInMillis());
        writeLine(mHeaderFont, FONT_SIZE_HDR2,HDR_INDENT, "Frequency Information");
        long percentActiveIdle = (pfd.getTotalDaysRun()*100/daysActive);
        String line = "Number of Runs - " + pfd.getTotalDaysRun() + "    Number of days ActoTracker active - " + daysActive + "   Percent run =
    "+percentActiveIdle;
        writeLine(mRegFont, FONT_SIZE_REG, BODY_INDENT_1, line);
    }

    private void addLocationRunInfo(){
        String line = "Number of locations run = " + pfd.getLocationRun();
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        for (int i=1; i<=pfd.getLocationRun();i++){
            String[] locationInfo = pfd.getLocationInfo(i);
            long percent = pfd.getRunsByLocation(i)*100/pfd.getTotalDaysRun();
            String line2= new String( locationInfo[0] + " - " + locationInfo[1] +" , "+locationInfo[2]+ "  Number of runs = " +
    pfd.getRunsByLocation(i) + "  Percent of runs = " +percent );
            writeLine(mRegFont, FONT_SIZE_REG,BODY_INDENT_2,line2);
        }
    }

    private void addWeekDayInfo(){
        int totDaysRunning = pfd.getTotalRunDay();
        int leastCnt = 0;
        int mostCnt = 0;
        mHorizonGrph = mHorizonVal - 90;
        mDayPercent = new long[8];
        String mostDay = " most common day";
        String leastDay = " least common day";
        DayFrequencyResults frequency = pfd.getDayDistribution();
        int[] leastDays = frequency.getLessDays();
        int[] mostDays = frequency.getMostDays();
        StringBuilder leastString = new StringBuilder();
        StringBuilder mostString = new StringBuilder();
        for (int i=0; i< leastDays.length;i++){
            if (leastDays[i] != 0) {
                leastString.append(Utility.getDayName(leastDays[i])).append(" ");
                leastCnt++;
            }
        }
        for (int j=0; j< mostDays.length;j++){
            if (mostDays[j] != 0) {
                mostString.append(Utility.getDayName(j+1)).append(" ");
                mostCnt++;
            }
        }
        if (leastCnt > 1){leastDay += "s";}
        if (mostCnt > 1) {mostDay +="s";}
        String line = mostString.toString()+mostDay+ " to run"+ "     "+leastString.toString()+leastDay+" to run";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        for (int i=1;i<8;i++){
            String day = new String(Utility.getDayName(i)+"  " + pfd.getRweekDayCount(i) + " runs "+" 
    "+pfd.getRweekDayCount(i)*100/totDaysRunning)+ "%";
            writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_2,day);
            double x = pfd.getRweekDayCount(i) / (double)pfd.getTotalDaysRun();
            mDayPercent[i] = Math.round(360*x);
        }
        System.out.println("BreakPoint");
    }

    private void addWeekInfo(){
        String line;
        Integer[] largestWeekTotals = {0,0,0,0,0,0,0};
        double largestDistance = 0D;
        double firstHalfDist = 0D;
        double secondHalfDist = 0D;
        DecimalFormat df = new DecimalFormat("####.##");

        int[] distFreq = pfd.getMonthlySummaryInfo();
        if (distFreq[0] > distFreq[1]){
            line = "Ran more in first half of months run.   "+ distFreq[0] + " times versus "+ distFreq[1]+" times";
        }else{
            line = "Ran more in second half of months run.   " + distFreq[1] + " times versus " + distFreq[0]+" times";
        }
        writeLine(mRegFont,FONT_SIZE_REG, BODY_INDENT_1, line);

        for (int i = 1; i<7;i++){
            if (i<4){
                firstHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
            }else{
                secondHalfDist += Utility.getMileage(pfd.fa.getWeekDistanceTotal(i),false);
            }
        }
        if (firstHalfDist > secondHalfDist){
            line = new String ("Ran further in the first half of the month " + df.format(firstHalfDist) + " miles versus " +
    df.format(secondHalfDist) + " miles");
        }else{
            line = new String ("Ran further in the second half of the month " + df.format(secondHalfDist) + " miles versus " +
    df.format(firstHalfDist)+ " miles");
        }
            writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1, line);
        }

        private void addFrequencyData(){

        int greatestFreq = 0;
        int leastDiff = 0;
        int greatestDiff = 0;
        int leastFreq = 0;
        for (int i=0; i<30; i++){
            int cnt = ppd.getRunsByFrequentcy(i);
            if (cnt > greatestFreq){
                greatestFreq = cnt;
                greatestDiff = i;
            }
            else{
                if (cnt > 0 && i>leastDiff){
                    leastDiff = i;
                    leastFreq = cnt;
                }
            }

            log.info("Frequency?? = " + cnt + " index = "+i);
        }
        String line = greatestDiff + " days is the most common frequency between runs "+greatestFreq+" times";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line);
        String line2 = leastDiff + " days longest time between runs " + leastFreq + " times";
        writeLine(mRegFont,FONT_SIZE_REG,BODY_INDENT_1,line2);
    }

    private void writeLine(PDFont font, int fontSize, int indent, String text){
        mHorizonVal -= 20;
        try {
            mContents.beginText();
            mContents.setFont(font, fontSize);
            mContents.newLineAtOffset(indent,mHorizonVal);
            mContents.showText(text);
            mContents.endText();
        }catch(IOException e){}
    }

    private void addFooter(){
        log.info("IN addFooter");
        mPage = new PDPage();
        mDoc.addPage(mPage);
        try {
            pdImage = PDImageXObject.createFromFile(mFullImagePath, mDoc);
        }catch(IOException ie){System.out.println("Error opening image file - "+ie.getMessage());}
        try {
            mContents.drawImage(pdImage,250,5,pdImage.getWidth()/2,pdImage.getHeight()/2);
        }catch(IOException e){log.error("Error adding image file - "+ e.getLocalizedMessage());}
    }

    private void cleanUpALlDone(){
        try {
            mContents.close();
            mDoc.save(mReportName);
            mDoc.close();
        }catch (IOException ie){System.out.println("Error closing PDF document - " + ie.getMessage());}
    }

    private void generateDailyChart(){
        int totalVal = 0;
        try {
            mContents.transform(Matrix.getTranslateInstance(375, 525));
        }catch(IOException e){}

        for (int i=1; i< 8;i++){
            totalVal += mDayPercent[i];
            writeTheChart(mDayPercent[i-1], totalVal,mColor[i]);
            log.info("Color selected = " +mColor[i] +"Index = "+i);
        }
    }

    private void writeTheChart(long beg, long end, Color color){
        try {
            log.info("Color received = " + color);
            drawSlice(color, 60,beg, end);
        }catch(IOException e){}
    }

    private void pukeMeAChart(){
        try {
            mContents.transform(Matrix.getTranslateInstance(375,525));
            drawSlice(Color.YELLOW, 60, 0, 69);
            mContents.fill();
            drawSlice(Color.BLUE, 60, 69, 117);
            drawSlice(Color.RED, 60, 117, 181);
            mContents.fill();
            drawSlice(Color.WHITE, 60, 181, 208);
            mContents.fill();
            drawSlice(Color.GREEN, 60, 208, 272);
            mContents.fill();
            drawSlice(Color.YELLOW, 60, 272, 336);
            drawSlice(Color.BLUE, 60, 336, 360);
            mContents.fill();
        } catch(IOException e ){}
    }

    private void drawSlice(Color color, float rad, float startDeg, float endDeg) throws IOException
    {
        mContents.setNonStrokingColor(color);
        mContents.moveTo(0, 0);
        List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));
        mContents.lineTo(smallArc.get(0), smallArc.get(1));
        mContents.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));
        mContents.closePath();
        mContents.fill();
    }

    private List<Float> createSmallArc(double r, double a1, double a2)
    {
        // Compute all four points for an arc that subtends the same total angle
        // but is centered on the X-axis
        double a = (a2 - a1) / 2;
        double x4 = r * Math.cos(a);
        double y4 = r * Math.sin(a);
        double x1 = x4;
        double y1 = -y4;
        double q1 = x1*x1 + y1*y1;

        double q2 = q1 + x1*x4 + y1*y4;
        double k2 = 4/3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);
        double x2 = x1 - k2 * y1;
        double y2 = y1 + k2 * x1;
        double x3 = x2;
        double y3 = -y2;

        // Find the arc points' actual locations by computing x1,y1 and x4,y4
        // and rotating the control points by a + a1

        double ar = a + a1;
        double cos_ar = Math.cos(ar);
        double sin_ar = Math.sin(ar);

        List<Float> list = new ArrayList<Float>();
        list.add((float) (r * Math.cos(a1)));
        list.add((float) (r * Math.sin(a1)));
        list.add((float) (x2 * cos_ar - y2 * sin_ar));
        list.add((float) (x2 * sin_ar + y2 * cos_ar));
        list.add((float) (x3 * cos_ar - y3 * sin_ar));
        list.add((float) (x3 * sin_ar + y3 * cos_ar));
        list.add((float) (r * Math.cos(a2)));
        list.add((float) (r * Math.sin(a2)));
        return list;
    }
}
private void pukeMeAChart(){
    try {
        mContents.transform(Matrix.getTranslateInstance(375,525));
        drawSlice(Color.YELLOW, 60, 0, 69);
        mContents.fill();
        drawSlice(Color.BLUE, 60, 69, 117);
        drawSlice(Color.RED, 60, 117, 181);
        mContents.fill();
        drawSlice(Color.WHITE, 60, 181, 208);
        mContents.fill();
        drawSlice(Color.GREEN, 60, 208, 272);
        mContents.fill();
        drawSlice(Color.YELLOW, 60, 272, 336);
        drawSlice(Color.BLUE, 60, 336, 360);
        mContents.fill();
    } catch(IOException e ){}
}
mContents.transform(Matrix.getTranslateInstance(375,525));
private void pukeMeAChart(){
    try {
        mContents.saveGraphicsState();
        mContents.transform(Matrix.getTranslateInstance(375,525));
        drawSlice(Color.YELLOW, 60, 0, 69);
        drawSlice(Color.BLUE, 60, 69, 117);
        drawSlice(Color.RED, 60, 117, 181);
        drawSlice(Color.WHITE, 60, 181, 208);
        drawSlice(Color.GREEN, 60, 208, 272);
        drawSlice(Color.YELLOW, 60, 272, 336);
        drawSlice(Color.BLUE, 60, 336, 360);
        mContents.restoreGraphicsState();
    } catch(IOException e ){}
}
private void generateDailyChart(){
    mContents.saveGraphicsState();
    int totalVal = 0;
    try {
        mContents.transform(Matrix.getTranslateInstance(375, 525));
    }catch(IOException e){}

    for (int i=1; i< 8;i++){
        totalVal += mDayPercent[i];
        writeTheChart(mDayPercent[i-1], totalVal,mColor[i]);
        log.info("Color selected = " +mColor[i] +"Index = "+i);
    }
    mContents.restoreGraphicsState();
}