You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2015/09/27 20:04:44 UTC

svn commit: r1705561 [3/6] - in /pdfbox/trunk: ./ debugger/ debugger/src/ debugger/src/main/ debugger/src/main/java/ debugger/src/main/java/org/ debugger/src/main/java/org/apache/ debugger/src/main/java/org/apache/pdfbox/ debugger/src/main/java/org/apa...

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,141 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+/**
+ * @author Khyrul Bashar
+ * A class that provides field flag bits.
+ */
+class FieldFlag extends Flag
+{
+    private final COSDictionary dictionary;
+
+    /**
+     * Constructor
+     * @param dictionary COSDictionary instance
+     */
+    FieldFlag(COSDictionary dictionary)
+    {
+        this.dictionary = dictionary;
+    }
+
+    @Override
+    String getFlagType()
+    {
+        COSName fieldType = dictionary.getCOSName(COSName.FT);
+        if (COSName.TX.equals(fieldType))
+        {
+            return "Text field flag";
+        }
+        else if (COSName.BTN.equals(fieldType))
+        {
+            return "Button field flag";
+        }
+        else if (COSName.CH.equals(fieldType))
+        {
+            return "Choice field flag";
+        }
+        return null;
+    }
+
+    @Override
+    String getFlagValue()
+    {
+        return "Flag value: " + dictionary.getInt(COSName.FF);
+    }
+
+    @Override
+    Object[][] getFlagBits()
+    {
+        int flagValue = dictionary.getInt(COSName.FF);
+        COSName fieldType = dictionary.getCOSName(COSName.FT);
+
+        if (COSName.TX.equals(fieldType))
+        {
+            return getTextFieldFlagBits(flagValue);
+        }
+        else if (COSName.BTN.equals(fieldType))
+        {
+            return getButtonFieldFlagBits(flagValue);
+        }
+        else if (COSName.CH.equals(fieldType))
+        {
+            return getChoiceFieldFlagBits(flagValue);
+        }
+        return null;
+    }
+
+    private Object[][] getTextFieldFlagBits(final int flagValue)
+    {
+        return new Object[][]{
+                new Object[]{1, "ReadOnly", isFlagBitSet(flagValue, 1)},
+                new Object[]{2, "Required", isFlagBitSet(flagValue, 2)},
+                new Object[]{3, "NoExport", isFlagBitSet(flagValue, 3)},
+                new Object[]{13, "Multiline", isFlagBitSet(flagValue, 13)},
+                new Object[]{14, "Password", isFlagBitSet(flagValue, 14)},
+                new Object[]{21, "FileSelect", isFlagBitSet(flagValue, 21)},
+                new Object[]{23, "DoNotSpellCheck", isFlagBitSet(flagValue, 23)},
+                new Object[]{24, "DoNotScroll", isFlagBitSet(flagValue, 24)},
+                new Object[]{25, "Comb", isFlagBitSet(flagValue, 25)},
+                new Object[]{26, "RichText", isFlagBitSet(flagValue, 26)}
+        };
+    }
+
+    private Object[][] getButtonFieldFlagBits(final int flagValue)
+    {
+        return new Object[][]{
+                new Object[]{1, "ReadOnly", isFlagBitSet(flagValue, 1)},
+                new Object[]{2, "Required", isFlagBitSet(flagValue, 2)},
+                new Object[]{3, "NoExport", isFlagBitSet(flagValue, 3)},
+                new Object[]{15, "NoToggleToOff", isFlagBitSet(flagValue, 15)},
+                new Object[]{16, "Radio", isFlagBitSet(flagValue, 16)},
+                new Object[]{17, "Pushbutton", isFlagBitSet(flagValue, 17)},
+                new Object[]{26, "RadiosInUnison", isFlagBitSet(flagValue, 26)}
+        };
+    }
+
+    private Object[][] getChoiceFieldFlagBits(final int flagValue)
+    {
+        return new Object[][]{
+                new Object[]{1, "ReadOnly", isFlagBitSet(flagValue, 1)},
+                new Object[]{2, "Required", isFlagBitSet(flagValue, 2)},
+                new Object[]{3, "NoExport", isFlagBitSet(flagValue, 3)},
+                new Object[]{18, "Combo", isFlagBitSet(flagValue, 18)},
+                new Object[]{19, "Edit", isFlagBitSet(flagValue, 19)},
+                new Object[]{20, "Sort", isFlagBitSet(flagValue, 20)},
+                new Object[]{22, "MultiSelect", isFlagBitSet(flagValue, 22)},
+                new Object[]{23, "DoNotSpellCheck", isFlagBitSet(flagValue, 23)},
+                new Object[]{27, "CommitOnSelChange", isFlagBitSet(flagValue, 27)}
+        };
+    }
+
+    /**
+     * Check the corresponding flag bit if set or not
+     * @param flagValue the flag integer
+     * @param bitPosition bit position to check
+     * @return if set return true else false
+     */
+    private Boolean isFlagBitSet(int flagValue, int bitPosition)
+    {
+        int binaryFormat = 1 << (bitPosition - 1);
+        return (flagValue & binaryFormat) == binaryFormat;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FieldFlag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,34 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * An abstract class that provides Flag bits.
+ */
+abstract class Flag
+{
+    abstract String getFlagType();
+    abstract String getFlagValue();
+    abstract Object[][] getFlagBits();
+    String[] getColumnNames()
+    {
+        return new String[] {"Bit Position", "Name", "Set"};
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/Flag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,83 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import javax.swing.JPanel;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that displays flag bits in a table in detail.
+ */
+public class FlagBitsPane
+{
+    private FlagBitsPaneView view;
+
+    /**
+     * Constructor.
+     * @param dictionary COSDictionary instance.
+     * @param flagType COSName instance.
+     */
+    public FlagBitsPane(final COSDictionary dictionary, COSName flagType)
+    {
+        createPane(dictionary, flagType);
+    }
+
+    private void createPane(final COSDictionary dictionary, final COSName flagType)
+    {
+        Flag flag;
+        if (COSName.FLAGS.equals(flagType))
+        {
+            flag = new FontFlag(dictionary);
+            view = new FlagBitsPaneView(
+                    flag.getFlagType(), flag.getFlagValue(), flag.getFlagBits(), flag.getColumnNames());
+        }
+
+        if (COSName.F.equals(flagType))
+        {
+            flag = new AnnotFlag(dictionary);
+            view = new FlagBitsPaneView(
+                    flag.getFlagType(), flag.getFlagValue(), flag.getFlagBits(), flag.getColumnNames());
+        }
+
+        if (COSName.FF.equals(flagType))
+        {
+            flag = new FieldFlag(dictionary);
+            view = new FlagBitsPaneView(
+                    flag.getFlagType(), flag.getFlagValue(), flag.getFlagBits(), flag.getColumnNames());
+        }
+
+        if (COSName.PANOSE.equals(flagType))
+        {
+            flag = new PanoseFlag(dictionary);
+            view = new FlagBitsPaneView(
+                    flag.getFlagType(), flag.getFlagValue(), flag.getFlagBits(), flag.getColumnNames());
+        }
+    }
+
+    /**
+     * Returns the Pane itself
+     * @return JPanel instance
+     */
+    public JPanel getPane()
+    {
+        return view.getPanel();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPane.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,117 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that create the necessary UI for showing Flag bits.
+ */
+class FlagBitsPaneView
+{
+    final private JPanel panel;
+    final private String flagHeader;
+    final private String flagValue;
+    final private Object[][] tableData;
+    final private String[] columnNames;
+
+    /**
+     * Constructor
+     * @param flagHeader String instance. Flag type.
+     * @param flagValue String instance. Flag integer value.
+     * @param tableRowData Object 2d array for table row data.
+     * @param columnNames String array for column names.
+     */
+    FlagBitsPaneView(String flagHeader, String flagValue, Object[][] tableRowData, String[] columnNames)
+    {
+        this.flagHeader = flagHeader;
+        this.flagValue = flagValue;
+        this.tableData = tableRowData;
+        this.columnNames = columnNames;
+        panel = new JPanel();
+
+        if (flagValue != null && tableData != null)
+        {
+            createView();
+        }
+    }
+
+    private void createView()
+    {
+        panel.setLayout(new GridBagLayout());
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        JLabel flagLabel = new JLabel(flagHeader);
+        flagLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        flagLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 30));
+        JPanel flagLabelPanel = new JPanel();
+        flagLabelPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        flagLabelPanel.add(flagLabel);
+
+        JLabel flagValueLabel = new JLabel(flagValue);
+        flagValueLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        flagValueLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 20));
+
+        JTable table = new JTable(tableData, columnNames);
+        JScrollPane scrollPane = new JScrollPane(table);
+        table.setFillsViewportHeight(true);
+        scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        Box box = Box.createVerticalBox();
+        box.add(flagValueLabel);
+        box.add(scrollPane);
+        box.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weighty = 0.05;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        gbc.anchor = GridBagConstraints.PAGE_START;
+
+        panel.add(flagLabelPanel, gbc);
+
+        gbc.gridy = 2;
+        gbc.weighty = 0.9;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        gbc.anchor = GridBagConstraints.BELOW_BASELINE;
+
+        panel.add(box, gbc);
+    }
+
+    /**
+     * Returns the view.
+     * @return JPanel instance.
+     */
+    JPanel getPanel()
+    {
+        return panel;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FlagBitsPaneView.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,70 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that provides Font flag bits.
+ */
+public class FontFlag extends Flag
+{
+    private final COSDictionary fontDescriptor;
+
+    /**
+     * Constructor
+     * @param fontDescDictionary COSDictionary instance.
+     */
+    FontFlag(COSDictionary fontDescDictionary)
+    {
+        fontDescriptor = fontDescDictionary;
+    }
+
+    @Override
+    String getFlagType()
+    {
+        return "Font flag";
+    }
+
+    @Override
+    String getFlagValue()
+    {
+        return "Flag value:" + fontDescriptor.getInt(COSName.FLAGS);
+    }
+
+    @Override
+    Object[][] getFlagBits()
+    {
+        PDFontDescriptor fontDesc = new PDFontDescriptor(fontDescriptor);
+        return new Object[][]{
+                new Object[]{1, "FixedPitch", fontDesc.isFixedPitch()},
+                new Object[]{2, "Serif", fontDesc.isSerif()},
+                new Object[]{3, "Symbolic", fontDesc.isSymbolic()},
+                new Object[]{4, "Script", fontDesc.isScript()},
+                new Object[]{6, "NonSymbolic", fontDesc.isNonSymbolic()},
+                new Object[]{7, "Italic", fontDesc.isItalic()},
+                new Object[]{17, "AllCap", fontDesc.isAllCap()},
+                new Object[]{18, "SmallCap", fontDesc.isSmallCap()},
+                new Object[]{19, "ForceBold", fontDesc.isForceBold()}
+        };
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/FontFlag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,267 @@
+/*
+ *   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.pdfbox.tools.pdfdebugger.flagbitspane;
+
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.font.PDPanose;
+import org.apache.pdfbox.pdmodel.font.PDPanoseClassification;
+
+/**
+ * @author Khyrul Bashar
+ * A class that provide Panose classification data
+ */
+public class PanoseFlag extends Flag
+{
+
+    private final byte[] bytes;
+    private final COSString byteValue;
+
+    /**
+     * Constructor.
+     * @param dictionary COSDictionary instance. style dictionary that contains panose object.
+     */
+    public PanoseFlag(COSDictionary dictionary)
+    {
+        byteValue = (COSString)dictionary.getDictionaryObject(COSName.PANOSE);
+        bytes = getPanoseBytes(dictionary);
+    }
+
+
+    @Override
+    String getFlagType()
+    {
+        return "Panose classification";
+    }
+
+    @Override
+    String getFlagValue()
+    {
+        return "Panose byte :" + byteValue.toHexString();
+    }
+
+    @Override
+    Object[][] getFlagBits()
+    {
+        PDPanoseClassification pc = new PDPanose(bytes).getPanose();
+        return new Object[][]{
+                {2, "Family Kind", pc.getFamilyKind(), getFamilyKindValue(pc.getFamilyKind())},
+                {3, "Serif Style", pc.getSerifStyle(), getSerifStyleValue(pc.getSerifStyle())},
+                {4, "Weight", pc.getWeight(), getWeightValue(pc.getWeight())},
+                {5, "Proportion", pc.getProportion(), getProportionValue(pc.getProportion())},
+                {6, "Contrast", pc.getContrast(), getContrastValue(pc.getContrast())},
+                {7, "Stroke Variation", pc.getStrokeVariation(), getStrokeVariationValue(pc.getStrokeVariation())},
+                {8, "Arm Style", pc.getArmStyle(), getArmStyleValue(pc.getArmStyle())},
+                {9, "Letterform", pc.getLetterform(), getLetterformValue(pc.getLetterform())},
+                {10, "Midline", pc.getMidline(), getMidlineValue(pc.getMidline())},
+                {11, "X-height", pc.getXHeight(), getXHeightValue(pc.getXHeight())},
+        };
+    }
+
+    @Override
+    String[] getColumnNames()
+    {
+        return new String[] {"Byte Position", "Name", "Byte Value", "Value"};
+    }
+
+    private String getFamilyKindValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Latin Text",
+                "Latin Hand Written",
+                "Latin Decorative",
+                "Latin Symbol"
+        }[index];
+    }
+
+    private String getSerifStyleValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Cove",
+                "Obtuse Cove",
+                "Square Cove",
+                "Obtuse Square Cove",
+                "Square",
+                "Thin",
+                "Oval",
+                "Exaggerated",
+                "Triangle",
+                "Normal Sans",
+                "Obtuse Sans",
+                "Perpendicular Sans",
+                "Flared",
+                "Rounded"
+        }[index];
+    }
+
+    private String getWeightValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Very Light",
+                "Light",
+                "Thin",
+                "Book",
+                "Medium",
+                "Demi",
+                "Bold",
+                "Heavy",
+                "Black",
+                "Extra Black"
+        }[index];
+    }
+
+    private String getProportionValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No fit",
+                "Old Style",
+                "Modern",
+                "Even Width",
+                "Extended",
+                "Condensed",
+                "Very Extended",
+                "Very Condensed",
+                "Monospaced"
+        }[index];
+    }
+
+    private String getContrastValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "None",
+                "Very Low",
+                "Low",
+                "Medium Low",
+                "Medium",
+                "Medium High",
+                "High",
+                "Very High"
+        }[index];
+    }
+
+    private String getStrokeVariationValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "No Variation",
+                "Gradual/Diagonal",
+                "Gradual/Transitional",
+                "Gradual/Vertical",
+                "Gradual/Horizontal",
+                "Rapid/Vertical",
+                "Rapid/Horizontal",
+                "Instant/Vertical",
+                "Instant/Horizontal",
+        }[index];
+    }
+
+    private String getArmStyleValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Straight Arms/Horizontal",
+                "Straight Arms/Wedge",
+                "Straight Arms/Vertical",
+                "Straight Arms/Single Serif",
+                "Straight Arms/Double Serif",
+                "Non-Straight/Horizontal",
+                "Non-Straight/Wedge",
+                "Non-Straight/Vertical",
+                "Non-Straight/Single Serif",
+                "Non-Straight/Double Serif",
+        }[index];
+    }
+
+    private String getLetterformValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Normal/Contact",
+                "Normal/Weighted",
+                "Normal/Boxed",
+                "Normal/Flattened",
+                "Normal/Rounded",
+                "Normal/Off Center",
+                "Normal/Square",
+                "Oblique/Contact",
+                "Oblique/Weighted",
+                "Oblique/Boxed",
+                "Oblique/Flattened",
+                "Oblique/Rounded",
+                "Oblique/Off Center",
+                "Oblique/Square",
+        }[index];
+    }
+
+    private String getMidlineValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Standard/Trimmed",
+                "Standard/Pointed",
+                "Standard/Serifed",
+                "High/Trimmed",
+                "High/Pointed",
+                "High/Serifed",
+                "Constant/Trimmed",
+                "Constant/Pointed",
+                "Constant/Serifed",
+                "Low/Trimmed",
+                "Low/Pointed",
+                "Low/Serifed"
+        }[index];
+    }
+
+    private String getXHeightValue(int index)
+    {
+        return new String[]{
+                "Any",
+                "No Fit",
+                "Constant/Small",
+                "Constant/Standard",
+                "Constant/Large",
+                "Ducking/Small",
+                "Ducking/Standard",
+                "Ducking/Large",
+        }[index];
+    }
+
+    public final byte[] getPanoseBytes(COSDictionary style)
+    {
+        if (style != null)
+        {
+            COSString panose = (COSString)style.getDictionaryObject(COSName.PANOSE);
+            return panose.getBytes();
+        }
+        return null;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/flagbitspane/PanoseFlag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.tools.pdfdebugger.fontencodingpane;
+
+import java.io.IOException;
+import javax.swing.JPanel;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDResources;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+
+interface FontPane
+{
+    JPanel getPanel();
+}
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that shows the glyph table or CIDToGID map depending on the font type. PDSimple and
+ * PDType0Font are supported.
+ */
+public class FontEncodingPaneController
+{
+    private FontPane fontPane;
+
+    /**
+     * Constructor.
+     * @param fontName COSName instance, Font name in the fonts dictionary.
+     * @param dictionary COSDictionary instance for resources which resides the font.
+     */
+    public FontEncodingPaneController(COSName fontName, COSDictionary dictionary)
+    {
+        PDResources resources = new PDResources(dictionary);
+        try
+        {
+            PDFont font = resources.getFont(fontName);
+            if (font instanceof PDSimpleFont)
+            {
+                fontPane = new SimpleFont((PDSimpleFont) font);
+            }
+            else if (font instanceof PDType0Font
+                    && ((PDType0Font) font).getDescendantFont() instanceof PDCIDFontType2)
+            {
+                fontPane = new Type0Font((PDCIDFontType2) ((PDType0Font) font).getDescendantFont(), font);
+            }
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * Return a pane to display details of a font.
+     * 
+     * @return a pane for font information, or null if that font type is not supported.
+     */
+    public JPanel getPane()
+    {
+        if (fontPane != null)
+        {
+            return fontPane.getPanel();
+        }
+        return null;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingPaneController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.tools.pdfdebugger.fontencodingpane;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Iterator;
+import java.util.Map;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingConstants;
+import javax.swing.table.TableCellRenderer;
+
+/**
+ * @author Khyrul Bashar
+ * A class that creates the UI for font encoding pane.
+ */
+class FontEncodingView
+{
+    private JPanel panel;
+
+    /**
+     * Constructor.
+     * @param tableData Object[][] instance as table data.
+     * @param headerAttributes Map<String, String> instance which contains info for showing in header
+     *                         panel. Here keys will be info type.
+     * @param columnNames String array containing the columns name.
+     */
+    FontEncodingView(Object[][] tableData, Map<String, String> headerAttributes, String[] columnNames)
+    {
+        createView(getHeaderPanel(headerAttributes), getTable(tableData, columnNames));
+    }
+
+    private void createView(JPanel headerPanel, JTable table)
+    {
+        panel = new JPanel(new GridBagLayout());
+        panel.setPreferredSize(new Dimension(300, 500));
+
+        JScrollPane scrollPane = new JScrollPane(table);
+        table.setFillsViewportHeight(true);
+        scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weighty = 0.05;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        gbc.anchor = GridBagConstraints.PAGE_START;
+
+        panel.add(headerPanel, gbc);
+
+        gbc.gridy = 2;
+        gbc.weighty = 0.9;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        gbc.anchor = GridBagConstraints.BELOW_BASELINE;
+
+        panel.add(scrollPane, gbc);
+    }
+
+    private JTable getTable(Object[][] tableData, String[] columnNames)
+    {
+        JTable table = new JTable(tableData, columnNames);
+        table.setRowHeight(40);
+        table.setDefaultRenderer(Object.class, new GlyphCellRenderer());
+        return table;
+    }
+
+    private JPanel getHeaderPanel(Map<String, String> attributes)
+    {
+        JPanel headerPanel = new JPanel(new GridBagLayout());
+
+        if (attributes != null)
+        {
+            Iterator<String> keys = attributes.keySet().iterator();
+            int row = 0;
+            while (keys.hasNext())
+
+            {
+                String key = keys.next();
+                JLabel encodingNameLabel = new JLabel(key + ": " + attributes.get(key));
+                encodingNameLabel.setFont(new Font(Font.MONOSPACED, Font.BOLD, 17));
+
+                GridBagConstraints gbc = new GridBagConstraints();
+                gbc.gridx = 0;
+                gbc.gridy = row++;
+                gbc.weighty = 0.1;
+                gbc.anchor = GridBagConstraints.LINE_START;
+
+                headerPanel.add(encodingNameLabel, gbc);
+
+            }
+        }
+        return headerPanel;
+    }
+
+    JPanel getPanel()
+    {
+        return panel;
+    }
+
+    private static final class GlyphCellRenderer implements TableCellRenderer
+    {
+
+        @Override
+        public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int i, int i1)
+        {
+            if (o != null)
+            {
+                JLabel label = new JLabel(o.toString());
+                label.setHorizontalAlignment(SwingConstants.CENTER);
+                label.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 25));
+                if (SimpleFont.NO_GLYPH.equals(o) || ".notdef".equals(o))
+                {
+                    label.setText(o.toString());
+                    label.setForeground(Color.RED);
+                }
+                return label;
+            }
+            return new JLabel();
+        }
+    }
+}
+
+

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/FontEncodingView.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.tools.pdfdebugger.fontencodingpane;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.swing.JPanel;
+import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
+
+/**
+ * @author Khyrul Bashar
+ * A class that shows the glyph table along with unicode characters for SimpleFont.
+ */
+class SimpleFont implements FontPane
+{
+    public static final String NO_GLYPH = "No glyph";
+    private int totalAvailableGlyph = 0;
+    private final FontEncodingView view;
+
+    /**
+     * Constructor.
+     * @param font PDSimpleFont instance.
+     * @throws IOException If fails to parse unicode characters.
+     */
+    SimpleFont(PDSimpleFont font) throws IOException
+    {
+        Object[][] tableData = getGlyphs(font);
+
+        Map<String, String> attributes = new LinkedHashMap<String, String>();
+        attributes.put("Encoding", getEncodingName(font));
+        attributes.put("Font", font.getName());
+        attributes.put("Glyph count", Integer.toString(totalAvailableGlyph));
+
+        view = new FontEncodingView(tableData, attributes, new String[] {"Code", "Glyph Name","Unicode Character"});
+    }
+
+    private Object[][] getGlyphs(PDSimpleFont font) throws IOException
+    {
+        Object[][] glyphs = new Object[256][3];
+
+        for (int index = 0; index <= 255; index++)
+        {
+            glyphs[index][0] = index;
+            if (font.getEncoding().contains(index))
+            {
+                glyphs[index][1] = font.getEncoding().getName(index);
+                glyphs[index][2] = font.toUnicode(index);
+                totalAvailableGlyph++;
+            }
+            else
+            {
+                glyphs[index][1] = NO_GLYPH;
+                glyphs[index][2] = NO_GLYPH;
+            }
+        }
+        return glyphs;
+    }
+
+
+    private String getEncodingName(PDSimpleFont font)
+    {
+        return font.getEncoding().getClass().getSimpleName();
+    }
+
+    @Override
+    public JPanel getPanel()
+    {
+        return view.getPanel();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/SimpleFont.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed 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.pdfbox.tools.pdfdebugger.fontencodingpane;
+
+import java.awt.Dimension;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.swing.JPanel;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+
+/**
+ * @author Khyrul Bashar
+ * A class that shows the CIDToGID table along with unicode characters for Type0Fonts when descendent
+ * font is of type PDCIDFontType2.
+ */
+class Type0Font implements FontPane
+{
+    private FontEncodingView view;
+
+    /**
+     * Constructor.
+     * @param descendantFont PDCIDFontType2 instance.
+     * @param parentFont PDFont instance.
+     * @throws IOException If fails to parse cidtogid map.
+     */
+    Type0Font(PDCIDFontType2 descendantFont, PDFont parentFont) throws IOException
+    {
+        Object[][] cidtogid = readCIDToGIDMap(descendantFont, parentFont);
+        if (cidtogid != null)
+        {
+            Map<String, String> attributes = new LinkedHashMap<String, String>();
+            attributes.put("Font", descendantFont.getName());
+            attributes.put("CID count", Integer.toString(cidtogid.length));
+
+            view = new FontEncodingView(cidtogid, attributes, new String[]{"CID", "GID", "Unicode Character"});
+        }
+    }
+
+    private Object[][] readCIDToGIDMap(PDCIDFontType2 font, PDFont parentFont) throws IOException
+    {
+        Object[][] cid2gid = null;
+        COSDictionary dict = font.getCOSObject();
+        COSBase map = dict.getDictionaryObject(COSName.CID_TO_GID_MAP);
+        if (map instanceof COSStream)
+        {
+            COSStream stream = (COSStream) map;
+
+            InputStream is = stream.createInputStream();
+            byte[] mapAsBytes = IOUtils.toByteArray(is);
+            IOUtils.closeQuietly(is);
+            int numberOfInts = mapAsBytes.length / 2;
+            cid2gid = new Object[numberOfInts][3];
+            int offset = 0;
+            for (int index = 0; index < numberOfInts; index++)
+            {
+                int gid = (mapAsBytes[offset] & 0xff) << 8 | mapAsBytes[offset + 1] & 0xff;
+                cid2gid[index][0] = index;
+                cid2gid[index][1] = gid;
+                if (gid != 0 && parentFont.toUnicode(index) != null)
+                {
+                    cid2gid[index][2] = parentFont.toUnicode(index);
+                }
+                offset += 2;
+            }
+        }
+        return cid2gid;
+    }
+
+
+
+    @Override
+    public JPanel getPanel()
+    {
+        if (view != null)
+        {
+            return view.getPanel();
+        }
+        JPanel panel = new JPanel();
+        panel.setPreferredSize(new Dimension(300, 500));
+        return panel;
+    }
+}
\ No newline at end of file

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/fontencodingpane/Type0Font.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,130 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import javax.swing.JComponent;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This class shows corresponding ASCII characters for bytes. For every 16 byte there is one line.
+ * This paints the only visible contents at one time.
+ */
+class ASCIIPane extends JComponent implements HexModelChangeListener
+{
+    private final HexModel model;
+    private int selectedLine = -1;
+    private int selectedIndexInLine;
+
+    /**
+     * Constructor.
+     * @param model HexModel instance.
+     */
+    ASCIIPane(HexModel model)
+    {
+        this.model = model;
+        setPreferredSize(new Dimension(HexView.ASCII_PANE_WIDTH, HexView.CHAR_HEIGHT * (model.totalLine()+1)));
+        model.addHexModelChangeListener(this);
+        setFont(HexView.FONT);
+    }
+
+
+    @Override
+    protected void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+
+        Graphics2D g2d = (Graphics2D)g;
+        g2d.setRenderingHints(HexView.RENDERING_HINTS);
+        
+        Rectangle bound = getVisibleRect();
+
+        int x = HexView.LINE_INSET;
+        int y = bound.y;
+
+        if (y == 0 || y%HexView.CHAR_HEIGHT != 0)
+        {
+            y += HexView.CHAR_HEIGHT - y%HexView.CHAR_HEIGHT;
+        }
+        int firstLine = y/HexView.CHAR_HEIGHT;
+
+        for (int line = firstLine; line < firstLine + bound.getHeight()/HexView.CHAR_HEIGHT; line++)
+        {
+            if (line > model.totalLine())
+            {
+                break;
+            }
+            if (line == selectedLine)
+            {
+                paintInSelected(g, x, y);
+            }
+            else
+            {
+                char[] chars = model.getLineChars(line);
+                g.drawChars(chars, 0, chars.length, x, y);
+            }
+            x = HexView.LINE_INSET;
+            y += HexView.CHAR_HEIGHT;
+        }
+    }
+
+    /**
+     * Paint a selected line
+     * @param g Graphics instance.
+     * @param x int. x axis value.
+     * @param y int. y axis value.
+     */
+    private void paintInSelected(Graphics g, int x, int y)
+    {
+        g.setFont(HexView.BOLD_FONT);
+        char[] content = model.getLineChars(selectedLine);
+        g.drawChars(content, 0, selectedIndexInLine - 0, x, y);
+
+        g.setColor(HexView.SELECTED_COLOR);
+        x += g.getFontMetrics().charsWidth(content, 0, selectedIndexInLine-0);
+        g.drawChars(content, selectedIndexInLine, 1, x, y);
+
+        g.setColor(Color.black);
+        x += g.getFontMetrics().charWidth(content[selectedIndexInLine]);
+        g.drawChars(content, selectedIndexInLine+1, (content.length-1)-selectedIndexInLine, x, y);
+        g.setFont(HexView.FONT);
+    }
+    
+    @Override
+    public void hexModelChanged(HexModelChangedEvent event)
+    {
+        repaint();
+    }
+
+    /**
+     * Updates the line text for a given index. It is used when a byte is
+     * selected in hex pane.
+     * @param index int.
+     */
+    void setSelected(int index)
+    {
+            selectedLine = HexModel.lineNumber(index);
+            selectedIndexInLine = HexModel.elementIndexInLine(index);
+            repaint();
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/ASCIIPane.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,118 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import javax.swing.JComponent;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This class shows the address of the currently selected byte.
+ */
+class AddressPane extends JComponent
+{
+    private final int totalLine;
+    private int selectedLine = -1;
+    private int selectedIndex = -1;
+
+    /**
+     * Constructor.
+     * @param total int. Total line number needed to show all the bytes.
+     */
+    AddressPane(int total)
+    {
+        totalLine = total;
+        setPreferredSize(new Dimension(HexView.ADDRESS_PANE_WIDTH, HexView.CHAR_HEIGHT * (totalLine+1)));
+        setFont(HexView.FONT);
+    }
+
+    @Override
+    protected void paintComponent(Graphics g)
+    {
+        super.paintComponent(g);
+
+        Graphics2D g2d = (Graphics2D)g;
+        g2d.setRenderingHints(HexView.RENDERING_HINTS);
+        
+        Rectangle bound = getVisibleRect();
+
+        int x = HexView.LINE_INSET;
+        int y = bound.y;
+
+        if (y == 0 || y%HexView.CHAR_HEIGHT != 0)
+        {
+            y += HexView.CHAR_HEIGHT - y%HexView.CHAR_HEIGHT;
+        }
+        int firstLine = y/HexView.CHAR_HEIGHT;
+
+        for (int line = firstLine; line < firstLine + bound.getHeight()/HexView.CHAR_HEIGHT; line++)
+        {
+            if (line > totalLine)
+            {
+                break;
+            }
+            if (line == selectedLine)
+            {
+                paintSelected(g, x, y);
+            }
+            else
+            {
+                g.drawString(String.format("%08X", (line - 1)*16), x, y);
+            }
+            x = HexView.LINE_INSET;
+            y += HexView.CHAR_HEIGHT;
+        }
+    }
+
+    /**
+     * Paint a selected line
+     * @param g Graphics instance.
+     * @param x int. x axis value.
+     * @param y int. y axis value.
+     */
+    private void paintSelected(Graphics g, int x, int y)
+    {
+        g.setColor(HexView.SELECTED_COLOR);
+        g.setFont(HexView.BOLD_FONT);
+
+        g.drawString(String.format("%08X", selectedIndex), x, y);
+
+        g.setColor(Color.black);
+        g.setFont(HexView.FONT);
+    }
+
+    /**
+     * Updates the line text (index in hexadecimal) for a given index. It is used when a byte is
+     * selected in hex pane.
+     * @param index int.
+     */
+    void setSelected(int index)
+    {
+        if (index != selectedIndex)
+        {
+            selectedLine = HexModel.lineNumber(index);
+            selectedIndex = index;
+            repaint();
+        }
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/AddressPane.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,28 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This Interface is used to listen for the byte value changes.
+ */
+interface HexChangeListener
+{
+    void hexChanged(HexChangedEvent event);
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangeListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,50 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This the event class for byte value changed from the Hex pane.
+ */
+class HexChangedEvent
+{
+    private final byte newValue;
+    private final int byteIndex;
+
+    /**
+     * Constructor.
+     * @param newValue byte. The new byte value for the index.
+     * @param byteIndex int. Index for the changed byte.
+     */
+    HexChangedEvent(byte newValue, int byteIndex)
+    {
+        this.newValue = newValue;
+        this.byteIndex = byteIndex;
+    }
+
+    public byte getNewValue()
+    {
+        return newValue;
+    }
+
+    public int getByteIndex()
+    {
+        return byteIndex;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexChangedEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,226 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.text.NumberFormat;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.JDialog;
+import javax.swing.JFormattedTextField;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.border.LineBorder;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * This class hosts all the UI components of Hex view and cordinate among them.
+ */
+class HexEditor extends JPanel implements SelectionChangeListener
+{
+    private final HexModel model;
+    private HexPane hexPane;
+    private ASCIIPane asciiPane;
+    private AddressPane addressPane;
+    private StatusPane statusPane;
+    private final Action jumpToIndex;
+
+    private int selectedIndex = -1;
+
+    /**
+     * Constructor.
+     * @param model HexModel instance.
+     */
+    HexEditor(HexModel model)
+    {
+        super();
+        this.jumpToIndex = new AbstractAction()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                createJumpDialog().setVisible(true);
+            }
+        };
+        this.model = model;
+        createView();
+    }
+
+    private void createView()
+    {
+        setLayout(new GridBagLayout());
+
+        addressPane = new AddressPane(model.totalLine());
+        hexPane = new HexPane(model);
+        hexPane.addHexChangeListeners(model);
+        asciiPane = new ASCIIPane(model);
+        UpperPane upperPane = new UpperPane();
+        statusPane = new StatusPane();
+
+        model.addHexModelChangeListener(hexPane);
+        model.addHexModelChangeListener(asciiPane);
+
+        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
+        panel.setPreferredSize(new Dimension(HexView.TOTAL_WIDTH, HexView.CHAR_HEIGHT * (model.totalLine() + 1)));
+        panel.add(addressPane);
+        panel.add(hexPane);
+        panel.add(asciiPane);
+
+        JScrollPane scrollPane = getScrollPane();
+        scrollPane.setViewportView(panel);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+        gbc.fill = GridBagConstraints.BOTH;
+        gbc.weighty = 0.02;
+        add(upperPane, gbc);
+        gbc.anchor = GridBagConstraints.LINE_START;
+        gbc.gridy = 1;
+        gbc.weighty = 1;
+        gbc.weightx = 1;
+        gbc.fill = GridBagConstraints.BOTH;
+        add(scrollPane, gbc);
+        gbc.gridy = 2;
+        gbc.weightx = 0.1;
+        gbc.weighty = 0.0;
+        gbc.anchor = GridBagConstraints.LAST_LINE_START;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        add(statusPane, gbc);
+
+        hexPane.addSelectionChangeListener(this);
+
+        KeyStroke jumpKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_DOWN_MASK);
+        this.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(jumpKeyStroke, "jump");
+        this.getActionMap().put("jump", jumpToIndex);
+    }
+
+    private JScrollPane getScrollPane()
+    {
+        JScrollPane scrollPane = new JScrollPane();
+        scrollPane.setBorder(new LineBorder(Color.LIGHT_GRAY));
+
+        Action blankAction = new AbstractAction()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+            }
+        };
+
+        scrollPane.getActionMap().put("unitScrollDown", blankAction);
+        scrollPane.getActionMap().put("unitScrollLeft", blankAction);
+        scrollPane.getActionMap().put("unitScrollRight", blankAction);
+        scrollPane.getActionMap().put("unitScrollUp", blankAction);
+
+        JScrollBar verticalScrollBar = scrollPane.createVerticalScrollBar();
+        verticalScrollBar.setUnitIncrement(HexView.CHAR_HEIGHT);
+        verticalScrollBar.setBlockIncrement(HexView.CHAR_HEIGHT * 20);
+        verticalScrollBar.setValues(0, 1, 0, HexView.CHAR_HEIGHT * (model.totalLine()+1));
+        scrollPane.setVerticalScrollBar(verticalScrollBar);
+
+        return scrollPane;
+    }
+
+    @Override
+    public void selectionChanged(SelectEvent event)
+    {
+        int index = event.getHexIndex();
+
+        if (event.getNavigation().equals(SelectEvent.NEXT))
+        {
+            index += 1;
+        }
+        else if (event.getNavigation().equals(SelectEvent.PREVIOUS))
+        {
+            index -= 1;
+        }
+        else if (event.getNavigation().equals(SelectEvent.UP))
+        {
+            index -= 16;
+
+        }
+        else if (event.getNavigation().equals(SelectEvent.DOWN))
+        {
+            index += 16;
+        }
+        if (index >= 0 && index <= model.size() - 1)
+        {
+            hexPane.setSelected(index);
+            addressPane.setSelected(index);
+            asciiPane.setSelected(index);
+            statusPane.updateStatus(index);
+            selectedIndex = index;
+        }
+    }
+
+    private JDialog createJumpDialog()
+    {
+        final JDialog dialog = new JDialog(SwingUtilities.windowForComponent(this), "Jump to index");
+        dialog.setLocationRelativeTo(this);
+        final JLabel nowLabel = new JLabel("Present index: " + selectedIndex);
+        final JLabel label = new JLabel("Index to go:");
+        final JTextField field = new JFormattedTextField(NumberFormat.getIntegerInstance());
+        field.setPreferredSize(new Dimension(100, 20));
+
+        field.addActionListener(new AbstractAction()
+        {
+            @Override
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                int index = Integer.parseInt(field.getText(), 10);
+                if (index >= 0 && index <= model.size() - 1)
+                {
+                    selectionChanged(new SelectEvent(index, SelectEvent.IN));
+                    dialog.dispose();
+                }
+            }
+        });
+
+        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+        panel.add(nowLabel);
+
+        JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+        inputPanel.add(label);
+        inputPanel.add(field);
+
+        JPanel contentPanel = new JPanel();
+        contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
+        contentPanel.add(panel);
+        contentPanel.add(inputPanel);
+        dialog.getContentPane().add(contentPanel);
+        dialog.pack();
+        return dialog;
+    }
+
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,167 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * A class that acts as a model for the hex viewer. It holds the data and provide the data as ncessary.
+ * It'll let listen for any underlying data changes.
+ */
+class HexModel implements HexChangeListener
+{
+    private final List<Byte> data;
+    private final List<HexModelChangeListener> modelChangeListeners;
+
+    /**
+     * Constructor
+     * @param bytes Byte array.
+     */
+    HexModel(byte[] bytes)
+    {
+        data = new ArrayList<Byte>(bytes.length);
+
+        for (byte b: bytes)
+        {
+            data.add(b);
+        }
+
+        modelChangeListeners = new ArrayList<HexModelChangeListener>();
+    }
+
+    /**
+     * provides the byte for a specific index of the byte array.
+     * @param index int.
+     * @return byte instance
+     */
+    public byte getByte(int index)
+    {
+        return data.get(index);
+    }
+
+    /**
+     * Provides a character array of 16 characters on availability.
+     * @param lineNumber int. The line number of the characters. Line counting starts from 1.
+     * @return A char array.
+     */
+    public char[] getLineChars(int lineNumber)
+    {
+        int start = (lineNumber-1) * 16;
+        int length = data.size() - start < 16 ? data.size() - start:16;
+        char[] chars = new char[length];
+
+        for (int i = 0; i < chars.length; i++)
+        {
+            char c = Character.toChars(data.get(start) & 0XFF)[0];
+            if (!isAsciiPrintable(c))
+            {
+                c = '.';
+            }
+            chars[i] = c;
+            start++;
+        }
+        return chars;
+    }
+
+    public byte[] getBytesForLine(int lineNumber)
+    {
+        int index = (lineNumber-1) * 16;
+        int length = Math.min(data.size() - index, 16);
+        byte[] bytes = new byte[length];
+
+        for (int i = 0; i < bytes.length; i++)
+        {
+            bytes[i] = data.get(index);
+            index++;
+        }
+        return bytes;
+    }
+
+    /**
+     * Provides the size of the model i.e. size of the input.
+     * @return int value.
+     */
+    public int size()
+    {
+        return data.size();
+    }
+
+    /**
+     *
+     * @return
+     */
+    public int totalLine()
+    {
+        return size() % 16 != 0 ? size()/16 + 1 : size()/16;
+    }
+
+    public static int lineNumber(int index)
+    {
+        int elementNo = index + 1;
+        return elementNo % 16 != 0 ? elementNo/16 + 1 : elementNo/16;
+    }
+
+    public static int elementIndexInLine(int index)
+    {
+        return index%16;
+    }
+
+    private static boolean isAsciiPrintable(char ch)
+    {
+        return ch >= 32 && ch < 127;
+    }
+
+    public void addHexModelChangeListener(HexModelChangeListener listener)
+    {
+        modelChangeListeners.add(listener);
+    }
+
+    public void updateModel(int index, byte value)
+    {
+        if (!data.get(index).equals(value))
+        {
+            data.set(index, value);
+            for (HexModelChangeListener listener: modelChangeListeners)
+            {
+                listener.hexModelChanged(new HexModelChangedEvent(index, HexModelChangedEvent.SINGLE_CHANGE));
+            }
+        }
+    }
+
+    private void fireModelChanged(int index)
+    {
+        for (HexModelChangeListener listener:modelChangeListeners)
+        {
+            listener.hexModelChanged(new HexModelChangedEvent(index, HexModelChangedEvent.SINGLE_CHANGE));
+        }
+    }
+
+    @Override
+    public void hexChanged(HexChangedEvent event)
+    {
+        int index = event.getByteIndex();
+        if (index != -1 && getByte(index) != event.getNewValue())
+        {
+            data.set(index, event.getNewValue());
+        }
+        fireModelChanged(index);
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,26 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ */
+interface HexModelChangeListener
+{
+    void hexModelChanged(HexModelChangedEvent event);
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangeListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java?rev=1705561&view=auto
==============================================================================
--- pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java (added)
+++ pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java Sun Sep 27 18:04:42 2015
@@ -0,0 +1,55 @@
+/*
+ * 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.pdfbox.tools.pdfdebugger.hexviewer;
+
+/**
+ * @author Khyrul Bashar
+ *
+ * HexModelChangedEvent describes the change in the HexModel.
+ */
+class HexModelChangedEvent
+{
+    static final int BULK_CHANGE = 1;
+    static final int SINGLE_CHANGE = 2;
+
+    private final int startIndex;
+    private final int changeType;
+
+    /**
+     * Constructor.
+     *
+     * @param startIndex int. From where changes start.
+     * @param changeType int. Change type if it is only a single change or a bulk change by pasting
+     * or deleting. Though later features are not yet implemented.
+     */
+    HexModelChangedEvent(int startIndex, int changeType)
+    {
+        this.startIndex = startIndex;
+        this.changeType = changeType;
+    }
+
+    int getStartIndex()
+    {
+        return startIndex;
+    }
+
+    int getChangeType()
+    {
+        return changeType;
+    }
+}

Propchange: pdfbox/trunk/debugger/src/main/java/org/apache/pdfbox/tools/pdfdebugger/hexviewer/HexModelChangedEvent.java
------------------------------------------------------------------------------
    svn:eol-style = native