From f8d03d8cd64593fdb24057ce928a07137b57f49f Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 02:33:11 +0100 Subject: Import Typecast r106, http://typecast.dev.java.net/ - Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 --- src/net/java/dev/typecast/ot/Disassembler.java | 109 ++ src/net/java/dev/typecast/ot/Fixed.java | 852 ++++++++++++ src/net/java/dev/typecast/ot/Glyph.java | 159 +++ src/net/java/dev/typecast/ot/Mnemonic.java | 397 ++++++ src/net/java/dev/typecast/ot/OTFont.java | 265 ++++ src/net/java/dev/typecast/ot/OTFontCollection.java | 169 +++ src/net/java/dev/typecast/ot/Point.java | 29 + src/net/java/dev/typecast/ot/mac/ResourceData.java | 45 + src/net/java/dev/typecast/ot/mac/ResourceFile.java | 77 ++ .../java/dev/typecast/ot/mac/ResourceHeader.java | 61 + src/net/java/dev/typecast/ot/mac/ResourceMap.java | 83 ++ .../dev/typecast/ot/mac/ResourceReference.java | 81 ++ src/net/java/dev/typecast/ot/mac/ResourceType.java | 82 ++ src/net/java/dev/typecast/ot/table/BaseTable.java | 436 +++++++ .../dev/typecast/ot/table/CffStandardStrings.java | 424 ++++++ src/net/java/dev/typecast/ot/table/CffTable.java | 620 +++++++++ src/net/java/dev/typecast/ot/table/Charstring.java | 33 + .../dev/typecast/ot/table/CharstringType2.java | 235 ++++ src/net/java/dev/typecast/ot/table/ClassDef.java | 33 + .../dev/typecast/ot/table/ClassDefFormat1.java | 39 + .../dev/typecast/ot/table/ClassDefFormat2.java | 37 + src/net/java/dev/typecast/ot/table/CmapFormat.java | 134 ++ .../java/dev/typecast/ot/table/CmapFormat0.java | 92 ++ .../java/dev/typecast/ot/table/CmapFormat2.java | 173 +++ .../java/dev/typecast/ot/table/CmapFormat4.java | 165 +++ .../java/dev/typecast/ot/table/CmapFormat6.java | 87 ++ .../dev/typecast/ot/table/CmapFormatUnknown.java | 54 + .../java/dev/typecast/ot/table/CmapIndexEntry.java | 117 ++ src/net/java/dev/typecast/ot/table/CmapTable.java | 161 +++ src/net/java/dev/typecast/ot/table/Coverage.java | 83 ++ .../dev/typecast/ot/table/CoverageFormat1.java | 88 ++ .../dev/typecast/ot/table/CoverageFormat2.java | 89 ++ src/net/java/dev/typecast/ot/table/CvtTable.java | 62 + src/net/java/dev/typecast/ot/table/Device.java | 50 + .../java/dev/typecast/ot/table/DirectoryEntry.java | 115 ++ src/net/java/dev/typecast/ot/table/DsigEntry.java | 43 + src/net/java/dev/typecast/ot/table/DsigTable.java | 69 + src/net/java/dev/typecast/ot/table/Feature.java | 85 ++ .../java/dev/typecast/ot/table/FeatureList.java | 118 ++ .../java/dev/typecast/ot/table/FeatureRecord.java | 88 ++ .../java/dev/typecast/ot/table/FeatureTags.java | 63 + src/net/java/dev/typecast/ot/table/FpgmTable.java | 46 + src/net/java/dev/typecast/ot/table/GaspRange.java | 45 + src/net/java/dev/typecast/ot/table/GaspTable.java | 63 + .../dev/typecast/ot/table/GlyfCompositeComp.java | 200 +++ .../typecast/ot/table/GlyfCompositeDescript.java | 202 +++ .../java/dev/typecast/ot/table/GlyfDescript.java | 124 ++ .../dev/typecast/ot/table/GlyfSimpleDescript.java | 245 ++++ src/net/java/dev/typecast/ot/table/GlyfTable.java | 132 ++ .../dev/typecast/ot/table/GlyphDescription.java | 86 ++ src/net/java/dev/typecast/ot/table/GposTable.java | 66 + src/net/java/dev/typecast/ot/table/GsubTable.java | 181 +++ src/net/java/dev/typecast/ot/table/HdmxTable.java | 117 ++ src/net/java/dev/typecast/ot/table/HeadTable.java | 205 +++ src/net/java/dev/typecast/ot/table/HheaTable.java | 135 ++ src/net/java/dev/typecast/ot/table/HmtxTable.java | 141 ++ src/net/java/dev/typecast/ot/table/ID.java | 399 ++++++ .../java/dev/typecast/ot/table/KernSubtable.java | 49 + .../dev/typecast/ot/table/KernSubtableFormat0.java | 47 + .../dev/typecast/ot/table/KernSubtableFormat2.java | 42 + src/net/java/dev/typecast/ot/table/KernTable.java | 62 + .../java/dev/typecast/ot/table/KerningPair.java | 44 + src/net/java/dev/typecast/ot/table/LangSys.java | 105 ++ .../java/dev/typecast/ot/table/LangSysRecord.java | 88 ++ src/net/java/dev/typecast/ot/table/Ligature.java | 85 ++ .../java/dev/typecast/ot/table/LigatureSet.java | 85 ++ .../java/dev/typecast/ot/table/LigatureSubst.java | 73 ++ .../typecast/ot/table/LigatureSubstFormat1.java | 95 ++ src/net/java/dev/typecast/ot/table/LocaTable.java | 77 ++ src/net/java/dev/typecast/ot/table/Lookup.java | 110 ++ src/net/java/dev/typecast/ot/table/LookupList.java | 108 ++ .../java/dev/typecast/ot/table/LookupSubtable.java | 60 + .../typecast/ot/table/LookupSubtableFactory.java | 64 + src/net/java/dev/typecast/ot/table/LtshTable.java | 68 + src/net/java/dev/typecast/ot/table/MaxpTable.java | 162 +++ src/net/java/dev/typecast/ot/table/NameRecord.java | 145 +++ src/net/java/dev/typecast/ot/table/NameTable.java | 131 ++ src/net/java/dev/typecast/ot/table/Os2Table.java | 358 ++++++ src/net/java/dev/typecast/ot/table/Panose.java | 96 ++ src/net/java/dev/typecast/ot/table/PcltTable.java | 105 ++ src/net/java/dev/typecast/ot/table/PostTable.java | 422 ++++++ src/net/java/dev/typecast/ot/table/PrepTable.java | 46 + src/net/java/dev/typecast/ot/table/Program.java | 41 + .../java/dev/typecast/ot/table/RangeRecord.java | 87 ++ src/net/java/dev/typecast/ot/table/Script.java | 118 ++ src/net/java/dev/typecast/ot/table/ScriptList.java | 115 ++ .../java/dev/typecast/ot/table/ScriptRecord.java | 88 ++ src/net/java/dev/typecast/ot/table/ScriptTags.java | 61 + .../java/dev/typecast/ot/table/SignatureBlock.java | 46 + .../java/dev/typecast/ot/table/SingleSubst.java | 81 ++ .../dev/typecast/ot/table/SingleSubstFormat1.java | 92 ++ .../dev/typecast/ot/table/SingleSubstFormat2.java | 97 ++ src/net/java/dev/typecast/ot/table/TTCHeader.java | 59 + src/net/java/dev/typecast/ot/table/Table.java | 67 + .../java/dev/typecast/ot/table/TableDirectory.java | 129 ++ .../java/dev/typecast/ot/table/TableException.java | 46 + .../java/dev/typecast/ot/table/TableFactory.java | 185 +++ src/net/java/dev/typecast/ot/table/VdmxTable.java | 197 +++ src/net/java/dev/typecast/ot/table/VheaTable.java | 147 +++ src/net/java/dev/typecast/ot/table/VmtxTable.java | 112 ++ src/net/java/dev/typecast/t2/T2Interpreter.java | 1043 +++++++++++++++ src/net/java/dev/typecast/t2/T2Mnemonic.java | 86 ++ .../java/dev/typecast/tt/engine/GraphicsState.java | 50 + .../java/dev/typecast/tt/engine/Interpreter.java | 1357 ++++++++++++++++++++ src/net/java/dev/typecast/tt/engine/Parser.java | 192 +++ 105 files changed, 15812 insertions(+) create mode 100644 src/net/java/dev/typecast/ot/Disassembler.java create mode 100644 src/net/java/dev/typecast/ot/Fixed.java create mode 100644 src/net/java/dev/typecast/ot/Glyph.java create mode 100644 src/net/java/dev/typecast/ot/Mnemonic.java create mode 100644 src/net/java/dev/typecast/ot/OTFont.java create mode 100644 src/net/java/dev/typecast/ot/OTFontCollection.java create mode 100644 src/net/java/dev/typecast/ot/Point.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceData.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceFile.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceHeader.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceMap.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceReference.java create mode 100644 src/net/java/dev/typecast/ot/mac/ResourceType.java create mode 100644 src/net/java/dev/typecast/ot/table/BaseTable.java create mode 100644 src/net/java/dev/typecast/ot/table/CffStandardStrings.java create mode 100644 src/net/java/dev/typecast/ot/table/CffTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Charstring.java create mode 100644 src/net/java/dev/typecast/ot/table/CharstringType2.java create mode 100644 src/net/java/dev/typecast/ot/table/ClassDef.java create mode 100644 src/net/java/dev/typecast/ot/table/ClassDefFormat1.java create mode 100644 src/net/java/dev/typecast/ot/table/ClassDefFormat2.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormat.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormat0.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormat2.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormat4.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormat6.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapIndexEntry.java create mode 100644 src/net/java/dev/typecast/ot/table/CmapTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Coverage.java create mode 100644 src/net/java/dev/typecast/ot/table/CoverageFormat1.java create mode 100644 src/net/java/dev/typecast/ot/table/CoverageFormat2.java create mode 100644 src/net/java/dev/typecast/ot/table/CvtTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Device.java create mode 100644 src/net/java/dev/typecast/ot/table/DirectoryEntry.java create mode 100644 src/net/java/dev/typecast/ot/table/DsigEntry.java create mode 100644 src/net/java/dev/typecast/ot/table/DsigTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Feature.java create mode 100644 src/net/java/dev/typecast/ot/table/FeatureList.java create mode 100644 src/net/java/dev/typecast/ot/table/FeatureRecord.java create mode 100644 src/net/java/dev/typecast/ot/table/FeatureTags.java create mode 100644 src/net/java/dev/typecast/ot/table/FpgmTable.java create mode 100644 src/net/java/dev/typecast/ot/table/GaspRange.java create mode 100644 src/net/java/dev/typecast/ot/table/GaspTable.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyfDescript.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyfTable.java create mode 100644 src/net/java/dev/typecast/ot/table/GlyphDescription.java create mode 100644 src/net/java/dev/typecast/ot/table/GposTable.java create mode 100644 src/net/java/dev/typecast/ot/table/GsubTable.java create mode 100644 src/net/java/dev/typecast/ot/table/HdmxTable.java create mode 100644 src/net/java/dev/typecast/ot/table/HeadTable.java create mode 100644 src/net/java/dev/typecast/ot/table/HheaTable.java create mode 100644 src/net/java/dev/typecast/ot/table/HmtxTable.java create mode 100644 src/net/java/dev/typecast/ot/table/ID.java create mode 100644 src/net/java/dev/typecast/ot/table/KernSubtable.java create mode 100644 src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java create mode 100644 src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java create mode 100644 src/net/java/dev/typecast/ot/table/KernTable.java create mode 100644 src/net/java/dev/typecast/ot/table/KerningPair.java create mode 100644 src/net/java/dev/typecast/ot/table/LangSys.java create mode 100644 src/net/java/dev/typecast/ot/table/LangSysRecord.java create mode 100644 src/net/java/dev/typecast/ot/table/Ligature.java create mode 100644 src/net/java/dev/typecast/ot/table/LigatureSet.java create mode 100644 src/net/java/dev/typecast/ot/table/LigatureSubst.java create mode 100644 src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java create mode 100644 src/net/java/dev/typecast/ot/table/LocaTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Lookup.java create mode 100644 src/net/java/dev/typecast/ot/table/LookupList.java create mode 100644 src/net/java/dev/typecast/ot/table/LookupSubtable.java create mode 100644 src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java create mode 100644 src/net/java/dev/typecast/ot/table/LtshTable.java create mode 100644 src/net/java/dev/typecast/ot/table/MaxpTable.java create mode 100644 src/net/java/dev/typecast/ot/table/NameRecord.java create mode 100644 src/net/java/dev/typecast/ot/table/NameTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Os2Table.java create mode 100644 src/net/java/dev/typecast/ot/table/Panose.java create mode 100644 src/net/java/dev/typecast/ot/table/PcltTable.java create mode 100644 src/net/java/dev/typecast/ot/table/PostTable.java create mode 100644 src/net/java/dev/typecast/ot/table/PrepTable.java create mode 100644 src/net/java/dev/typecast/ot/table/Program.java create mode 100644 src/net/java/dev/typecast/ot/table/RangeRecord.java create mode 100644 src/net/java/dev/typecast/ot/table/Script.java create mode 100644 src/net/java/dev/typecast/ot/table/ScriptList.java create mode 100644 src/net/java/dev/typecast/ot/table/ScriptRecord.java create mode 100644 src/net/java/dev/typecast/ot/table/ScriptTags.java create mode 100644 src/net/java/dev/typecast/ot/table/SignatureBlock.java create mode 100644 src/net/java/dev/typecast/ot/table/SingleSubst.java create mode 100644 src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java create mode 100644 src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java create mode 100644 src/net/java/dev/typecast/ot/table/TTCHeader.java create mode 100644 src/net/java/dev/typecast/ot/table/Table.java create mode 100644 src/net/java/dev/typecast/ot/table/TableDirectory.java create mode 100644 src/net/java/dev/typecast/ot/table/TableException.java create mode 100644 src/net/java/dev/typecast/ot/table/TableFactory.java create mode 100644 src/net/java/dev/typecast/ot/table/VdmxTable.java create mode 100644 src/net/java/dev/typecast/ot/table/VheaTable.java create mode 100644 src/net/java/dev/typecast/ot/table/VmtxTable.java create mode 100644 src/net/java/dev/typecast/t2/T2Interpreter.java create mode 100644 src/net/java/dev/typecast/t2/T2Mnemonic.java create mode 100644 src/net/java/dev/typecast/tt/engine/GraphicsState.java create mode 100644 src/net/java/dev/typecast/tt/engine/Interpreter.java create mode 100644 src/net/java/dev/typecast/tt/engine/Parser.java diff --git a/src/net/java/dev/typecast/ot/Disassembler.java b/src/net/java/dev/typecast/ot/Disassembler.java new file mode 100644 index 000000000..73e75cc39 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Disassembler.java @@ -0,0 +1,109 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * @author David Schweinsberg + * @version $Id: Disassembler.java,v 1.1.1.1 2004-12-05 23:14:25 davidsch Exp $ + */ +public class Disassembler { + + /** + * Advance the instruction pointer to the next executable opcode. + * This will be the next byte, unless the current opcode is a push + * instruction, in which case it will be the byte immediately beyond + * the last data byte. + * @param ip The current instruction pointer + * @return The new instruction pointer + */ + public static int advanceIP(short[] instructions, int ip) { + + // The high word specifies font, cvt, or glyph program + int i = ip & 0xffff; + int dataCount; + ip++; + if (Mnemonic.NPUSHB == instructions[i]) { + // Next byte is the data byte count + dataCount = instructions[++i]; + ip += dataCount + 1; + } else if (Mnemonic.NPUSHW == instructions[i]) { + // Next byte is the data word count + dataCount = instructions[++i]; + ip += dataCount*2 + 1; + } else if (Mnemonic.PUSHB == (instructions[i] & 0xf8)) { + dataCount = (short)((instructions[i] & 0x07) + 1); + ip += dataCount; + } else if (Mnemonic.PUSHW == (instructions[i] & 0xf8)) { + dataCount = (short)((instructions[i] & 0x07) + 1); + ip += dataCount*2; + } + return ip; + } + + public static short getPushCount(short[] instructions, int ip) { + short instr = instructions[ip & 0xffff]; + if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) { + return instructions[(ip & 0xffff) + 1]; + } else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) { + return (short)((instr & 0x07) + 1); + } + return 0; + } + + public static int[] getPushData(short[] instructions, int ip) { + int count = getPushCount(instructions, ip); + int[] data = new int[count]; + int i = ip & 0xffff; + short instr = instructions[i]; + if (Mnemonic.NPUSHB == instr) { + for (int j = 0; j < count; j++) { + data[j] = instructions[i + j + 2]; + } + } else if (Mnemonic.PUSHB == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = instructions[i + j + 1]; + } + } else if (Mnemonic.NPUSHW == instr) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[i + j*2 + 2] << 8) | instructions[i + j*2 + 3]; + } + } else if (Mnemonic.PUSHW == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[i + j*2 + 1] << 8) | instructions[i + j*2 + 2]; + } + } + return data; + } + + public static String disassemble(short[] instructions, int leadingSpaces) { + StringBuffer sb = new StringBuffer(); + int ip = 0; + while (ip < instructions.length) { + for (int i = 0; i < leadingSpaces; i++) { + sb.append(" "); + } + sb.append(ip).append(": "); + sb.append(Mnemonic.getMnemonic(instructions[ip])); + if (getPushCount(instructions, ip) > 0) { + int[] data = getPushData(instructions, ip); + for(int j = 0; j < data.length; j++) { + if ((instructions[ip] == Mnemonic.PUSHW) || + (instructions[ip] == Mnemonic.NPUSHW)) { + sb.append(" ").append((short) data[j]); + } else { + sb.append(" ").append(data[j]); + } + } + } + sb.append("\n"); + ip = advanceIP(instructions, ip); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/Fixed.java b/src/net/java/dev/typecast/ot/Fixed.java new file mode 100644 index 000000000..6f83e922c --- /dev/null +++ b/src/net/java/dev/typecast/ot/Fixed.java @@ -0,0 +1,852 @@ +/* + * $Id: Fixed.java,v 1.1.1.1 2004-12-05 23:14:26 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot; + +/** + * Functions for working with signed 16.16 fixed values + * @author David Schweinsberg + * @version $Id: Fixed.java,v 1.1.1.1 2004-12-05 23:14:26 davidsch Exp $ + */ +public class Fixed { + + // Tangent LUT + static private int[] t = { + 0x0, + 0x1, + 0x3, + 0x4, + 0x6, + 0x7, + 0x9, + 0xb, + 0xc, + 0xe, + 0xf, + 0x11, + 0x12, + 0x14, + 0x16, + 0x17, + 0x19, + 0x1a, + 0x1c, + 0x1d, + 0x1f, + 0x21, + 0x22, + 0x24, + 0x25, + 0x27, + 0x29, + 0x2a, + 0x2c, + 0x2e, + 0x2f, + 0x31, + 0x32, + 0x34, + 0x36, + 0x37, + 0x39, + 0x3b, + 0x3c, + 0x3e, + 0x40, + 0x41, + 0x43, + 0x45, + 0x46, + 0x48, + 0x4a, + 0x4b, + 0x4d, + 0x4f, + 0x51, + 0x52, + 0x54, + 0x56, + 0x58, + 0x59, + 0x5b, + 0x5d, + 0x5f, + 0x60, + 0x62, + 0x64, + 0x66, + 0x68, + 0x6a, + 0x6b, + 0x6d, + 0x6f, + 0x71, + 0x73, + 0x75, + 0x77, + 0x79, + 0x7b, + 0x7c, + 0x7e, + 0x80, + 0x82, + 0x84, + 0x86, + 0x88, + 0x8a, + 0x8c, + 0x8e, + 0x91, + 0x93, + 0x95, + 0x97, + 0x99, + 0x9b, + 0x9d, + 0x9f, + 0xa2, + 0xa4, + 0xa6, + 0xa8, + 0xab, + 0xad, + 0xaf, + 0xb1, + 0xb4, + 0xb6, + 0xb9, + 0xbb, + 0xbd, + 0xc0, + 0xc2, + 0xc5, + 0xc7, + 0xca, + 0xcc, + 0xcf, + 0xd2, + 0xd4, + 0xd7, + 0xda, + 0xdc, + 0xdf, + 0xe2, + 0xe5, + 0xe8, + 0xea, + 0xed, + 0xf0, + 0xf3, + 0xf6, + 0xf9, + 0xfc, + 0x100, + 0x103, + 0x106, + 0x109, + 0x10c, + 0x110, + 0x113, + 0x116, + 0x11a, + 0x11d, + 0x121, + 0x125, + 0x128, + 0x12c, + 0x130, + 0x134, + 0x137, + 0x13b, + 0x13f, + 0x143, + 0x148, + 0x14c, + 0x150, + 0x154, + 0x159, + 0x15d, + 0x162, + 0x166, + 0x16b, + 0x170, + 0x175, + 0x17a, + 0x17f, + 0x184, + 0x189, + 0x18e, + 0x194, + 0x199, + 0x19f, + 0x1a5, + 0x1ab, + 0x1b1, + 0x1b7, + 0x1bd, + 0x1c3, + 0x1ca, + 0x1d1, + 0x1d7, + 0x1de, + 0x1e6, + 0x1ed, + 0x1f4, + 0x1fc, + 0x204, + 0x20c, + 0x214, + 0x21d, + 0x225, + 0x22e, + 0x238, + 0x241, + 0x24b, + 0x255, + 0x25f, + 0x26a, + 0x274, + 0x280, + 0x28b, + 0x297, + 0x2a3, + 0x2b0, + 0x2bd, + 0x2cb, + 0x2d9, + 0x2e8, + 0x2f7, + 0x306, + 0x317, + 0x328, + 0x339, + 0x34b, + 0x35e, + 0x372, + 0x387, + 0x39d, + 0x3b3, + 0x3cb, + 0x3e4, + 0x3fe, + 0x419, + 0x435, + 0x454, + 0x474, + 0x495, + 0x4b9, + 0x4de, + 0x506, + 0x531, + 0x55e, + 0x58f, + 0x5c3, + 0x5fb, + 0x637, + 0x677, + 0x6bd, + 0x709, + 0x75c, + 0x7b7, + 0x81b, + 0x889, + 0x904, + 0x98d, + 0xa27, + 0xad5, + 0xb9c, + 0xc82, + 0xd8e, + 0xecb, + 0x1046, + 0x1217, + 0x145a, + 0x1744, + 0x1b26, + 0x2095, + 0x28bc, + 0x3651, + 0x517b, + 0xa2f8 + }; + + // Sine LUT + static private int[] s = { + 0x0, + 0x1, + 0x3, + 0x4, + 0x6, + 0x7, + 0x9, + 0xa, + 0xc, + 0xe, + 0xf, + 0x11, + 0x12, + 0x14, + 0x15, + 0x17, + 0x19, + 0x1a, + 0x1c, + 0x1d, + 0x1f, + 0x20, + 0x22, + 0x24, + 0x25, + 0x27, + 0x28, + 0x2a, + 0x2b, + 0x2d, + 0x2e, + 0x30, + 0x31, + 0x33, + 0x35, + 0x36, + 0x38, + 0x39, + 0x3b, + 0x3c, + 0x3e, + 0x3f, + 0x41, + 0x42, + 0x44, + 0x45, + 0x47, + 0x48, + 0x4a, + 0x4b, + 0x4d, + 0x4e, + 0x50, + 0x51, + 0x53, + 0x54, + 0x56, + 0x57, + 0x59, + 0x5a, + 0x5c, + 0x5d, + 0x5f, + 0x60, + 0x61, + 0x63, + 0x64, + 0x66, + 0x67, + 0x69, + 0x6a, + 0x6c, + 0x6d, + 0x6e, + 0x70, + 0x71, + 0x73, + 0x74, + 0x75, + 0x77, + 0x78, + 0x7a, + 0x7b, + 0x7c, + 0x7e, + 0x7f, + 0x80, + 0x82, + 0x83, + 0x84, + 0x86, + 0x87, + 0x88, + 0x8a, + 0x8b, + 0x8c, + 0x8e, + 0x8f, + 0x90, + 0x92, + 0x93, + 0x94, + 0x95, + 0x97, + 0x98, + 0x99, + 0x9b, + 0x9c, + 0x9d, + 0x9e, + 0x9f, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + 0xa6, + 0xa7, + 0xa8, + 0xa9, + 0xaa, + 0xab, + 0xad, + 0xae, + 0xaf, + 0xb0, + 0xb1, + 0xb2, + 0xb3, + 0xb5, + 0xb6, + 0xb7, + 0xb8, + 0xb9, + 0xba, + 0xbb, + 0xbc, + 0xbd, + 0xbe, + 0xbf, + 0xc0, + 0xc1, + 0xc2, + 0xc3, + 0xc4, + 0xc5, + 0xc6, + 0xc7, + 0xc8, + 0xc9, + 0xca, + 0xcb, + 0xcc, + 0xcd, + 0xce, + 0xcf, + 0xd0, + 0xd1, + 0xd2, + 0xd3, + 0xd3, + 0xd4, + 0xd5, + 0xd6, + 0xd7, + 0xd8, + 0xd9, + 0xd9, + 0xda, + 0xdb, + 0xdc, + 0xdd, + 0xdd, + 0xde, + 0xdf, + 0xe0, + 0xe1, + 0xe1, + 0xe2, + 0xe3, + 0xe3, + 0xe4, + 0xe5, + 0xe6, + 0xe6, + 0xe7, + 0xe8, + 0xe8, + 0xe9, + 0xea, + 0xea, + 0xeb, + 0xeb, + 0xec, + 0xed, + 0xed, + 0xee, + 0xee, + 0xef, + 0xef, + 0xf0, + 0xf1, + 0xf1, + 0xf2, + 0xf2, + 0xf3, + 0xf3, + 0xf4, + 0xf4, + 0xf4, + 0xf5, + 0xf5, + 0xf6, + 0xf6, + 0xf7, + 0xf7, + 0xf7, + 0xf8, + 0xf8, + 0xf9, + 0xf9, + 0xf9, + 0xfa, + 0xfa, + 0xfa, + 0xfb, + 0xfb, + 0xfb, + 0xfb, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfd, + 0xfd, + 0xfd, + 0xfd, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff + }; + + // Cosine LUT + static private int[] c = { + 0x100, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfd, + 0xfd, + 0xfd, + 0xfd, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfb, + 0xfb, + 0xfb, + 0xfb, + 0xfa, + 0xfa, + 0xfa, + 0xf9, + 0xf9, + 0xf9, + 0xf8, + 0xf8, + 0xf7, + 0xf7, + 0xf7, + 0xf6, + 0xf6, + 0xf5, + 0xf5, + 0xf4, + 0xf4, + 0xf4, + 0xf3, + 0xf3, + 0xf2, + 0xf2, + 0xf1, + 0xf1, + 0xf0, + 0xef, + 0xef, + 0xee, + 0xee, + 0xed, + 0xed, + 0xec, + 0xeb, + 0xeb, + 0xea, + 0xea, + 0xe9, + 0xe8, + 0xe8, + 0xe7, + 0xe6, + 0xe6, + 0xe5, + 0xe4, + 0xe3, + 0xe3, + 0xe2, + 0xe1, + 0xe1, + 0xe0, + 0xdf, + 0xde, + 0xdd, + 0xdd, + 0xdc, + 0xdb, + 0xda, + 0xd9, + 0xd9, + 0xd8, + 0xd7, + 0xd6, + 0xd5, + 0xd4, + 0xd3, + 0xd3, + 0xd2, + 0xd1, + 0xd0, + 0xcf, + 0xce, + 0xcd, + 0xcc, + 0xcb, + 0xca, + 0xc9, + 0xc8, + 0xc7, + 0xc6, + 0xc5, + 0xc4, + 0xc3, + 0xc2, + 0xc1, + 0xc0, + 0xbf, + 0xbe, + 0xbd, + 0xbc, + 0xbb, + 0xba, + 0xb9, + 0xb8, + 0xb7, + 0xb6, + 0xb5, + 0xb3, + 0xb2, + 0xb1, + 0xb0, + 0xaf, + 0xae, + 0xad, + 0xab, + 0xaa, + 0xa9, + 0xa8, + 0xa7, + 0xa6, + 0xa4, + 0xa3, + 0xa2, + 0xa1, + 0x9f, + 0x9e, + 0x9d, + 0x9c, + 0x9b, + 0x99, + 0x98, + 0x97, + 0x95, + 0x94, + 0x93, + 0x92, + 0x90, + 0x8f, + 0x8e, + 0x8c, + 0x8b, + 0x8a, + 0x88, + 0x87, + 0x86, + 0x84, + 0x83, + 0x82, + 0x80, + 0x7f, + 0x7e, + 0x7c, + 0x7b, + 0x7a, + 0x78, + 0x77, + 0x75, + 0x74, + 0x73, + 0x71, + 0x70, + 0x6e, + 0x6d, + 0x6c, + 0x6a, + 0x69, + 0x67, + 0x66, + 0x64, + 0x63, + 0x61, + 0x60, + 0x5f, + 0x5d, + 0x5c, + 0x5a, + 0x59, + 0x57, + 0x56, + 0x54, + 0x53, + 0x51, + 0x50, + 0x4e, + 0x4d, + 0x4b, + 0x4a, + 0x48, + 0x47, + 0x45, + 0x44, + 0x42, + 0x41, + 0x3f, + 0x3e, + 0x3c, + 0x3b, + 0x39, + 0x38, + 0x36, + 0x35, + 0x33, + 0x31, + 0x30, + 0x2e, + 0x2d, + 0x2b, + 0x2a, + 0x28, + 0x27, + 0x25, + 0x24, + 0x22, + 0x20, + 0x1f, + 0x1d, + 0x1c, + 0x1a, + 0x19, + 0x17, + 0x15, + 0x14, + 0x12, + 0x11, + 0xf, + 0xe, + 0xc, + 0xa, + 0x9, + 0x7, + 0x6, + 0x4, + 0x3, + 0x1 + }; + + /** + * Yet to be implemented. + * @param num Input + * @return Output + */ + public static int arctan( int num ) { + return 0; + } + + /** + * 26.6 fixed number square root function. + * Simple (brain-dead) divide & conqure algorithm. + * @param num The 26.6 fixed number in question + * @return The resulting square root + */ + public static int squareRoot(int num) { + int n = num; + int divisor = num; + int nSquared; + + while (divisor != 0) { + divisor /= 2; + nSquared = (n * n) >> 6; + if (nSquared == num) { + break; + } else if (nSquared > num) { + n -= divisor; + } else { + n += divisor; + } + } + return n; + } + + public static float floatValue(long fixed) { + return (fixed >> 16) + (float)(fixed & 0xffff) / 0x10000; + } + + public static float roundedFloatValue(long fixed, int decimalPlaces) { + int factor = 10 * decimalPlaces; + return (float)((int)(floatValue(fixed) * factor)) / factor; + } +} diff --git a/src/net/java/dev/typecast/ot/Glyph.java b/src/net/java/dev/typecast/ot/Glyph.java new file mode 100644 index 000000000..a59d62684 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Glyph.java @@ -0,0 +1,159 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot; + +import net.java.dev.typecast.ot.table.GlyphDescription; +import net.java.dev.typecast.ot.table.GlyfDescript; +import net.java.dev.typecast.ot.table.Charstring; +import net.java.dev.typecast.ot.table.CharstringType2; + +import net.java.dev.typecast.t2.T2Interpreter; + +/** + * An individual glyph within a font. + * @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $ + * @author David Schweinsberg + */ +public class Glyph { + + protected short _leftSideBearing; + protected int _advanceWidth; + private Point[] _points; + + /** + * Construct a Glyph from a TrueType outline described by + * a GlyphDescription. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public Glyph(GlyphDescription gd, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + describe(gd); + } + + /** + * Construct a Glyph from a PostScript outline described by a Charstring. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public Glyph(Charstring cs, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + if (cs instanceof CharstringType2) { + T2Interpreter t2i = new T2Interpreter(); + _points = t2i.execute((CharstringType2) cs); + } else { + //throw unsupported charstring type + } + } + + public int getAdvanceWidth() { + return _advanceWidth; + } + + public short getLeftSideBearing() { + return _leftSideBearing; + } + + public Point getPoint(int i) { + return _points[i]; + } + + public int getPointCount() { + return _points.length; + } + + /** + * Resets the glyph to the TrueType table settings + */ + public void reset() { + } + + /** + * @param factor a 16.16 fixed value + */ + public void scale(int factor) { + for (int i = 0; i < _points.length; i++) { + //points[i].x = ( points[i].x * factor ) >> 6; + //points[i].y = ( points[i].y * factor ) >> 6; + _points[i].x = ((_points[i].x<<10) * factor) >> 26; + _points[i].y = ((_points[i].y<<10) * factor) >> 26; + } + _leftSideBearing = (short)(( _leftSideBearing * factor) >> 6); + _advanceWidth = (_advanceWidth * factor) >> 6; + } + + /** + * Set the points of a glyph from the GlyphDescription + */ + private void describe(GlyphDescription gd) { + int endPtIndex = 0; + _points = new Point[gd.getPointCount() + 2]; + for (int i = 0; i < gd.getPointCount(); i++) { + boolean endPt = gd.getEndPtOfContours(endPtIndex) == i; + if (endPt) { + endPtIndex++; + } + _points[i] = new Point( + gd.getXCoordinate(i), + gd.getYCoordinate(i), + (gd.getFlags(i) & GlyfDescript.onCurve) != 0, + endPt); + } + + // Append the origin and advanceWidth points (n & n+1) + _points[gd.getPointCount()] = new Point(0, 0, true, true); + _points[gd.getPointCount()+1] = new Point(_advanceWidth, 0, true, true); + } +} diff --git a/src/net/java/dev/typecast/ot/Mnemonic.java b/src/net/java/dev/typecast/ot/Mnemonic.java new file mode 100644 index 000000000..5655c1e86 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Mnemonic.java @@ -0,0 +1,397 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * The Mnemonic representations of the TrueType instruction set. + * @author David Schweinsberg + * @version $Id: Mnemonic.java,v 1.1.1.1 2004-12-05 23:14:30 davidsch Exp $ + */ +public class Mnemonic { + + public static final short SVTCA = 0x00; // [a] + public static final short SPVTCA = 0x02; // [a] + public static final short SFVTCA = 0x04; // [a] + public static final short SPVTL = 0x06; // [a] + public static final short SFVTL = 0x08; // [a] + public static final short SPVFS = 0x0A; + public static final short SFVFS = 0x0B; + public static final short GPV = 0x0C; + public static final short GFV = 0x0D; + public static final short SFVTPV = 0x0E; + public static final short ISECT = 0x0F; + public static final short SRP0 = 0x10; + public static final short SRP1 = 0x11; + public static final short SRP2 = 0x12; + public static final short SZP0 = 0x13; + public static final short SZP1 = 0x14; + public static final short SZP2 = 0x15; + public static final short SZPS = 0x16; + public static final short SLOOP = 0x17; + public static final short RTG = 0x18; + public static final short RTHG = 0x19; + public static final short SMD = 0x1A; + public static final short ELSE = 0x1B; + public static final short JMPR = 0x1C; + public static final short SCVTCI = 0x1D; + public static final short SSWCI = 0x1E; + public static final short SSW = 0x1F; + public static final short DUP = 0x20; + public static final short POP = 0x21; + public static final short CLEAR = 0x22; + public static final short SWAP = 0x23; + public static final short DEPTH = 0x24; + public static final short CINDEX = 0x25; + public static final short MINDEX = 0x26; + public static final short ALIGNPTS = 0x27; + public static final short UTP = 0x29; + public static final short LOOPCALL = 0x2A; + public static final short CALL = 0x2B; + public static final short FDEF = 0x2C; + public static final short ENDF = 0x2D; + public static final short MDAP = 0x2E; // [a] + public static final short IUP = 0x30; // [a] + public static final short SHP = 0x32; + public static final short SHC = 0x34; // [a] + public static final short SHZ = 0x36; // [a] + public static final short SHPIX = 0x38; + public static final short IP = 0x39; + public static final short MSIRP = 0x3A; // [a] + public static final short ALIGNRP = 0x3C; + public static final short RTDG = 0x3D; + public static final short MIAP = 0x3E; // [a] + public static final short NPUSHB = 0x40; + public static final short NPUSHW = 0x41; + public static final short WS = 0x42; + public static final short RS = 0x43; + public static final short WCVTP = 0x44; + public static final short RCVT = 0x45; + public static final short GC = 0x46; // [a] + public static final short SCFS = 0x48; + public static final short MD = 0x49; // [a] + public static final short MPPEM = 0x4B; + public static final short MPS = 0x4C; + public static final short FLIPON = 0x4D; + public static final short FLIPOFF = 0x4E; + public static final short DEBUG = 0x4F; + public static final short LT = 0x50; + public static final short LTEQ = 0x51; + public static final short GT = 0x52; + public static final short GTEQ = 0x53; + public static final short EQ = 0x54; + public static final short NEQ = 0x55; + public static final short ODD = 0x56; + public static final short EVEN = 0x57; + public static final short IF = 0x58; + public static final short EIF = 0x59; + public static final short AND = 0x5A; + public static final short OR = 0x5B; + public static final short NOT = 0x5C; + public static final short DELTAP1 = 0x5D; + public static final short SDB = 0x5E; + public static final short SDS = 0x5F; + public static final short ADD = 0x60; + public static final short SUB = 0x61; + public static final short DIV = 0x62; + public static final short MUL = 0x63; + public static final short ABS = 0x64; + public static final short NEG = 0x65; + public static final short FLOOR = 0x66; + public static final short CEILING = 0x67; + public static final short ROUND = 0x68; // [ab] + public static final short NROUND = 0x6C; // [ab] + public static final short WCVTF = 0x70; + public static final short DELTAP2 = 0x71; + public static final short DELTAP3 = 0x72; + public static final short DELTAC1 = 0x73; + public static final short DELTAC2 = 0x74; + public static final short DELTAC3 = 0x75; + public static final short SROUND = 0x76; + public static final short S45ROUND = 0x77; + public static final short JROT = 0x78; + public static final short JROF = 0x79; + public static final short ROFF = 0x7A; + public static final short RUTG = 0x7C; + public static final short RDTG = 0x7D; + public static final short SANGW = 0x7E; + public static final short AA = 0x7F; + public static final short FLIPPT = 0x80; + public static final short FLIPRGON = 0x81; + public static final short FLIPRGOFF = 0x82; + public static final short SCANCTRL = 0x85; + public static final short SDPVTL = 0x86; // [a] + public static final short GETINFO = 0x88; + public static final short IDEF = 0x89; + public static final short ROLL = 0x8A; + public static final short MAX = 0x8B; + public static final short MIN = 0x8C; + public static final short SCANTYPE = 0x8D; + public static final short INSTCTRL = 0x8E; + public static final short PUSHB = 0xB0; // [abc] + public static final short PUSHW = 0xB8; // [abc] + public static final short MDRP = 0xC0; // [abcde] + public static final short MIRP = 0xE0; // [abcde] + + /** + * Gets the mnemonic text for the specified opcode + * @param opcode The opcode for which the mnemonic is required + * @return The mnemonic, with a description + */ + public static String getMnemonic(short opcode) { + if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]"; + else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]"; + else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]"; + else if (opcode >= PUSHB) return "PUSHB["+((opcode&7)+1)+"]"; + else if (opcode >= INSTCTRL) return "INSTCTRL"; + else if (opcode >= SCANTYPE) return "SCANTYPE"; + else if (opcode >= MIN) return "MIN"; + else if (opcode >= MAX) return "MAX"; + else if (opcode >= ROLL) return "ROLL"; + else if (opcode >= IDEF) return "IDEF"; + else if (opcode >= GETINFO) return "GETINFO"; + else if (opcode >= SDPVTL) return "SDPVTL["+(opcode&1)+"]"; + else if (opcode >= SCANCTRL) return "SCANCTRL"; + else if (opcode >= FLIPRGOFF) return "FLIPRGOFF"; + else if (opcode >= FLIPRGON) return "FLIPRGON"; + else if (opcode >= FLIPPT) return "FLIPPT"; + else if (opcode >= AA) return "AA"; + else if (opcode >= SANGW) return "SANGW"; + else if (opcode >= RDTG) return "RDTG"; + else if (opcode >= RUTG) return "RUTG"; + else if (opcode >= ROFF) return "ROFF"; + else if (opcode >= JROF) return "JROF"; + else if (opcode >= JROT) return "JROT"; + else if (opcode >= S45ROUND) return "S45ROUND"; + else if (opcode >= SROUND) return "SROUND"; + else if (opcode >= DELTAC3) return "DELTAC3"; + else if (opcode >= DELTAC2) return "DELTAC2"; + else if (opcode >= DELTAC1) return "DELTAC1"; + else if (opcode >= DELTAP3) return "DELTAP3"; + else if (opcode >= DELTAP2) return "DELTAP2"; + else if (opcode >= WCVTF) return "WCVTF"; + else if (opcode >= NROUND) return "NROUND["+(opcode&3)+"]"; + else if (opcode >= ROUND) return "ROUND["+(opcode&3)+"]"; + else if (opcode >= CEILING) return "CEILING"; + else if (opcode >= FLOOR) return "FLOOR"; + else if (opcode >= NEG) return "NEG"; + else if (opcode >= ABS) return "ABS"; + else if (opcode >= MUL) return "MUL"; + else if (opcode >= DIV) return "DIV"; + else if (opcode >= SUB) return "SUB"; + else if (opcode >= ADD) return "ADD"; + else if (opcode >= SDS) return "SDS"; + else if (opcode >= SDB) return "SDB"; + else if (opcode >= DELTAP1) return "DELTAP1"; + else if (opcode >= NOT) return "NOT"; + else if (opcode >= OR) return "OR"; + else if (opcode >= AND) return "AND"; + else if (opcode >= EIF) return "EIF"; + else if (opcode >= IF) return "IF"; + else if (opcode >= EVEN) return "EVEN"; + else if (opcode >= ODD) return "ODD"; + else if (opcode >= NEQ) return "NEQ"; + else if (opcode >= EQ) return "EQ"; + else if (opcode >= GTEQ) return "GTEQ"; + else if (opcode >= GT) return "GT"; + else if (opcode >= LTEQ) return "LTEQ"; + else if (opcode >= LT) return "LT"; + else if (opcode >= DEBUG) return "DEBUG"; + else if (opcode >= FLIPOFF) return "FLIPOFF"; + else if (opcode >= FLIPON) return "FLIPON"; + else if (opcode >= MPS) return "MPS"; + else if (opcode >= MPPEM) return "MPPEM"; + else if (opcode >= MD) return "MD["+(opcode&1)+"]"; + else if (opcode >= SCFS) return "SCFS"; + else if (opcode >= GC) return "GC["+(opcode&1)+"]"; + else if (opcode >= RCVT) return "RCVT"; + else if (opcode >= WCVTP) return "WCVTP"; + else if (opcode >= RS) return "RS"; + else if (opcode >= WS) return "WS"; + else if (opcode >= NPUSHW) return "NPUSHW"; + else if (opcode >= NPUSHB) return "NPUSHB"; + else if (opcode >= MIAP) return "MIAP["+((opcode&1)==0?"nrd+nci":"rd+ci")+"]"; + else if (opcode >= RTDG) return "RTDG"; + else if (opcode >= ALIGNRP) return "ALIGNRP"; + else if (opcode >= MSIRP) return "MSIRP["+(opcode&1)+"]"; + else if (opcode >= IP) return "IP"; + else if (opcode >= SHPIX) return "SHPIX"; + else if (opcode >= SHZ) return "SHZ["+(opcode&1)+"]"; + else if (opcode >= SHC) return "SHC["+(opcode&1)+"]"; + else if (opcode >= SHP) return "SHP"; + else if (opcode >= IUP) return "IUP["+((opcode&1)==0?"y":"x")+"]"; + else if (opcode >= MDAP) return "MDAP["+((opcode&1)==0?"nrd":"rd")+"]"; + else if (opcode >= ENDF) return "ENDF"; + else if (opcode >= FDEF) return "FDEF"; + else if (opcode >= CALL) return "CALL"; + else if (opcode >= LOOPCALL) return "LOOPCALL"; + else if (opcode >= UTP) return "UTP"; + else if (opcode >= ALIGNPTS) return "ALIGNPTS"; + else if (opcode >= MINDEX) return "MINDEX"; + else if (opcode >= CINDEX) return "CINDEX"; + else if (opcode >= DEPTH) return "DEPTH"; + else if (opcode >= SWAP) return "SWAP"; + else if (opcode >= CLEAR) return "CLEAR"; + else if (opcode >= POP) return "POP"; + else if (opcode >= DUP) return "DUP"; + else if (opcode >= SSW) return "SSW"; + else if (opcode >= SSWCI) return "SSWCI"; + else if (opcode >= SCVTCI) return "SCVTCI"; + else if (opcode >= JMPR) return "JMPR"; + else if (opcode >= ELSE) return "ELSE"; + else if (opcode >= SMD) return "SMD"; + else if (opcode >= RTHG) return "RTHG"; + else if (opcode >= RTG) return "RTG"; + else if (opcode >= SLOOP) return "SLOOP"; + else if (opcode >= SZPS) return "SZPS"; + else if (opcode >= SZP2) return "SZP2"; + else if (opcode >= SZP1) return "SZP1"; + else if (opcode >= SZP0) return "SZP0"; + else if (opcode >= SRP2) return "SRP2"; + else if (opcode >= SRP1) return "SRP1"; + else if (opcode >= SRP0) return "SRP0"; + else if (opcode >= ISECT) return "ISECT"; + else if (opcode >= SFVTPV) return "SFVTPV"; + else if (opcode >= GFV) return "GFV"; + else if (opcode >= GPV) return "GPV"; + else if (opcode >= SFVFS) return "SFVFS"; + else if (opcode >= SPVFS) return "SPVFS"; + else if (opcode >= SFVTL) return "SFVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SPVTL) return "SPVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SFVTCA) return "SFVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SPVTCA) return "SPVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SVTCA) return "SVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else return "????"; + } + + public static String getComment(short opcode) { + if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Indirect Relative Point"; + else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Direct Relative Point"; + else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]"; + else if (opcode >= PUSHB) return "PUSHB["+((opcode&7)+1)+"]"; + else if (opcode >= INSTCTRL) return "INSTCTRL\tINSTruction Execution ConTRol"; + else if (opcode >= SCANTYPE) return "SCANTYPE\tSCANTYPE"; + else if (opcode >= MIN) return "MIN\t\tMINimum of top two stack elements"; + else if (opcode >= MAX) return "MAX\t\tMAXimum of top two stack elements"; + else if (opcode >= ROLL) return "ROLL\t\tROLL the top three stack elements"; + else if (opcode >= IDEF) return "IDEF\t\tInstruction DEFinition"; + else if (opcode >= GETINFO) return "GETINFO\tGET INFOrmation"; + else if (opcode >= SDPVTL) return "SDPVTL["+(opcode&1)+"]\tSet Dual Projection_Vector To Line"; + else if (opcode >= SCANCTRL) return "SCANCTRL\tSCAN conversion ConTRoL"; + else if (opcode >= FLIPRGOFF) return "FLIPRGOFF\tFLIP RanGe OFF"; + else if (opcode >= FLIPRGON) return "FLIPRGON\tFLIP RanGe ON"; + else if (opcode >= FLIPPT) return "FLIPPT\tFLIP PoinT"; + else if (opcode >= AA) return "AA"; + else if (opcode >= SANGW) return "SANGW\t\tSet Angle _Weight"; + else if (opcode >= RDTG) return "RDTG\t\tRound Down To Grid"; + else if (opcode >= RUTG) return "RUTG\t\tRound Up To Grid"; + else if (opcode >= ROFF) return "ROFF\t\tRound OFF"; + else if (opcode >= JROF) return "JROF\t\tJump Relative On False"; + else if (opcode >= JROT) return "JROT\t\tJump Relative On True"; + else if (opcode >= S45ROUND) return "S45ROUND\tSuper ROUND 45 degrees"; + else if (opcode >= SROUND) return "SROUND\tSuper ROUND"; + else if (opcode >= DELTAC3) return "DELTAC3\tDELTA exception C3"; + else if (opcode >= DELTAC2) return "DELTAC2\tDELTA exception C2"; + else if (opcode >= DELTAC1) return "DELTAC1\tDELTA exception C1"; + else if (opcode >= DELTAP3) return "DELTAP3\tDELTA exception P3"; + else if (opcode >= DELTAP2) return "DELTAP2\tDELTA exception P2"; + else if (opcode >= WCVTF) return "WCVTF\t\tWrite Control Value Table in FUnits"; + else if (opcode >= NROUND) return "NROUND["+(opcode&3)+"]"; + else if (opcode >= ROUND) return "ROUND["+(opcode&3)+"]"; + else if (opcode >= CEILING) return "CEILING\tCEILING"; + else if (opcode >= FLOOR) return "FLOOR\t\tFLOOR"; + else if (opcode >= NEG) return "NEG\t\tNEGate"; + else if (opcode >= ABS) return "ABS\t\tABSolute value"; + else if (opcode >= MUL) return "MUL\t\tMULtiply"; + else if (opcode >= DIV) return "DIV\t\tDIVide"; + else if (opcode >= SUB) return "SUB\t\tSUBtract"; + else if (opcode >= ADD) return "ADD\t\tADD"; + else if (opcode >= SDS) return "SDS\t\tSet Delta_Shift in the graphics state"; + else if (opcode >= SDB) return "SDB\t\tSet Delta_Base in the graphics state"; + else if (opcode >= DELTAP1) return "DELTAP1\tDELTA exception P1"; + else if (opcode >= NOT) return "NOT\t\tlogical NOT"; + else if (opcode >= OR) return "OR\t\t\tlogical OR"; + else if (opcode >= AND) return "AND\t\tlogical AND"; + else if (opcode >= EIF) return "EIF\t\tEnd IF"; + else if (opcode >= IF) return "IF\t\t\tIF test"; + else if (opcode >= EVEN) return "EVEN"; + else if (opcode >= ODD) return "ODD"; + else if (opcode >= NEQ) return "NEQ\t\tNot EQual"; + else if (opcode >= EQ) return "EQ\t\t\tEQual"; + else if (opcode >= GTEQ) return "GTEQ\t\tGreater Than or Equal"; + else if (opcode >= GT) return "GT\t\t\tGreater Than"; + else if (opcode >= LTEQ) return "LTEQ\t\tLess Than or Equal"; + else if (opcode >= LT) return "LT\t\t\tLess Than"; + else if (opcode >= DEBUG) return "DEBUG"; + else if (opcode >= FLIPOFF) return "FLIPOFF\tSet the auto_flip Boolean to OFF"; + else if (opcode >= FLIPON) return "FLIPON\tSet the auto_flip Boolean to ON"; + else if (opcode >= MPS) return "MPS\t\tMeasure Point Size"; + else if (opcode >= MPPEM) return "MPPEM\t\tMeasure Pixels Per EM"; + else if (opcode >= MD) return "MD["+(opcode&1)+"]\t\t\tMeasure Distance"; + else if (opcode >= SCFS) return "SCFS\t\tSets Coordinate From the Stack using projection_vector and freedom_vector"; + else if (opcode >= GC) return "GC["+(opcode&1)+"]\t\t\tGet Coordinate projected onto the projection_vector"; + else if (opcode >= RCVT) return "RCVT\t\tRead Control Value Table"; + else if (opcode >= WCVTP) return "WCVTP\t\tWrite Control Value Table in Pixel units"; + else if (opcode >= RS) return "RS\t\t\tRead Store"; + else if (opcode >= WS) return "WS\t\t\tWrite Store"; + else if (opcode >= NPUSHW) return "NPUSHW"; + else if (opcode >= NPUSHB) return "NPUSHB"; + else if (opcode >= MIAP) return "MIAP["+((opcode&1)==0?"nrd+nci":"rd+ci")+"]\t\tMove Indirect Absolute Point"; + else if (opcode >= RTDG) return "RTDG\t\tRound To Double Grid"; + else if (opcode >= ALIGNRP) return "ALIGNRP\tALIGN Relative Point"; + else if (opcode >= MSIRP) return "MSIRP["+(opcode&1)+"]\t\tMove Stack Indirect Relative Point"; + else if (opcode >= IP) return "IP\t\t\tInterpolate Point by the last relative stretch"; + else if (opcode >= SHPIX) return "SHPIX\t\tSHift point by a PIXel amount"; + else if (opcode >= SHZ) return "SHZ["+(opcode&1)+"]\t\tSHift Zone by the last pt"; + else if (opcode >= SHC) return "SHC["+(opcode&1)+"]\t\tSHift Contour by the last point"; + else if (opcode >= SHP) return "SHP\t\tSHift Point by the last point"; + else if (opcode >= IUP) return "IUP["+((opcode&1)==0?"y":"x")+"]\t\tInterpolate Untouched Points through the outline"; + else if (opcode >= MDAP) return "MDAP["+((opcode&1)==0?"nrd":"rd")+"]\t\tMove Direct Absolute Point"; + else if (opcode >= ENDF) return "ENDF\t\tEND Function definition"; + else if (opcode >= FDEF) return "FDEF\t\tFunction DEFinition "; + else if (opcode >= CALL) return "CALL\t\tCALL function"; + else if (opcode >= LOOPCALL) return "LOOPCALL\tLOOP and CALL function"; + else if (opcode >= UTP) return "UTP\t\tUnTouch Point"; + else if (opcode >= ALIGNPTS) return "ALIGNPTS\tALIGN Points"; + else if (opcode >= MINDEX) return "MINDEX\tMove the INDEXed element to the top of the stack"; + else if (opcode >= CINDEX) return "CINDEX\tCopy the INDEXed element to the top of the stack"; + else if (opcode >= DEPTH) return "DEPTH\t\tReturns the DEPTH of the stack"; + else if (opcode >= SWAP) return "SWAP\t\tSWAP the top two elements on the stack"; + else if (opcode >= CLEAR) return "CLEAR\t\tClear the entire stack"; + else if (opcode >= POP) return "POP\t\tPOP top stack element"; + else if (opcode >= DUP) return "DUP\t\tDuplicate top stack element"; + else if (opcode >= SSW) return "SSW\t\tSet Single-width"; + else if (opcode >= SSWCI) return "SSWCI\t\tSet Single_Width_Cut_In"; + else if (opcode >= SCVTCI) return "SCVTCI\tSet Control Value Table Cut In"; + else if (opcode >= JMPR) return "JMPR\t\tJuMP"; + else if (opcode >= ELSE) return "ELSE"; + else if (opcode >= SMD) return "SMD\t\tSet Minimum_ Distance"; + else if (opcode >= RTHG) return "RTHG\t\tRound To Half Grid"; + else if (opcode >= RTG) return "RTG\t\tRound To Grid"; + else if (opcode >= SLOOP) return "SLOOP\t\tSet LOOP variable"; + else if (opcode >= SZPS) return "SZPS\t\tSet Zone PointerS"; + else if (opcode >= SZP2) return "SZP2\t\tSet Zone Pointer 2"; + else if (opcode >= SZP1) return "SZP1\t\tSet Zone Pointer 1"; + else if (opcode >= SZP0) return "SZP0\t\tSet Zone Pointer 0"; + else if (opcode >= SRP2) return "SRP2\t\tSet Reference Point 2"; + else if (opcode >= SRP1) return "SRP1\t\tSet Reference Point 1"; + else if (opcode >= SRP0) return "SRP0\t\tSet Reference Point 0"; + else if (opcode >= ISECT) return "ISECT\t\tmoves point p to the InterSECTion of two lines"; + else if (opcode >= SFVTPV) return "SFVTPV\tSet Freedom_Vector To Projection Vector"; + else if (opcode >= GFV) return "GFV\t\tGet Freedom_Vector"; + else if (opcode >= GPV) return "GPV\t\tGet Projection_Vector"; + else if (opcode >= SFVFS) return "SFVFS\t\tSet Freedom_Vector From Stack"; + else if (opcode >= SPVFS) return "SPVFS\t\tSet Projection_Vector From Stack"; + else if (opcode >= SFVTL) return "SFVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet Freedom_Vector To Line"; + else if (opcode >= SPVTL) return "SPVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet Projection_Vector To Line"; + else if (opcode >= SFVTCA) return "SFVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\tSet Freedom_Vector to Coordinate Axis"; + else if (opcode >= SPVTCA) return "SPVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\tSet Projection_Vector To Coordinate Axis"; + else if (opcode >= SVTCA) return "SVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet freedom and projection Vectors To Coordinate Axis"; + else return "????"; + } +} diff --git a/src/net/java/dev/typecast/ot/OTFont.java b/src/net/java/dev/typecast/ot/OTFont.java new file mode 100644 index 000000000..d23228483 --- /dev/null +++ b/src/net/java/dev/typecast/ot/OTFont.java @@ -0,0 +1,265 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot; + +import java.io.DataInputStream; +import java.io.IOException; + +import net.java.dev.typecast.ot.table.DirectoryEntry; +import net.java.dev.typecast.ot.table.TTCHeader; +import net.java.dev.typecast.ot.table.TableDirectory; +import net.java.dev.typecast.ot.table.Table; +import net.java.dev.typecast.ot.table.Os2Table; +import net.java.dev.typecast.ot.table.CmapTable; +import net.java.dev.typecast.ot.table.GlyfTable; +import net.java.dev.typecast.ot.table.HeadTable; +import net.java.dev.typecast.ot.table.HheaTable; +import net.java.dev.typecast.ot.table.HmtxTable; +import net.java.dev.typecast.ot.table.LocaTable; +import net.java.dev.typecast.ot.table.MaxpTable; +import net.java.dev.typecast.ot.table.NameTable; +import net.java.dev.typecast.ot.table.PostTable; +import net.java.dev.typecast.ot.table.VheaTable; +import net.java.dev.typecast.ot.table.TableFactory; + +/** + * The TrueType font. + * @version $Id: OTFont.java,v 1.6 2007-01-31 01:49:18 davidsch Exp $ + * @author David Schweinsberg + */ +public class OTFont { + + private OTFontCollection _fc; + private TableDirectory _tableDirectory = null; + private Table[] _tables; + private Os2Table _os2; + private CmapTable _cmap; + private GlyfTable _glyf; + private HeadTable _head; + private HheaTable _hhea; + private HmtxTable _hmtx; + private LocaTable _loca; + private MaxpTable _maxp; + private NameTable _name; + private PostTable _post; + private VheaTable _vhea; + + /** + * Constructor + */ + public OTFont(OTFontCollection fc) { + _fc = fc; + } + + public Table getTable(int tableType) { + for (int i = 0; i < _tables.length; i++) { + if ((_tables[i] != null) && (_tables[i].getType() == tableType)) { + return _tables[i]; + } + } + return null; + } + + public Os2Table getOS2Table() { + return _os2; + } + + public CmapTable getCmapTable() { + return _cmap; + } + + public HeadTable getHeadTable() { + return _head; + } + + public HheaTable getHheaTable() { + return _hhea; + } + + public HmtxTable getHmtxTable() { + return _hmtx; + } + + public LocaTable getLocaTable() { + return _loca; + } + + public MaxpTable getMaxpTable() { + return _maxp; + } + + public NameTable getNameTable() { + return _name; + } + + public PostTable getPostTable() { + return _post; + } + + public VheaTable getVheaTable() { + return _vhea; + } + + public int getAscent() { + return _hhea.getAscender(); + } + + public int getDescent() { + return _hhea.getDescender(); + } + + public int getNumGlyphs() { + return _maxp.getNumGlyphs(); + } + + public Glyph getGlyph(int i) { + return (_glyf.getDescription(i) != null) + ? new Glyph( + _glyf.getDescription(i), + _hmtx.getLeftSideBearing(i), + _hmtx.getAdvanceWidth(i)) + : null; + } + + public TableDirectory getTableDirectory() { + return _tableDirectory; + } + + private Table readTable( + DataInputStream dis, + int tablesOrigin, + int tag) throws IOException { + dis.reset(); + DirectoryEntry entry = _tableDirectory.getEntryByTag(tag); + if (entry == null) { + return null; + } + dis.skip(tablesOrigin + entry.getOffset()); + return TableFactory.create(_fc, this, entry, dis); + } + + /** + * @param dis OpenType/TrueType font file data. + * @param directoryOffset The Table Directory offset within the file. For a + * regular TTF/OTF file this will be zero, but for a TTC (Font Collection) + * the offset is retrieved from the TTC header. For a Mac font resource, + * offset is retrieved from the resource headers. + * @param tablesOrigin The point the table offsets are calculated from. + * Once again, in a regular TTF file, this will be zero. In a TTC is is + * also zero, but within a Mac resource, it is the beggining of the + * individual font resource data. + */ + protected void read( + DataInputStream dis, + int directoryOffset, + int tablesOrigin) throws IOException { + + // Load the table directory + dis.reset(); + dis.skip(directoryOffset); + _tableDirectory = new TableDirectory(dis); + _tables = new Table[_tableDirectory.getNumTables()]; + + // Load some prerequisite tables + _head = (HeadTable) readTable(dis, tablesOrigin, Table.head); + _hhea = (HheaTable) readTable(dis, tablesOrigin, Table.hhea); + _maxp = (MaxpTable) readTable(dis, tablesOrigin, Table.maxp); + _loca = (LocaTable) readTable(dis, tablesOrigin, Table.loca); + _vhea = (VheaTable) readTable(dis, tablesOrigin, Table.vhea); + + int index = 0; + _tables[index++] = _head; + _tables[index++] = _hhea; + _tables[index++] = _maxp; + if (_loca != null) { + _tables[index++] = _loca; + } + if (_vhea != null) { + _tables[index++] = _vhea; + } + + // Load all other tables + for (int i = 0; i < _tableDirectory.getNumTables(); i++) { + DirectoryEntry entry = _tableDirectory.getEntry(i); + if (entry.getTag() == Table.head + || entry.getTag() == Table.hhea + || entry.getTag() == Table.maxp + || entry.getTag() == Table.loca + || entry.getTag() == Table.vhea) { + continue; + } + dis.reset(); + dis.skip(tablesOrigin + entry.getOffset()); + _tables[index] = TableFactory.create(_fc, this, entry, dis); + ++index; + } + + // Get references to commonly used tables (these happen to be all the + // required tables) + _cmap = (CmapTable) getTable(Table.cmap); + _hmtx = (HmtxTable) getTable(Table.hmtx); + _name = (NameTable) getTable(Table.name); + _os2 = (Os2Table) getTable(Table.OS_2); + _post = (PostTable) getTable(Table.post); + + // If this is a TrueType outline, then we'll have at least the + // 'glyf' table (along with the 'loca' table) + _glyf = (GlyfTable) getTable(Table.glyf); + } + + public String toString() { + if (_tableDirectory != null) { + return _tableDirectory.toString(); + } else { + return "Empty font"; + } + } +} diff --git a/src/net/java/dev/typecast/ot/OTFontCollection.java b/src/net/java/dev/typecast/ot/OTFontCollection.java new file mode 100644 index 000000000..6f8754f59 --- /dev/null +++ b/src/net/java/dev/typecast/ot/OTFontCollection.java @@ -0,0 +1,169 @@ +/* + * $Id: OTFontCollection.java,v 1.6 2010-08-10 11:38:11 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot; + +import java.io.File; +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; + +import java.util.ArrayList; + +import net.java.dev.typecast.ot.mac.ResourceHeader; +import net.java.dev.typecast.ot.mac.ResourceMap; +import net.java.dev.typecast.ot.mac.ResourceReference; +import net.java.dev.typecast.ot.mac.ResourceType; +import net.java.dev.typecast.ot.table.DirectoryEntry; +import net.java.dev.typecast.ot.table.Table; +import net.java.dev.typecast.ot.table.TTCHeader; + +/** + * + * @author David Schweinsberg + * @version $Id: OTFontCollection.java,v 1.6 2010-08-10 11:38:11 davidsch Exp $ + */ +public class OTFontCollection { + + private String _pathName; + private String _fileName; + private TTCHeader _ttcHeader; + private OTFont[] _fonts; + private ArrayList _tables = new ArrayList
(); + private boolean _resourceFork = false; + + /** Creates new FontCollection */ + protected OTFontCollection() { + } + + /** + * @param file The OpenType font file + */ + public static OTFontCollection create(File file) throws IOException { + OTFontCollection fc = new OTFontCollection(); + fc.read(file); + return fc; + } + + public String getPathName() { + return _pathName; + } + + public String getFileName() { + return _fileName; + } + + public OTFont getFont(int i) { + return _fonts[i]; + } + + public int getFontCount() { + return _fonts.length; + } + + public TTCHeader getTtcHeader() { + return _ttcHeader; + } + + public Table getTable(DirectoryEntry de) { + for (int i = 0; i < _tables.size(); i++) { + Table table = _tables.get(i); + if ((table.getDirectoryEntry().getTag() == de.getTag()) && + (table.getDirectoryEntry().getOffset() == de.getOffset())) { + return table; + } + } + return null; + } + + public void addTable(Table table) { + _tables.add(table); + } + + /** + * @param file The OpenType font file + */ + protected void read(File file) throws IOException { + _pathName = file.getPath(); + _fileName = file.getName(); + + if (!file.exists()) { + throw new IOException(); + } + + // Do we need to modify the path name to deal with font resources + // in a Mac resource fork? + if (file.length() == 0) { + file = new File(file, "..namedfork/rsrc"); + if (!file.exists()) { + throw new IOException(); + } + _resourceFork = true; + } + + DataInputStream dis = new DataInputStream( + new BufferedInputStream( + new FileInputStream(file), (int) file.length())); + dis.mark((int) file.length()); + + if (_resourceFork || _pathName.endsWith(".dfont")) { + + // This is a Macintosh font suitcase resource + ResourceHeader resourceHeader = new ResourceHeader(dis); + + // Seek to the map offset and read the map + dis.reset(); + dis.skip(resourceHeader.getMapOffset()); + ResourceMap map = new ResourceMap(dis); + + // Get the 'sfnt' resources + ResourceType resourceType = map.getResourceType("sfnt"); + + // Load the font data + _fonts = new OTFont[resourceType.getCount()]; + for (int i = 0; i < resourceType.getCount(); i++) { + ResourceReference resourceReference = resourceType.getReference(i); + _fonts[i] = new OTFont(this); + int offset = resourceHeader.getDataOffset() + + resourceReference.getDataOffset() + 4; + _fonts[i].read(dis, offset, offset); + } + + } else if (TTCHeader.isTTC(dis)) { + + // This is a TrueType font collection + dis.reset(); + _ttcHeader = new TTCHeader(dis); + _fonts = new OTFont[_ttcHeader.getDirectoryCount()]; + for (int i = 0; i < _ttcHeader.getDirectoryCount(); i++) { + _fonts[i] = new OTFont(this); + _fonts[i].read(dis, _ttcHeader.getTableDirectory(i), 0); + } + } else { + + // This is a standalone font file + _fonts = new OTFont[1]; + _fonts[0] = new OTFont(this); + _fonts[0].read(dis, 0, 0); + } + dis.close(); + } +} diff --git a/src/net/java/dev/typecast/ot/Point.java b/src/net/java/dev/typecast/ot/Point.java new file mode 100644 index 000000000..fae13b098 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Point.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * @version $Id: Point.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + * @author David Schweinsberg + */ +public class Point { + + public int x = 0; + public int y = 0; + public boolean onCurve = true; + public boolean endOfContour = false; + public boolean touched = false; + + public Point(int x, int y, boolean onCurve, boolean endOfContour) { + this.x = x; + this.y = y; + this.onCurve = onCurve; + this.endOfContour = endOfContour; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceData.java b/src/net/java/dev/typecast/ot/mac/ResourceData.java new file mode 100644 index 000000000..a1c12ffc0 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceData.java @@ -0,0 +1,45 @@ +/* + * $Id: ResourceData.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ResourceData.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + */ +public class ResourceData { + + private byte[] data; + + /** Creates new ResourceData */ + public ResourceData(DataInput di) throws IOException { + int dataLen = di.readInt(); + data = new byte[dataLen]; + di.readFully(data); + } + + public byte[] getData() { + return data; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceFile.java b/src/net/java/dev/typecast/ot/mac/ResourceFile.java new file mode 100644 index 000000000..e9499d9e8 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceFile.java @@ -0,0 +1,77 @@ +/* + * $Id: ResourceFile.java,v 1.2 2007-01-29 04:01:53 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Mac resource loading test. + * TODO: incorporate this into the test suite. + * @author David Schweinsberg + * @version $Id: ResourceFile.java,v 1.2 2007-01-29 04:01:53 davidsch Exp $ + */ +public class ResourceFile { + + private ResourceHeader header; + private ResourceMap map; + + /** Creates new Resource */ + public ResourceFile(RandomAccessFile raf) throws IOException { + + // Read header at the beginning of the file + raf.seek(0); + header = new ResourceHeader(raf); + + // Seek to the map offset and read the map + raf.seek(header.getMapOffset()); + map = new ResourceMap(raf); + } + + public ResourceMap getResourceMap() { + return map; + } + + public static void main(String[] args) { + try { + //RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/GillSans.dfont", "r"); + + // Tests loading a font from a resource fork on Mac OS X + RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/Georgia/..namedfork/rsrc", "r"); + ResourceFile resource = new ResourceFile(raf); + for (int i = 0; i < resource.getResourceMap().getResourceTypeCount(); i++) { + System.out.println(resource.getResourceMap().getResourceType(i).getTypeAsString()); + } + + // Get the first 'sfnt' resource + ResourceType type = resource.getResourceMap().getResourceType("sfnt"); + ResourceReference reference = type.getReference(0); + + type = resource.getResourceMap().getResourceType("FOND"); + for (int i = 0; i < type.getCount(); ++i) { + reference = type.getReference(i); + System.out.println(reference.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceHeader.java b/src/net/java/dev/typecast/ot/mac/ResourceHeader.java new file mode 100644 index 000000000..bdfe15a72 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceHeader.java @@ -0,0 +1,61 @@ +/* + * $Id: ResourceHeader.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ResourceHeader.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceHeader { + + private int dataOffset; + private int mapOffset; + private int dataLen; + private int mapLen; + + /** Creates new ResourceHeader */ + public ResourceHeader(DataInput di) throws IOException { + dataOffset = di.readInt(); + mapOffset = di.readInt(); + dataLen = di.readInt(); + mapLen = di.readInt(); + } + + public int getDataOffset() { + return dataOffset; + } + + public int getMapOffset() { + return mapOffset; + } + + public int getDataLength() { + return dataLen; + } + + public int getMapLength() { + return mapLen; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceMap.java b/src/net/java/dev/typecast/ot/mac/ResourceMap.java new file mode 100644 index 000000000..ee98fd8eb --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceMap.java @@ -0,0 +1,83 @@ +/* + * $Id: ResourceMap.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ResourceMap.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceMap { + + private byte[] headerCopy = new byte[16]; + private int nextResourceMap; + private int fileReferenceNumber; + private int attributes; + private ResourceType[] types; + + /** Creates new ResourceMap */ + public ResourceMap(DataInput di) throws IOException { + di.readFully(headerCopy); + nextResourceMap = di.readInt(); + fileReferenceNumber = di.readUnsignedShort(); + attributes = di.readUnsignedShort(); + int typeOffset = di.readUnsignedShort(); + int nameOffset = di.readUnsignedShort(); + int typeCount = di.readUnsignedShort() + 1; + + // Read types + types = new ResourceType[typeCount]; + for (int i = 0; i < typeCount; i++) { + types[i] = new ResourceType(di); + } + + // Read the references + for (int i = 0; i < typeCount; i++) { + types[i].readRefs(di); + } + + // Read the names + for (int i = 0; i < typeCount; i++) { + types[i].readNames(di); + } + } + + public ResourceType getResourceType(String typeName) { + for (int i = 0; i < types.length; i++) { + String s = types[i].getTypeAsString(); + if (types[i].getTypeAsString().equals(typeName)) { + return types[i]; + } + } + return null; + } + + public ResourceType getResourceType(int i) { + return types[i]; + } + + public int getResourceTypeCount() { + return types.length; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceReference.java b/src/net/java/dev/typecast/ot/mac/ResourceReference.java new file mode 100644 index 000000000..f7f6e0fdf --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceReference.java @@ -0,0 +1,81 @@ +/* + * $Id: ResourceReference.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ResourceReference.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceReference { + + private int id; + private short nameOffset; + private short attributes; + private int dataOffset; + private int handle; + private String name; + + /** Creates new ResourceReference */ + protected ResourceReference(DataInput di) throws IOException { + id = di.readUnsignedShort(); + nameOffset = di.readShort(); + attributes = (short) di.readUnsignedByte(); + dataOffset = (di.readUnsignedByte()<<16) | di.readUnsignedShort(); + handle = di.readInt(); + } + + protected void readName(DataInput di) throws IOException { + if (nameOffset > -1) { + int len = di.readUnsignedByte(); + byte[] buf = new byte[len]; + di.readFully(buf); + name = new String(buf); + } + } + + public int getId() { + return id; + } + + public short getNameOffset() { + return nameOffset; + } + + public short getAttributes() { + return attributes; + } + + public int getDataOffset() { + return dataOffset; + } + + public int getHandle() { + return handle; + } + + public String getName() { + return name; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceType.java b/src/net/java/dev/typecast/ot/mac/ResourceType.java new file mode 100644 index 000000000..2c21e7a27 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceType.java @@ -0,0 +1,82 @@ +/* + * $Id: ResourceType.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ResourceType.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ResourceType { + + private int type; + private int count; + private int offset; + private ResourceReference[] references; + + /** Creates new ResourceType */ + protected ResourceType(DataInput di) throws IOException { + type = di.readInt(); + count = di.readUnsignedShort() + 1; + offset = di.readUnsignedShort(); + references = new ResourceReference[count]; + } + + protected void readRefs(DataInput di) throws IOException { + for (int i = 0; i < count; i++) { + references[i] = new ResourceReference(di); + } + } + + protected void readNames(DataInput di) throws IOException { + for (int i = 0; i < count; i++) { + references[i].readName(di); + } + } + + public int getType() { + return type; + } + + public String getTypeAsString() { + return new StringBuffer() + .append((char)((type>>24)&0xff)) + .append((char)((type>>16)&0xff)) + .append((char)((type>>8)&0xff)) + .append((char)((type)&0xff)) + .toString(); + } + + public int getCount() { + return count; + } + + public int getOffset() { + return offset; + } + + public ResourceReference getReference(int i) { + return references[i]; + } +} diff --git a/src/net/java/dev/typecast/ot/table/BaseTable.java b/src/net/java/dev/typecast/ot/table/BaseTable.java new file mode 100644 index 000000000..7e6c37a5e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/BaseTable.java @@ -0,0 +1,436 @@ +/* + * $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * Baseline Table + * @version $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ + * @author David Schweinsberg + */ +public class BaseTable implements Table { + + private abstract class BaseCoord { + + public abstract int getBaseCoordFormat(); + + public abstract short getCoordinate(); + } + + private class BaseCoordFormat1 extends BaseCoord { + + private short _coordinate; + + protected BaseCoordFormat1(DataInput di) throws IOException { + _coordinate = di.readShort(); + } + + public int getBaseCoordFormat() { + return 1; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class BaseCoordFormat2 extends BaseCoord { + + private short _coordinate; + private int _referenceGlyph; + private int _baseCoordPoint; + + protected BaseCoordFormat2(DataInput di) throws IOException { + _coordinate = di.readShort(); + _referenceGlyph = di.readUnsignedShort(); + _baseCoordPoint = di.readUnsignedShort(); + } + + public int getBaseCoordFormat() { + return 2; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class BaseCoordFormat3 extends BaseCoord { + + private short _coordinate; + private int _deviceTableOffset; + + protected BaseCoordFormat3(DataInput di) throws IOException { + _coordinate = di.readShort(); + _deviceTableOffset = di.readUnsignedShort(); + } + + public int getBaseCoordFormat() { + return 2; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class FeatMinMaxRecord { + + private int _tag; + private int _minCoordOffset; + private int _maxCoordOffset; + + protected FeatMinMaxRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _minCoordOffset = di.readUnsignedShort(); + _maxCoordOffset = di.readUnsignedShort(); + } + } + + private class MinMax { + + private int _minCoordOffset; + private int _maxCoordOffset; + private int _featMinMaxCount; + private FeatMinMaxRecord[] _featMinMaxRecord; + + protected MinMax(int minMaxOffset) throws IOException { + DataInput di = getDataInputForOffset(minMaxOffset); + _minCoordOffset = di.readUnsignedShort(); + _maxCoordOffset = di.readUnsignedShort(); + _featMinMaxCount = di.readUnsignedShort(); + _featMinMaxRecord = new FeatMinMaxRecord[_featMinMaxCount]; + for (int i = 0; i < _featMinMaxCount; ++i) { + _featMinMaxRecord[i] = new FeatMinMaxRecord(di); + } + } + } + + private class BaseValues { + + private int _defaultIndex; + private int _baseCoordCount; + private int[] _baseCoordOffset; + private BaseCoord[] _baseCoords; + + protected BaseValues(int baseValuesOffset) throws IOException { + DataInput di = getDataInputForOffset(baseValuesOffset); + _defaultIndex = di.readUnsignedShort(); + _baseCoordCount = di.readUnsignedShort(); + _baseCoordOffset = new int[_baseCoordCount]; + for (int i = 0; i < _baseCoordCount; ++i) { + _baseCoordOffset[i] = di.readUnsignedShort(); + } + _baseCoords = new BaseCoord[_baseCoordCount]; + for (int i = 0; i < _baseCoordCount; ++i) { + int format = di.readUnsignedShort(); + switch (format) { + case 1: + _baseCoords[i] = new BaseCoordFormat1(di); + break; + case 2: + _baseCoords[i] = new BaseCoordFormat2(di); + break; + case 3: + _baseCoords[i] = new BaseCoordFormat3(di); + break; + } + } + } + } + + private class BaseLangSysRecord { + + private int _baseLangSysTag; + private int _minMaxOffset; + + protected BaseLangSysRecord(DataInput di) throws IOException { + _baseLangSysTag = di.readInt(); + _minMaxOffset = di.readUnsignedShort(); + } + + public int getBaseLangSysTag() { + return _baseLangSysTag; + } + + public int getMinMaxOffset() { + return _minMaxOffset; + } + } + + private class BaseScript { + + private int _thisOffset; + private int _baseValuesOffset; + private int _defaultMinMaxOffset; + private int _baseLangSysCount; + private BaseLangSysRecord[] _baseLangSysRecord; + private BaseValues _baseValues; + private MinMax[] _minMax; + + protected BaseScript(int baseScriptOffset) throws IOException { + _thisOffset = baseScriptOffset; + DataInput di = getDataInputForOffset(baseScriptOffset); + _baseValuesOffset = di.readUnsignedShort(); + _defaultMinMaxOffset = di.readUnsignedShort(); + _baseLangSysCount = di.readUnsignedShort(); + _baseLangSysRecord = new BaseLangSysRecord[_baseLangSysCount]; + for (int i = 0; i < _baseLangSysCount; ++i) { + _baseLangSysRecord[i] = new BaseLangSysRecord(di); + } + if (_baseValuesOffset > 0) { + _baseValues = new BaseValues(baseScriptOffset + _baseValuesOffset); + } + for (int i = 0; i < _baseLangSysCount; ++i) { + _minMax[i] = new MinMax(baseScriptOffset + _baseLangSysRecord[i].getMinMaxOffset()); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseScript BaseScriptT").append(Integer.toHexString(_thisOffset)) + .append("\nBaseValuesT").append(Integer.toHexString(_thisOffset + _baseValuesOffset)) + .append("\nMinMaxT").append(Integer.toHexString(_thisOffset + _defaultMinMaxOffset)) + .append("\n").append(Integer.toHexString(_baseLangSysCount)); +// for (int i = 0; i < _baseLangSysCount; ++i) { +// sb.append("\n ; BaseScriptRecord[").append(i); +// sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); +// sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); +// } +// for (int i = 0; i < _baseScriptCount; ++i) { +// sb.append("\n").append(_baseScripts[i].toString()); +// } + if (_baseValues != null) { + sb.append("\n").append(_baseValues.toString()); + } + return sb.toString(); + } + } + + private class BaseScriptRecord { + + private int _baseScriptTag; + private int _baseScriptOffset; + + protected BaseScriptRecord(DataInput di) throws IOException { + _baseScriptTag = di.readInt(); + _baseScriptOffset = di.readUnsignedShort(); + } + + public int getBaseScriptTag() { + return _baseScriptTag; + } + + public int getBaseScriptOffset() { + return _baseScriptOffset; + } + } + + private class BaseScriptList { + + private int _thisOffset; + private int _baseScriptCount; + private BaseScriptRecord[] _baseScriptRecord; + private BaseScript[] _baseScripts; + + protected BaseScriptList(int baseScriptListOffset) throws IOException { + _thisOffset = baseScriptListOffset; + DataInput di = getDataInputForOffset(baseScriptListOffset); + _baseScriptCount = di.readUnsignedShort(); + _baseScriptRecord = new BaseScriptRecord[_baseScriptCount]; + for (int i = 0; i < _baseScriptCount; ++i) { + _baseScriptRecord[i] = new BaseScriptRecord(di); + } + _baseScripts = new BaseScript[_baseScriptCount]; + for (int i = 0; i < _baseScriptCount; ++i) { + _baseScripts[i] = new BaseScript( + baseScriptListOffset + _baseScriptRecord[i].getBaseScriptOffset()); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseScriptList BaseScriptListT").append(Integer.toHexString(_thisOffset)) + .append("\n").append(Integer.toHexString(_baseScriptCount)); + for (int i = 0; i < _baseScriptCount; ++i) { + sb.append("\n ; BaseScriptRecord[").append(i); + sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); + sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); + } + for (int i = 0; i < _baseScriptCount; ++i) { + sb.append("\n").append(_baseScripts[i].toString()); + } + return sb.toString(); + } + } + + private class BaseTagList { + + private int _thisOffset; + private int _baseTagCount; + private int[] _baselineTag; + + protected BaseTagList(int baseTagListOffset) throws IOException { + _thisOffset = baseTagListOffset; + DataInput di = getDataInputForOffset(baseTagListOffset); + _baseTagCount = di.readUnsignedShort(); + _baselineTag = new int[_baseTagCount]; + for (int i = 0; i < _baseTagCount; ++i) { + _baselineTag[i] = di.readInt(); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseTagList BaseTagListT").append(Integer.toHexString(_thisOffset)) + .append("\n").append(Integer.toHexString(_baseTagCount)); + for (int i = 0; i < _baseTagCount; ++i) { + sb.append("\n'").append(tagAsString(_baselineTag[i])).append("'"); + } + return sb.toString(); + } + } + + private class Axis { + + private int _thisOffset; + private int _baseTagListOffset; + private int _baseScriptListOffset; + private BaseTagList _baseTagList; + private BaseScriptList _baseScriptList; + + protected Axis(int axisOffset) throws IOException { + _thisOffset = axisOffset; + DataInput di = getDataInputForOffset(axisOffset); + _baseTagListOffset = di.readUnsignedShort(); + _baseScriptListOffset = di.readUnsignedShort(); + if (_baseTagListOffset != 0) { + _baseTagList = new BaseTagList(axisOffset + _baseTagListOffset); + } + if (_baseScriptListOffset != 0) { + _baseScriptList = new BaseScriptList( + axisOffset + _baseScriptListOffset); + } + } + + public String toString() { + return new StringBuffer() + .append("\nAxis AxisT").append(Integer.toHexString(_thisOffset)) + .append("\nBaseTagListT").append(Integer.toHexString(_thisOffset + _baseTagListOffset)) + .append("\nBaseScriptListT").append(Integer.toHexString(_thisOffset + _baseScriptListOffset)) + .append("\n").append(_baseTagList) + .append("\n").append(_baseScriptList) + .toString(); + } + } + + private DirectoryEntry _de; + private int _version; + private int _horizAxisOffset; + private int _vertAxisOffset; + private Axis _horizAxis; + private Axis _vertAxis; + private byte[] _buf; + + /** Creates a new instance of BaseTable */ + protected BaseTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load entire table into a buffer, and create another input stream + _buf = new byte[de.getLength()]; + di.readFully(_buf); + DataInput di2 = getDataInputForOffset(0); + + _version = di2.readInt(); + _horizAxisOffset = di2.readUnsignedShort(); + _vertAxisOffset = di2.readUnsignedShort(); + if (_horizAxisOffset != 0) { + _horizAxis = new Axis(_horizAxisOffset); + } + if (_vertAxisOffset != 0) { + _vertAxis = new Axis(_vertAxisOffset); + } + + // Let go of the buffer + _buf = null; + } + + private DataInput getDataInputForOffset(int offset) { + return new DataInputStream(new ByteArrayInputStream( + _buf, offset, + _de.getLength() - offset)); + } + +// private String valueAsShortHex(int value) { +// return String.format("%1$4x", value); +// } +// +// private String valueAsLongHex(int value) { +// return String.format("%1$8x", value); +// } + + static protected String tagAsString(int tag) { + char[] c = new char[4]; + c[0] = (char)((tag >> 24) & 0xff); + c[1] = (char)((tag >> 16) & 0xff); + c[2] = (char)((tag >> 8) & 0xff); + c[3] = (char)(tag & 0xff); + return String.valueOf(c); + } + + public int getType() { + return BASE; + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("; 'BASE' Table - Baseline\n;-------------------------------------\n\n") + .append("BASEHeader BASEHeaderT").append(Integer.toHexString(0)) + .append("\n").append(Integer.toHexString(_version)) + .append("\nAxisT").append(Integer.toHexString(_horizAxisOffset)) + .append("\nAxisT").append(Integer.toHexString(_vertAxisOffset)); + if (_horizAxis != null) { + sb.append("\n").append(_horizAxis.toString()); + } + if (_vertAxis != null) { + sb.append("\n").append(_vertAxis.toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CffStandardStrings.java b/src/net/java/dev/typecast/ot/table/CffStandardStrings.java new file mode 100644 index 000000000..987ea886c --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CffStandardStrings.java @@ -0,0 +1,424 @@ +/* + * $Id: CffStandardStrings.java,v 1.1 2007-02-05 12:41:52 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +/** + * Compact Font Format Standard Strings. As per Appendix A of the Adobe + * CFF specification. + * @version $Id: CffStandardStrings.java,v 1.1 2007-02-05 12:41:52 davidsch Exp $ + * @author David Schweinsberg + */ +public class CffStandardStrings { + + public static final String[] standardStrings = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" + }; +} diff --git a/src/net/java/dev/typecast/ot/table/CffTable.java b/src/net/java/dev/typecast/ot/table/CffTable.java new file mode 100644 index 000000000..2bd0cec63 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CffTable.java @@ -0,0 +1,620 @@ +/* + * $Id: CffTable.java,v 1.4 2007-07-26 11:15:06 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * Compact Font Format Table + * @version $Id: CffTable.java,v 1.4 2007-07-26 11:15:06 davidsch Exp $ + * @author David Schweinsberg + */ +public class CffTable implements Table { + + public class Dict { + + private Dictionary _entries = new Hashtable(); + private int[] _data; + private int _index; + + protected Dict(int[] data, int offset, int length) { + _data = data; + _index = offset; + while (_index < offset + length) { + addKeyAndValueEntry(); + } + } + + public Object getValue(int key) { + return _entries.get(key); + } + + private boolean addKeyAndValueEntry() { + ArrayList operands = new ArrayList(); + Object operand = null; + while (isOperandAtIndex()) { + operand = nextOperand(); + operands.add(operand); + } + int operator = _data[_index++]; + if (operator == 12) { + operator <<= 8; + operator |= _data[_index++]; + } + if (operands.size() == 1) { + _entries.put(operator, operand); + } else { + _entries.put(operator, operands); + } + return true; + } + + private boolean isOperandAtIndex() { + int b0 = _data[_index]; + if ((32 <= b0 && b0 <= 254) + || b0 == 28 + || b0 == 29 + || b0 == 30) { + return true; + } + return false; + } + + private boolean isOperatorAtIndex() { + int b0 = _data[_index]; + if (0 <= b0 && b0 <= 21) { + return true; + } + return false; + } + + private Object nextOperand() { + int b0 = _data[_index]; + if (32 <= b0 && b0 <= 246) { + + // 1 byte integer + ++_index; + return new Integer(b0 - 139); + } else if (247 <= b0 && b0 <= 250) { + + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return new Integer((b0 - 247) * 256 + b1 + 108); + } else if (251 <= b0 && b0 <= 254) { + + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return new Integer(-(b0 - 251) * 256 - b1 - 108); + } else if (b0 == 28) { + + // 3 byte integer + int b1 = _data[_index + 1]; + int b2 = _data[_index + 2]; + _index += 3; + return new Integer(b1 << 8 | b2); + } else if (b0 == 29) { + + // 5 byte integer + int b1 = _data[_index + 1]; + int b2 = _data[_index + 2]; + int b3 = _data[_index + 3]; + int b4 = _data[_index + 4]; + _index += 5; + return new Integer(b1 << 24 | b2 << 16 | b3 << 8 | b4); + } else if (b0 == 30) { + + // Real number + StringBuffer fString = new StringBuffer(); + int nibble1 = 0; + int nibble2 = 0; + ++_index; + while ((nibble1 != 0xf) && (nibble2 != 0xf)) { + nibble1 = _data[_index] >> 4; + nibble2 = _data[_index] & 0xf; + ++_index; + fString.append(decodeRealNibble(nibble1)); + fString.append(decodeRealNibble(nibble2)); + } + return new Float(fString.toString()); + } else { + return null; + } + } + + private String decodeRealNibble(int nibble) { + if (nibble < 0xa) { + return Integer.toString(nibble); + } else if (nibble == 0xa) { + return "."; + } else if (nibble == 0xb) { + return "E"; + } else if (nibble == 0xc) { + return "E-"; + } else if (nibble == 0xe) { + return "-"; + } + return ""; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + Enumeration keys = _entries.keys(); + while (keys.hasMoreElements()) { + Integer key = keys.nextElement(); + if ((key.intValue() & 0xc00) == 0xc00) { + sb.append("12 ").append(key.intValue() & 0xff).append(": "); + } else { + sb.append(key.toString()).append(": "); + } + sb.append(_entries.get(key).toString()).append("\n"); + } + return sb.toString(); + } + } + + public class Index { + + private int _count; + private int _offSize; + private int[] _offset; + private int[] _data; + + protected Index(DataInput di) throws IOException { + _count = di.readUnsignedShort(); + _offset = new int[_count + 1]; + _offSize = di.readUnsignedByte(); + for (int i = 0; i < _count + 1; ++i) { + int thisOffset = 0; + for (int j = 0; j < _offSize; ++j) { + thisOffset |= di.readUnsignedByte() << ((_offSize - j - 1) * 8); + } + _offset[i] = thisOffset; + } + _data = new int[getDataLength()]; + for (int i = 0; i < getDataLength(); ++i) { + _data[i] = di.readUnsignedByte(); + } + } + + public int getCount() { + return _count; + } + + public int getOffset(int index) { + return _offset[index]; + } + + public int getDataLength() { + return _offset[_offset.length - 1] - 1; + } + + public int[] getData() { + return _data; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("DICT\n"); + sb.append("count: ").append(_count).append("\n"); + sb.append("offSize: ").append(_offSize).append("\n"); + for (int i = 0; i < _count + 1; ++i) { + sb.append("offset[").append(i).append("]: ").append(_offset[i]).append("\n"); + } + sb.append("data:"); + for (int i = 0; i < _data.length; ++i) { + if (i % 8 == 0) { + sb.append("\n"); + } else { + sb.append(" "); + } + sb.append(_data[i]); + } + sb.append("\n"); + return sb.toString(); + } + } + + public class TopDictIndex extends Index { + + protected TopDictIndex(DataInput di) throws IOException { + super(di); + } + + public Dict getTopDict(int index) { + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + return new Dict(getData(), offset, len); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getTopDict(i).toString()).append("\n"); + } + return sb.toString(); + } + } + + public class NameIndex extends Index { + + protected NameIndex(DataInput di) throws IOException { + super(di); + } + + public String getName(int index) { + String name = null; + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + + // Ensure the name hasn't been deleted + if (getData()[offset] != 0) { + StringBuffer sb = new StringBuffer(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + name = sb.toString(); + } else { + name = "DELETED NAME"; + } + return name; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getName(i)).append("\n"); + } + return sb.toString(); + } + } + + public class StringIndex extends Index { + + protected StringIndex(DataInput di) throws IOException { + super(di); + } + + public String getString(int index) { + if (index < CffStandardStrings.standardStrings.length) { + return CffStandardStrings.standardStrings[index]; + } else { + index -= CffStandardStrings.standardStrings.length; + if (index >= getCount()) { + return null; + } + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + + StringBuffer sb = new StringBuffer(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + return sb.toString(); + } + } + + public String toString() { + int nonStandardBase = CffStandardStrings.standardStrings.length; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(nonStandardBase + i).append(": "); + sb.append(getString(nonStandardBase + i)).append("\n"); + } + return sb.toString(); + } + } + + private class CharsetRange { + + private int _first; + private int _left; + + public int getFirst() { + return _first; + } + + protected void setFirst(int first) { + _first = first; + } + + public int getLeft() { + return _left; + } + + protected void setLeft(int left) { + _left = left; + } + } + + private class CharsetRange1 extends CharsetRange { + + protected CharsetRange1(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedByte()); + } + } + + private class CharsetRange2 extends CharsetRange { + + protected CharsetRange2(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedShort()); + } + } + + private abstract class Charset { + + public abstract int getFormat(); + + public abstract int getSID(int gid); + } + + private class CharsetFormat0 extends Charset { + + private int[] _glyph; + + protected CharsetFormat0(DataInput di, int glyphCount) throws IOException { + _glyph = new int[glyphCount - 1]; // minus 1 because .notdef is omitted + for (int i = 0; i < glyphCount - 1; ++i) { + _glyph[i] = di.readUnsignedShort(); + } + } + + public int getFormat() { + return 0; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + return _glyph[gid - 1]; + } + } + + private class CharsetFormat1 extends Charset { + + private ArrayList _charsetRanges = new ArrayList(); + + protected CharsetFormat1(DataInput di, int glyphCount) throws IOException { + int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted + while (glyphsCovered > 0) { + CharsetRange range = new CharsetRange1(di); + _charsetRanges.add(range); + glyphsCovered -= range.getLeft() + 1; + } + } + + public int getFormat() { + return 1; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 0; + for (CharsetRange range : _charsetRanges) { + count += range.getLeft(); + if (gid < count) { + int sid = gid - count + range.getFirst(); + return sid; + } + } + return 0; + } + } + + private class CharsetFormat2 extends Charset { + + private ArrayList _charsetRanges = new ArrayList(); + + protected CharsetFormat2(DataInput di, int glyphCount) throws IOException { + int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted + while (glyphsCovered > 0) { + CharsetRange range = new CharsetRange2(di); + _charsetRanges.add(range); + glyphsCovered -= range.getLeft() + 1; + } + } + + public int getFormat() { + return 2; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 0; + for (CharsetRange range : _charsetRanges) { + if (gid < range.getLeft() + count) { + int sid = gid - count + range.getFirst() - 1; + return sid; + } + count += range.getLeft(); + } + return 0; + } + } + + private DirectoryEntry _de; + private int _major; + private int _minor; + private int _hdrSize; + private int _offSize; + private NameIndex _nameIndex; + private TopDictIndex _topDictIndex; + private StringIndex _stringIndex; + private Index _globalSubrIndex; + private Index _charStringsIndexArray[]; + private Charset[] _charsets; + private Charstring[][] _charstringsArray; + + private byte[] _buf; + + /** Creates a new instance of CffTable */ + protected CffTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load entire table into a buffer, and create another input stream + _buf = new byte[de.getLength()]; + di.readFully(_buf); + DataInput di2 = getDataInputForOffset(0); + + // Header + _major = di2.readUnsignedByte(); + _minor = di2.readUnsignedByte(); + _hdrSize = di2.readUnsignedByte(); + _offSize = di2.readUnsignedByte(); + + // Name INDEX + di2 = getDataInputForOffset(_hdrSize); + _nameIndex = new NameIndex(di2); + + // Top DICT INDEX + _topDictIndex = new TopDictIndex(di2); + + // String INDEX + _stringIndex = new StringIndex(di2); + + // Global Subr INDEX + _globalSubrIndex = new Index(di2); + + // Encodings go here -- but since this is an OpenType font will this + // not always be a CIDFont? In which case there are no encodings + // within the CFF data. + + // Load each of the fonts + _charStringsIndexArray = new Index[_topDictIndex.getCount()]; + _charsets = new Charset[_topDictIndex.getCount()]; + _charstringsArray = new Charstring[_topDictIndex.getCount()][]; + for (int i = 0; i < _topDictIndex.getCount(); ++i) { + + // Charstrings INDEX + // We load this before Charsets because we may need to know the number + // of glyphs + Integer charStringsOffset = (Integer) _topDictIndex.getTopDict(i).getValue(17); + di2 = getDataInputForOffset(charStringsOffset); + _charStringsIndexArray[i] = new Index(di2); + int glyphCount = _charStringsIndexArray[i].getCount(); + + // Charsets + Integer charsetOffset = (Integer) _topDictIndex.getTopDict(i).getValue(15); + di2 = getDataInputForOffset(charsetOffset); + int format = di2.readUnsignedByte(); + switch (format) { + case 0: + _charsets[i] = new CharsetFormat0(di2, glyphCount); + break; + case 1: + _charsets[i] = new CharsetFormat1(di2, glyphCount); + break; + case 2: + _charsets[i] = new CharsetFormat2(di2, glyphCount); + break; + } + + // Create the charstrings + _charstringsArray[i] = new Charstring[glyphCount]; + for (int j = 0; j < glyphCount; ++j) { + int offset = _charStringsIndexArray[i].getOffset(j) - 1; + int len = _charStringsIndexArray[i].getOffset(j + 1) - offset - 1; + _charstringsArray[i][j] = new CharstringType2( + i, + _stringIndex.getString(_charsets[i].getSID(j)), + _charStringsIndexArray[i].getData(), + offset, + len, + null, + null); + } + } + } + + private DataInput getDataInputForOffset(int offset) { + return new DataInputStream(new ByteArrayInputStream( + _buf, offset, + _de.getLength() - offset)); + } + + public NameIndex getNameIndex() { + return _nameIndex; + } + + public Charset getCharset(int fontIndex) { + return _charsets[fontIndex]; + } + + public Charstring getCharstring(int fontIndex, int gid) { + return _charstringsArray[fontIndex][gid]; + } + + public int getCharstringCount(int fontIndex) { + return _charstringsArray[fontIndex].length; + } + + public int getType() { + return CFF; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'CFF' Table - Compact Font Format\n---------------------------------\n"); + sb.append("\nName INDEX\n"); + sb.append(_nameIndex.toString()); + sb.append("\nTop DICT INDEX\n"); + sb.append(_topDictIndex.toString()); + sb.append("\nString INDEX\n"); + sb.append(_stringIndex.toString()); + sb.append("\nGlobal Subr INDEX\n"); + sb.append(_globalSubrIndex.toString()); + for (int i = 0; i < _charStringsIndexArray.length; ++i) { + sb.append("\nCharStrings INDEX ").append(i).append("\n"); + sb.append(_charStringsIndexArray[i].toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Charstring.java b/src/net/java/dev/typecast/ot/table/Charstring.java new file mode 100644 index 000000000..2439d6bc5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Charstring.java @@ -0,0 +1,33 @@ +/* + * $Id: Charstring.java,v 1.2 2007-02-21 12:25:19 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +/** + * CFF Charstring + * @version $Id: Charstring.java,v 1.2 2007-02-21 12:25:19 davidsch Exp $ + * @author David Schweinsberg + */ +public abstract class Charstring { + + public abstract int getIndex(); + + public abstract String getName(); +} diff --git a/src/net/java/dev/typecast/ot/table/CharstringType2.java b/src/net/java/dev/typecast/ot/table/CharstringType2.java new file mode 100644 index 000000000..e47825cf3 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CharstringType2.java @@ -0,0 +1,235 @@ +/* + * $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import net.java.dev.typecast.ot.table.CffTable; + +/** + * CFF Type 2 Charstring + * @version $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $ + * @author David Schweinsberg + */ +public class CharstringType2 extends Charstring { + + private static final String[] _oneByteOperators = { + "-Reserved-", + "hstem", + "-Reserved-", + "vstem", + "vmoveto", + "rlineto", + "hlineto", + "vlineto", + "rrcurveto", + "-Reserved-", + "callsubr", + "return", + "escape", + "-Reserved-", + "endchar", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "hstemhm", + "hintmask", + "cntrmask", + "rmoveto", + "hmoveto", + "vstemhm", + "rcurveline", + "rlinecurve", + "vvcurveto", + "hhcurveto", + "shortint", + "callgsubr", + "vhcurveto", + "hvcurveto" + }; + + private static final String[] _twoByteOperators = { + "-Reserved- (dotsection)", + "-Reserved-", + "-Reserved-", + "and", + "or", + "not", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "abs", + "add", + "sub", + "div", + "-Reserved-", + "neg", + "eq", + "-Reserved-", + "-Reserved-", + "drop", + "-Reserved-", + "put", + "get", + "ifelse", + "random", + "mul", + "-Reserved-", + "sqrt", + "dup", + "exch", + "index", + "roll", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "hflex", + "flex", + "hflex1", + "flex1", + "-Reserved-" + }; + + private int _index; + private String _name; + private int[] _data; + private int _offset; + private int _length; + private CffTable.Index _localSubrIndex; + private CffTable.Index _globalSubrIndex; + private int _ip; + + /** Creates a new instance of CharstringType2 */ + protected CharstringType2( + int index, + String name, + int[] data, + int offset, + int length, + CffTable.Index localSubrIndex, + CffTable.Index globalSubrIndex) { + _index = index; + _name = name; + _data = data; + _offset = offset; + _length = length; + _localSubrIndex = localSubrIndex; + _globalSubrIndex = globalSubrIndex; + } + + public int getIndex() { + return _index; + } + + public String getName() { + return _name; + } + + private void disassemble(StringBuffer sb) { + Number operand = null; + while (isOperandAtIndex()) { + operand = nextOperand(); + sb.append(operand).append(" "); + } + int operator = nextByte(); + String mnemonic; + if (operator == 12) { + operator = nextByte(); + + // Check we're not exceeding the upper limit of our mnemonics + if (operator > 38) { + operator = 38; + } + mnemonic = _twoByteOperators[operator]; + } else { + mnemonic = _oneByteOperators[operator]; + } + sb.append(mnemonic); + } + + public void resetIP() { + _ip = _offset; + } + + public boolean isOperandAtIndex() { + int b0 = _data[_ip]; + if ((32 <= b0 && b0 <= 255) || b0 == 28) { + return true; + } + return false; + } + + public Number nextOperand() { + int b0 = _data[_ip]; + if (32 <= b0 && b0 <= 246) { + + // 1 byte integer + ++_ip; + return new Integer(b0 - 139); + } else if (247 <= b0 && b0 <= 250) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return new Integer((b0 - 247) * 256 + b1 + 108); + } else if (251 <= b0 && b0 <= 254) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return new Integer(-(b0 - 251) * 256 - b1 - 108); + } else if (b0 == 28) { + + // 3 byte integer + int b1 = _data[_ip + 1]; + int b2 = _data[_ip + 2]; + _ip += 3; + return new Integer(b1 << 8 | b2); + } else if (b0 == 255) { + + // 16-bit signed integer with 16 bits of fraction + int b1 = (byte) _data[_ip + 1]; + int b2 = _data[_ip + 2]; + int b3 = _data[_ip + 3]; + int b4 = _data[_ip + 4]; + _ip += 5; + return new Float((b1 << 8 | b2) + ((b3 << 8 | b4) / 65536.0)); + } else { + return null; + } + } + + public int nextByte() { + return _data[_ip++]; + } + + public boolean moreBytes() { + return _ip < _offset + _length; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + resetIP(); + while (moreBytes()) { + disassemble(sb); + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDef.java b/src/net/java/dev/typecast/ot/table/ClassDef.java new file mode 100644 index 000000000..9fa45c3c6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDef.java @@ -0,0 +1,33 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author David Schweinsberg + * @version $Id: ClassDef.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public abstract class ClassDef { + + public abstract int getFormat(); + + protected static ClassDef read(RandomAccessFile raf) throws IOException { + ClassDef c = null; + int format = raf.readUnsignedShort(); + if (format == 1) { + c = new ClassDefFormat1(raf); + } else if (format == 2) { + c = new ClassDefFormat2(raf); + } + return c; + } +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java b/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java new file mode 100644 index 000000000..07b85ddf9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author David Schweinsberg + * @version $Id: ClassDefFormat1.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ClassDefFormat1 extends ClassDef { + + private int startGlyph; + private int glyphCount; + private int[] classValues; + + /** Creates new ClassDefFormat1 */ + public ClassDefFormat1(RandomAccessFile raf) throws IOException { + startGlyph = raf.readUnsignedShort(); + glyphCount = raf.readUnsignedShort(); + classValues = new int[glyphCount]; + for (int i = 0; i < glyphCount; i++) { + classValues[i] = raf.readUnsignedShort(); + } + } + + public int getFormat() { + return 1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java b/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java new file mode 100644 index 000000000..f8b883c41 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java @@ -0,0 +1,37 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author David Schweinsberg + * @version $Id: ClassDefFormat2.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ClassDefFormat2 extends ClassDef { + + private int classRangeCount; + private RangeRecord[] classRangeRecords; + + /** Creates new ClassDefFormat2 */ + public ClassDefFormat2(RandomAccessFile raf) throws IOException { + classRangeCount = raf.readUnsignedShort(); + classRangeRecords = new RangeRecord[classRangeCount]; + for (int i = 0; i < classRangeCount; i++) { + classRangeRecords[i] = new RangeRecord(raf); + } + } + + public int getFormat() { + return 2; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat.java b/src/net/java/dev/typecast/ot/table/CmapFormat.java new file mode 100644 index 000000000..be88af1e6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat.java @@ -0,0 +1,134 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapFormat.java,v 1.3 2004-12-21 16:56:35 davidsch Exp $ + * @author David Schweinsberg + */ +public abstract class CmapFormat { + + public class Range { + + private int _startCode; + private int _endCode; + + protected Range(int startCode, int endCode) { + _startCode = startCode; + _endCode = endCode; + } + + public int getStartCode() { + return _startCode; + } + + public int getEndCode() { + return _endCode; + } + } + + protected int _format; + protected int _length; + protected int _language; + + protected CmapFormat(DataInput di) throws IOException { + _length = di.readUnsignedShort(); + _language = di.readUnsignedShort(); + } + + protected static CmapFormat create(int format, DataInput di) + throws IOException { + switch(format) { + case 0: + return new CmapFormat0(di); + case 2: + return new CmapFormat2(di); + case 4: + return new CmapFormat4(di); + case 6: + return new CmapFormat6(di); + default: + return new CmapFormatUnknown(format, di); + } + } + + public int getFormat() { + return _format; + } + + public int getLength() { + return _length; + } + + public int getLanguage() { + return _language; + } + + public abstract int getRangeCount(); + + public abstract Range getRange(int index) + throws ArrayIndexOutOfBoundsException; + + public abstract int mapCharCode(int charCode); + + public String toString() { + return new StringBuffer() + .append("format: ") + .append(_format) + .append(", length: ") + .append(_length) + .append(", language: ") + .append(_language).toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat0.java b/src/net/java/dev/typecast/ot/table/CmapFormat0.java new file mode 100644 index 000000000..80f42b227 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat0.java @@ -0,0 +1,92 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Simple Macintosh cmap table, mapping only the ASCII character set to glyphs. + * + * @version $Id: CmapFormat0.java,v 1.2 2004-12-21 10:22:55 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapFormat0 extends CmapFormat { + + private int[] _glyphIdArray = new int[256]; + + protected CmapFormat0(DataInput di) throws IOException { + super(di); + _format = 0; + for (int i = 0; i < 256; i++) { + _glyphIdArray[i] = di.readUnsignedByte(); + } + } + + public int getRangeCount() { + return 1; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index != 0) { + throw new ArrayIndexOutOfBoundsException(); + } + return new Range(0, 255); + } + + public int mapCharCode(int charCode) { + if (0 <= charCode && charCode < 256) { + return _glyphIdArray[charCode]; + } else { + return 0; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat2.java b/src/net/java/dev/typecast/ot/table/CmapFormat2.java new file mode 100644 index 000000000..4eeaf420a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat2.java @@ -0,0 +1,173 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * High-byte mapping through table cmap format. + * @version $Id: CmapFormat2.java,v 1.3 2004-12-21 16:56:54 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapFormat2 extends CmapFormat { + + private class SubHeader { + int _firstCode; + int _entryCount; + short _idDelta; + int _idRangeOffset; + int _arrayIndex; + } + + private int[] _subHeaderKeys = new int[256]; + private SubHeader[] _subHeaders; + private int[] _glyphIndexArray; + + protected CmapFormat2(DataInput di) throws IOException { + super(di); + _format = 2; + + int pos = 6; + + // Read the subheader keys, noting the highest value, as this will + // determine the number of subheaders to read. + int highest = 0; + for (int i = 0; i < 256; ++i) { + _subHeaderKeys[i] = di.readUnsignedShort(); + highest = Math.max(highest, _subHeaderKeys[i]); + pos += 2; + } + int subHeaderCount = highest / 8 + 1; + _subHeaders = new SubHeader[subHeaderCount]; + + // Read the subheaders, once again noting the highest glyphIndexArray + // index range. + int indexArrayOffset = 8 * subHeaderCount + 518; + highest = 0; + for (int i = 0; i < _subHeaders.length; ++i) { + SubHeader sh = new SubHeader(); + sh._firstCode = di.readUnsignedShort(); + sh._entryCount = di.readUnsignedShort(); + sh._idDelta = di.readShort(); + sh._idRangeOffset = di.readUnsignedShort(); + + // Calculate the offset into the _glyphIndexArray + pos += 8; + sh._arrayIndex = + (pos - 2 + sh._idRangeOffset - indexArrayOffset) / 2; + + // What is the highest range within the glyphIndexArray? + highest = Math.max(highest, sh._arrayIndex + sh._entryCount); + + _subHeaders[i] = sh; + } + + // Read the glyphIndexArray + _glyphIndexArray = new int[highest]; + for (int i = 0; i < _glyphIndexArray.length; ++i) { + _glyphIndexArray[i] = di.readUnsignedShort(); + } + } + + public int getRangeCount() { + return _subHeaders.length; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index < 0 || index >= _subHeaders.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + // Find the high-byte (if any) + int highByte = 0; + if (index != 0) { + for (int i = 0; i < 256; ++i) { + if (_subHeaderKeys[i] / 8 == index) { + highByte = i << 8; + break; + } + } + } + + return new Range( + highByte | _subHeaders[index]._firstCode, + highByte | (_subHeaders[index]._firstCode + + _subHeaders[index]._entryCount - 1)); + } + + public int mapCharCode(int charCode) { + + // Get the appropriate subheader + int index = 0; + int highByte = charCode >> 8; + if (highByte != 0) { + index = _subHeaderKeys[highByte] / 8; + } + SubHeader sh = _subHeaders[index]; + + // Is the charCode out-of-range? + int lowByte = charCode & 0xff; + if (lowByte < sh._firstCode || + lowByte >= (sh._firstCode + sh._entryCount)) { + return 0; + } + + // Now calculate the glyph index + int glyphIndex = + _glyphIndexArray[sh._arrayIndex + (lowByte - sh._firstCode)]; + if (glyphIndex != 0) { + glyphIndex += sh._idDelta; + glyphIndex %= 65536; + } + return glyphIndex; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat4.java b/src/net/java/dev/typecast/ot/table/CmapFormat4.java new file mode 100644 index 000000000..3748a8f84 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat4.java @@ -0,0 +1,165 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapFormat4.java,v 1.3 2004-12-21 16:57:23 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapFormat4 extends CmapFormat { + + private int _segCountX2; + private int _searchRange; + private int _entrySelector; + private int _rangeShift; + private int[] _endCode; + private int[] _startCode; + private int[] _idDelta; + private int[] _idRangeOffset; + private int[] _glyphIdArray; + private int _segCount; + + protected CmapFormat4(DataInput di) throws IOException { + super(di); // 6 + _format = 4; + _segCountX2 = di.readUnsignedShort(); // +2 (8) + _segCount = _segCountX2 / 2; + _endCode = new int[_segCount]; + _startCode = new int[_segCount]; + _idDelta = new int[_segCount]; + _idRangeOffset = new int[_segCount]; + _searchRange = di.readUnsignedShort(); // +2 (10) + _entrySelector = di.readUnsignedShort(); // +2 (12) + _rangeShift = di.readUnsignedShort(); // +2 (14) + for (int i = 0; i < _segCount; i++) { + _endCode[i] = di.readUnsignedShort(); + } // + 2*segCount (2*segCount + 14) + di.readUnsignedShort(); // reservePad +2 (2*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _startCode[i] = di.readUnsignedShort(); + } // + 2*segCount (4*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _idDelta[i] = di.readUnsignedShort(); + } // + 2*segCount (6*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _idRangeOffset[i] = di.readUnsignedShort(); + } // + 2*segCount (8*segCount + 16) + + // Whatever remains of this header belongs in glyphIdArray + int count = (_length - (8*_segCount + 16)) / 2; + _glyphIdArray = new int[count]; + for (int i = 0; i < count; i++) { + _glyphIdArray[i] = di.readUnsignedShort(); + } // + 2*count (8*segCount + 2*count + 18) + + // Are there any padding bytes we need to consume? +// int leftover = length - (8*segCount + 2*count + 18); +// if (leftover > 0) { +// di.skipBytes(leftover); +// } + } + + public int getRangeCount() { + return _segCount; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index < 0 || index >= _segCount) { + throw new ArrayIndexOutOfBoundsException(); + } + return new Range(_startCode[index], _endCode[index]); + } + + public int mapCharCode(int charCode) { + try { + for (int i = 0; i < _segCount; i++) { + if (_endCode[i] >= charCode) { + if (_startCode[i] <= charCode) { + if (_idRangeOffset[i] > 0) { + return _glyphIdArray[_idRangeOffset[i]/2 + (charCode - _startCode[i]) - (_segCount - i)]; + } else { + return (_idDelta[i] + charCode) % 65536; + } + } else { + break; + } + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println("error: Array out of bounds - " + e.getMessage()); + } + return 0; + } + + public String toString() { + return new StringBuffer() + .append(super.toString()) + .append(", segCountX2: ") + .append(_segCountX2) + .append(", searchRange: ") + .append(_searchRange) + .append(", entrySelector: ") + .append(_entrySelector) + .append(", rangeShift: ") + .append(_rangeShift) + .append(", endCode: ") + .append(_endCode) + .append(", startCode: ") + .append(_endCode) + .append(", idDelta: ") + .append(_idDelta) + .append(", idRangeOffset: ") + .append(_idRangeOffset).toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat6.java b/src/net/java/dev/typecast/ot/table/CmapFormat6.java new file mode 100644 index 000000000..f9b398aab --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat6.java @@ -0,0 +1,87 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * TODO: To be implemented + * @version $Id: CmapFormat6.java,v 1.2 2004-12-21 10:22:56 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapFormat6 extends CmapFormat { + + private short _firstCode; + private short _entryCount; + private short[] _glyphIdArray; + + protected CmapFormat6(DataInput di) throws IOException { + super(di); + _format = 6; + + // HACK: As this is not yet implemented, we need to skip over the bytes + // we should be consuming + //di.skipBytes(_length - 4); + } + + public int getRangeCount() { + return 0; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + throw new ArrayIndexOutOfBoundsException(); + } + + public int mapCharCode(int charCode) { + return 0; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java b/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java new file mode 100644 index 000000000..01ca600f1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java @@ -0,0 +1,54 @@ +/* + * $Id: CmapFormatUnknown.java,v 1.1 2004-12-21 10:21:23 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * When we encounter a cmap format we don't understand, we can use this class + * to hold the bare minimum information about it. + * @author David Schweinsberg + * @version $Id: CmapFormatUnknown.java,v 1.1 2004-12-21 10:21:23 davidsch Exp $ + */ +public class CmapFormatUnknown extends CmapFormat { + + /** Creates a new instance of CmapFormatUnknown */ + protected CmapFormatUnknown(int format, DataInput di) throws IOException { + super(di); + _format = format; + + // We don't know how to handle this data, so we'll just skip over it + di.skipBytes(_length - 4); + } + + public int getRangeCount() { + return 0; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + throw new ArrayIndexOutOfBoundsException(); + } + + public int mapCharCode(int charCode) { + return 0; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java b/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java new file mode 100644 index 000000000..c82e270fb --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java @@ -0,0 +1,117 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapIndexEntry.java,v 1.2 2004-12-21 10:22:56 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapIndexEntry implements Comparable { + + private int _platformId; + private int _encodingId; + private int _offset; + private CmapFormat _format; + + protected CmapIndexEntry(DataInput di) throws IOException { + _platformId = di.readUnsignedShort(); + _encodingId = di.readUnsignedShort(); + _offset = di.readInt(); + } + + public int getPlatformId() { + return _platformId; + } + + public int getEncodingId() { + return _encodingId; + } + + public int getOffset() { + return _offset; + } + + public CmapFormat getFormat() { + return _format; + } + + public void setFormat(CmapFormat format) { + _format = format; + } + + public String toString() { + return new StringBuffer() + .append("platform id: ") + .append(_platformId) + .append(" (") + .append(ID.getPlatformName((short) _platformId)) + .append("), encoding id: ") + .append(_encodingId) + .append(" (") + .append(ID.getEncodingName((short) _platformId, (short) _encodingId)) + .append("), offset: ") + .append(_offset).toString(); + } + + public int compareTo(java.lang.Object obj) { + CmapIndexEntry entry = (CmapIndexEntry) obj; + if (getOffset() < entry.getOffset()) { + return -1; + } else if (getOffset() > entry.getOffset()) { + return 1; + } else { + return 0; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapTable.java b/src/net/java/dev/typecast/ot/table/CmapTable.java new file mode 100644 index 000000000..de69cc1f0 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapTable.java @@ -0,0 +1,161 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import java.util.Arrays; + +/** + * @version $Id: CmapTable.java,v 1.3 2004-12-21 10:22:56 davidsch Exp $ + * @author David Schweinsberg + */ +public class CmapTable implements Table { + + private DirectoryEntry _de; + private int _version; + private int _numTables; + private CmapIndexEntry[] _entries; + + protected CmapTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numTables = di.readUnsignedShort(); + long bytesRead = 4; + _entries = new CmapIndexEntry[_numTables]; + + // Get each of the index entries + for (int i = 0; i < _numTables; i++) { + _entries[i] = new CmapIndexEntry(di); + bytesRead += 8; + } + + // Sort into their order of offset + Arrays.sort(_entries); + + // Get each of the tables + int lastOffset = 0; + CmapFormat lastFormat = null; + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getOffset() == lastOffset) { + + // This is a multiple entry + _entries[i].setFormat(lastFormat); + continue; + } else if (_entries[i].getOffset() > bytesRead) { + di.skipBytes(_entries[i].getOffset() - (int) bytesRead); + } else if (_entries[i].getOffset() != bytesRead) { + + // Something is amiss + throw new IOException(); + } + int formatType = di.readUnsignedShort(); + lastFormat = CmapFormat.create(formatType, di); + lastOffset = _entries[i].getOffset(); + _entries[i].setFormat(lastFormat); + bytesRead += lastFormat.getLength(); + } + } + + public int getVersion() { + return _version; + } + + public int getNumTables() { + return _numTables; + } + + public CmapIndexEntry getCmapIndexEntry(int i) { + return _entries[i]; + } + + public CmapFormat getCmapFormat(short platformId, short encodingId) { + + // Find the requested format + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getPlatformId() == platformId + && _entries[i].getEncodingId() == encodingId) { + return _entries[i].getFormat(); + } + } + return null; + } + + public int getType() { + return cmap; + } + + public String toString() { + StringBuffer sb = new StringBuffer().append("cmap\n"); + + // Get each of the index entries + for (int i = 0; i < _numTables; i++) { + sb.append("\t").append(_entries[i].toString()).append("\n"); + } + + // Get each of the tables +// for (int i = 0; i < numTables; i++) { +// sb.append("\t").append(formats[i].toString()).append("\n"); +// } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Coverage.java b/src/net/java/dev/typecast/ot/table/Coverage.java new file mode 100644 index 000000000..3c6cf0409 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Coverage.java @@ -0,0 +1,83 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: Coverage.java,v 1.3 2007-01-24 09:43:30 davidsch Exp $ + */ +public abstract class Coverage { + + public abstract int getFormat(); + + /** + * @param glyphId The ID of the glyph to find. + * @return The index of the glyph within the coverage, or -1 if the glyph + * can't be found. + */ + public abstract int findGlyph(int glyphId); + + protected static Coverage read(DataInput di) throws IOException { + Coverage c = null; + int format = di.readUnsignedShort(); + if (format == 1) { + c = new CoverageFormat1(di); + } else if (format == 2) { + c = new CoverageFormat2(di); + } + return c; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CoverageFormat1.java b/src/net/java/dev/typecast/ot/table/CoverageFormat1.java new file mode 100644 index 000000000..a81eb0f1e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CoverageFormat1.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: CoverageFormat1.java,v 1.2 2007-01-24 09:43:30 davidsch Exp $ + */ +public class CoverageFormat1 extends Coverage { + + private int _glyphCount; + private int[] _glyphIds; + + /** Creates new CoverageFormat1 */ + protected CoverageFormat1(DataInput di) throws IOException { + _glyphCount = di.readUnsignedShort(); + _glyphIds = new int[_glyphCount]; + for (int i = 0; i < _glyphCount; i++) { + _glyphIds[i] = di.readUnsignedShort(); + } + } + + public int getFormat() { + return 1; + } + + public int findGlyph(int glyphId) { + for (int i = 0; i < _glyphCount; i++) { + if (_glyphIds[i] == glyphId) { + return i; + } + } + return -1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CoverageFormat2.java b/src/net/java/dev/typecast/ot/table/CoverageFormat2.java new file mode 100644 index 000000000..a30489647 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CoverageFormat2.java @@ -0,0 +1,89 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: CoverageFormat2.java,v 1.2 2007-01-24 09:43:30 davidsch Exp $ + */ +public class CoverageFormat2 extends Coverage { + + private int _rangeCount; + private RangeRecord[] _rangeRecords; + + /** Creates new CoverageFormat2 */ + protected CoverageFormat2(DataInput di) throws IOException { + _rangeCount = di.readUnsignedShort(); + _rangeRecords = new RangeRecord[_rangeCount]; + for (int i = 0; i < _rangeCount; i++) { + _rangeRecords[i] = new RangeRecord(di); + } + } + + public int getFormat() { + return 2; + } + + public int findGlyph(int glyphId) { + for (int i = 0; i < _rangeCount; i++) { + int n = _rangeRecords[i].getCoverageIndex(glyphId); + if (n > -1) { + return n; + } + } + return -1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CvtTable.java b/src/net/java/dev/typecast/ot/table/CvtTable.java new file mode 100644 index 000000000..6035c6378 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CvtTable.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CvtTable.java,v 1.1.1.1 2004-12-05 23:14:36 davidsch Exp $ + * @author David Schweinsberg + */ +public class CvtTable implements Table { + + private DirectoryEntry de; + private short[] values; + + protected CvtTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + int len = de.getLength() / 2; + values = new short[len]; + for (int i = 0; i < len; i++) { + values[i] = di.readShort(); + } + } + + public int getType() { + return cvt; + } + + public short[] getValues() { + return values; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'cvt ' Table - Control Value Table\n----------------------------------\n"); + sb.append("Size = ").append(0).append(" bytes, ").append(values.length).append(" entries\n"); + sb.append(" Values\n ------\n"); + for (int i = 0; i < values.length; i++) { + sb.append(" ").append(i).append(": ").append(values[i]).append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Device.java b/src/net/java/dev/typecast/ot/table/Device.java new file mode 100644 index 000000000..75c302acd --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Device.java @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author David Schweinsberg + * @version $Id: Device.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + */ +public class Device extends Object { + + private int startSize; + private int endSize; + private int deltaFormat; + private int[] deltaValues; + + /** Creates new Device */ + public Device(RandomAccessFile raf) throws IOException { + startSize = raf.readUnsignedShort(); + endSize = raf.readUnsignedShort(); + deltaFormat = raf.readUnsignedShort(); + int size = startSize - endSize; + switch (deltaFormat) { + case 1: + size = (size % 8 == 0) ? size / 8 : size / 8 + 1; + break; + case 2: + size = (size % 4 == 0) ? size / 4 : size / 4 + 1; + break; + case 3: + size = (size % 2 == 0) ? size / 2 : size / 2 + 1; + break; + } + deltaValues = new int[size]; + for (int i = 0; i < size; i++) { + deltaValues[i] = raf.readUnsignedShort(); + } + } + + +} diff --git a/src/net/java/dev/typecast/ot/table/DirectoryEntry.java b/src/net/java/dev/typecast/ot/table/DirectoryEntry.java new file mode 100644 index 000000000..c0f2f9bc1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DirectoryEntry.java @@ -0,0 +1,115 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: DirectoryEntry.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author David Schweinsberg + */ +public class DirectoryEntry implements Cloneable { + + private int _tag; + private int _checksum; + private int _offset; + private int _length; + + protected DirectoryEntry(DataInput di) throws IOException { + _tag = di.readInt(); + _checksum = di.readInt(); + _offset = di.readInt(); + _length = di.readInt(); + } + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + public int getChecksum() { + return _checksum; + } + + public int getLength() { + return _length; + } + + public int getOffset() { + return _offset; + } + + public int getTag() { + return _tag; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } + + public String toString() { + return new StringBuffer() + .append("'").append(getTagAsString()) + .append("' - chksm = 0x").append(Integer.toHexString(_checksum)) + .append(", off = 0x").append(Integer.toHexString(_offset)) + .append(", len = ").append(_length) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/DsigEntry.java b/src/net/java/dev/typecast/ot/table/DsigEntry.java new file mode 100644 index 000000000..6ce41ec48 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DsigEntry.java @@ -0,0 +1,43 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: DsigEntry.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + * @author David Schweinsberg + */ +public class DsigEntry { + + private int format; + private int length; + private int offset; + + /** Creates new DsigEntry */ + protected DsigEntry(DataInput di) throws IOException { + format = di.readInt(); + length = di.readInt(); + offset = di.readInt(); + } + + public int getFormat() { + return format; + } + + public int getLength() { + return length; + } + + public int getOffset() { + return offset; + } +} diff --git a/src/net/java/dev/typecast/ot/table/DsigTable.java b/src/net/java/dev/typecast/ot/table/DsigTable.java new file mode 100644 index 000000000..8d63800d4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DsigTable.java @@ -0,0 +1,69 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: DsigTable.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + * @author David Schweinsberg + */ +public class DsigTable implements Table { + + private DirectoryEntry de; + private int version; + private int numSigs; + private int flag; + private DsigEntry[] dsigEntry; + private SignatureBlock[] sigBlocks; + + /** Creates new DsigTable */ + protected DsigTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + numSigs = di.readUnsignedShort(); + flag = di.readUnsignedShort(); + dsigEntry = new DsigEntry[numSigs]; + sigBlocks = new SignatureBlock[numSigs]; + for (int i = 0; i < numSigs; i++) { + dsigEntry[i] = new DsigEntry(di); + } + for (int i = 0; i < numSigs; i++) { + sigBlocks[i] = new SignatureBlock(di); + } + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return DSIG; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + + public String toString() { + StringBuffer sb = new StringBuffer().append("DSIG\n"); + for (int i = 0; i < numSigs; i++) { + sb.append(sigBlocks[i].toString()); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/Feature.java b/src/net/java/dev/typecast/ot/table/Feature.java new file mode 100644 index 000000000..34adf4662 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Feature.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: Feature.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class Feature { + + private int _featureParams; + private int _lookupCount; + private int[] _lookupListIndex; + + /** Creates new Feature */ + protected Feature(DataInput di) throws IOException { + _featureParams = di.readUnsignedShort(); + _lookupCount = di.readUnsignedShort(); + _lookupListIndex = new int[_lookupCount]; + for (int i = 0; i < _lookupCount; i++) { + _lookupListIndex[i] = di.readUnsignedShort(); + } + } + + public int getLookupCount() { + return _lookupCount; + } + + public int getLookupListIndex(int i) { + return _lookupListIndex[i]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureList.java b/src/net/java/dev/typecast/ot/table/FeatureList.java new file mode 100644 index 000000000..8f17c461f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureList.java @@ -0,0 +1,118 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: FeatureList.java,v 1.3 2007-01-24 09:54:44 davidsch Exp $ + */ +public class FeatureList { + + private int _featureCount; + private FeatureRecord[] _featureRecords; + private Feature[] _features; + + /** Creates new FeatureList */ + public FeatureList(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _featureCount = dis.readUnsignedShort(); + _featureRecords = new FeatureRecord[_featureCount]; + _features = new Feature[_featureCount]; + for (int i = 0; i < _featureCount; i++) { + _featureRecords[i] = new FeatureRecord(dis); + } + for (int i = 0; i < _featureCount; i++) { + dis.reset(); + dis.skipBytes(offset + _featureRecords[i].getOffset()); + _features[i] = new Feature(dis); + } + } + + public int getFeatureCount() { + return _featureCount; + } + + public FeatureRecord getFeatureRecord(int i) { + return _featureRecords[i]; + } + + public Feature getFeature(int i) { + return _features[i]; + } + + public Feature findFeature(LangSys langSys, String tag) { + if (tag.length() != 4) { + return null; + } + int tagVal = ((tag.charAt(0)<<24) + | (tag.charAt(1)<<16) + | (tag.charAt(2)<<8) + | tag.charAt(3)); + for (int i = 0; i < _featureCount; i++) { + if (_featureRecords[i].getTag() == tagVal) { + if (langSys.isFeatureIndexed(i)) { + return _features[i]; + } + } + } + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureRecord.java b/src/net/java/dev/typecast/ot/table/FeatureRecord.java new file mode 100644 index 000000000..7c2788892 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: FeatureRecord.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class FeatureRecord { + + private int _tag; + private int _offset; + + /** Creates new FeatureRecord */ + protected FeatureRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureTags.java b/src/net/java/dev/typecast/ot/table/FeatureTags.java new file mode 100644 index 000000000..8d573d0c6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureTags.java @@ -0,0 +1,63 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Definition of Feature tags + * + * @version $Id: FeatureTags.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + * @author Vincent Hardy + */ +public interface FeatureTags { + public static final String FEATURE_TAG_INIT = "init"; + public static final String FEATURE_TAG_MEDI = "medi"; + public static final String FEATURE_TAG_FINA = "fina"; +} diff --git a/src/net/java/dev/typecast/ot/table/FpgmTable.java b/src/net/java/dev/typecast/ot/table/FpgmTable.java new file mode 100644 index 000000000..37a2ae045 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FpgmTable.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: FpgmTable.java,v 1.1.1.1 2004-12-05 23:14:38 davidsch Exp $ + * @author David Schweinsberg + */ +public class FpgmTable extends Program implements Table { + + private DirectoryEntry de; + + protected FpgmTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + readInstructions(di, de.getLength()); + } + + public int getType() { + return fpgm; + } + + public String toString() { + return Disassembler.disassemble(getInstructions(), 0); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GaspRange.java b/src/net/java/dev/typecast/ot/table/GaspRange.java new file mode 100644 index 000000000..9f343e942 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GaspRange.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: GaspRange.java,v 1.1.1.1 2004-12-05 23:14:38 davidsch Exp $ + */ +public class GaspRange { + + public static final int GASP_GRIDFIT = 1; + public static final int GASP_DOGRAY = 2; + + private int rangeMaxPPEM; + private int rangeGaspBehavior; + + /** Creates new GaspRange */ + protected GaspRange(DataInput di) throws IOException { + rangeMaxPPEM = di.readUnsignedShort(); + rangeGaspBehavior = di.readUnsignedShort(); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(" rangeMaxPPEM: ").append(rangeMaxPPEM) + .append("\n rangeGaspBehavior: 0x").append(rangeGaspBehavior); + if ((rangeGaspBehavior & GASP_GRIDFIT) != 0) { + sb.append("- GASP_GRIDFIT "); + } + if ((rangeGaspBehavior & GASP_DOGRAY) != 0) { + sb.append("- GASP_DOGRAY"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GaspTable.java b/src/net/java/dev/typecast/ot/table/GaspTable.java new file mode 100644 index 000000000..50a1bcd93 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GaspTable.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: GaspTable.java,v 1.1.1.1 2004-12-05 23:14:39 davidsch Exp $ + */ +public class GaspTable implements Table { + + private DirectoryEntry de; + private int version; + private int numRanges; + private GaspRange[] gaspRange; + + /** Creates new GaspTable */ + protected GaspTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + numRanges = di.readUnsignedShort(); + gaspRange = new GaspRange[numRanges]; + for (int i = 0; i < numRanges; i++) { + gaspRange[i] = new GaspRange(di); + } + } + + public int getType() { + return gasp; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'gasp' Table - Grid-fitting And Scan-conversion Procedure\n---------------------------------------------------------"); + sb.append("\n 'gasp' version: ").append(version); + sb.append("\n numRanges: ").append(numRanges); + for (int i = 0; i < numRanges; i++) { + sb.append("\n\n gasp Range ").append(i).append("\n"); + sb.append(gaspRange[i].toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java b/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java new file mode 100644 index 000000000..0a3f91a2a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java @@ -0,0 +1,200 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: GlyfCompositeComp.java,v 1.3 2010-08-10 11:41:55 davidsch Exp $ + * @author David Schweinsberg + */ +public class GlyfCompositeComp { + + public static final short ARG_1_AND_2_ARE_WORDS = 0x0001; + public static final short ARGS_ARE_XY_VALUES = 0x0002; + public static final short ROUND_XY_TO_GRID = 0x0004; + public static final short WE_HAVE_A_SCALE = 0x0008; + public static final short MORE_COMPONENTS = 0x0020; + public static final short WE_HAVE_AN_X_AND_Y_SCALE = 0x0040; + public static final short WE_HAVE_A_TWO_BY_TWO = 0x0080; + public static final short WE_HAVE_INSTRUCTIONS = 0x0100; + public static final short USE_MY_METRICS = 0x0200; + + private int _firstIndex; + private int _firstContour; + private short _argument1; + private short _argument2; + private int _flags; + private int _glyphIndex; + private double _xscale = 1.0; + private double _yscale = 1.0; + private double _scale01 = 0.0; + private double _scale10 = 0.0; + private int _xtranslate = 0; + private int _ytranslate = 0; + private int _point1 = 0; + private int _point2 = 0; + + protected GlyfCompositeComp(int firstIndex, int firstContour, DataInput di) + throws IOException { + _firstIndex = firstIndex; + _firstContour = firstContour; + _flags = di.readUnsignedShort(); + _glyphIndex = di.readUnsignedShort(); + + // Get the arguments as just their raw values + if ((_flags & ARG_1_AND_2_ARE_WORDS) != 0) { + _argument1 = di.readShort(); + _argument2 = di.readShort(); + } else { + _argument1 = (short) di.readByte(); + _argument2 = (short) di.readByte(); + } + + // Assign the arguments according to the flags + if ((_flags & ARGS_ARE_XY_VALUES) != 0) { + _xtranslate = _argument1; + _ytranslate = _argument2; + } else { + _point1 = _argument1; + _point2 = _argument2; + } + + // Get the scale values (if any) + if ((_flags & WE_HAVE_A_SCALE) != 0) { + int i = di.readShort(); + _xscale = _yscale = (double) i / (double) 0x4000; + } else if ((_flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) { + short i = di.readShort(); + _xscale = (double) i / (double) 0x4000; + i = di.readShort(); + _yscale = (double) i / (double) 0x4000; + } else if ((_flags & WE_HAVE_A_TWO_BY_TWO) != 0) { + int i = di.readShort(); + _xscale = (double) i / (double) 0x4000; + i = di.readShort(); + _scale01 = (double) i / (double) 0x4000; + i = di.readShort(); + _scale10 = (double) i / (double) 0x4000; + i = di.readShort(); + _yscale = (double) i / (double) 0x4000; + } + } + + public int getFirstIndex() { + return _firstIndex; + } + + public int getFirstContour() { + return _firstContour; + } + + public short getArgument1() { + return _argument1; + } + + public short getArgument2() { + return _argument2; + } + + public int getFlags() { + return _flags; + } + + public int getGlyphIndex() { + return _glyphIndex; + } + + public double getScale01() { + return _scale01; + } + + public double getScale10() { + return _scale10; + } + + public double getXScale() { + return _xscale; + } + + public double getYScale() { + return _yscale; + } + + public int getXTranslate() { + return _xtranslate; + } + + public int getYTranslate() { + return _ytranslate; + } + + /** + * Transforms an x-coordinate of a point for this component. + * @param x The x-coordinate of the point to transform + * @param y The y-coordinate of the point to transform + * @return The transformed x-coordinate + */ + public int scaleX(int x, int y) { + return (int)((double) x * _xscale + (double) y * _scale10); + } + + /** + * Transforms a y-coordinate of a point for this component. + * @param x The x-coordinate of the point to transform + * @param y The y-coordinate of the point to transform + * @return The transformed y-coordinate + */ + public int scaleY(int x, int y) { + return (int)((double) x * _scale01 + (double) y * _yscale); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java b/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java new file mode 100644 index 000000000..97c0b0f79 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java @@ -0,0 +1,202 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import java.util.ArrayList; + +/** + * Glyph description for composite glyphs. Composite glyphs are made up of one + * or more simple glyphs, usually with some sort of transformation applied to + * each. + * + * @version $Id: GlyfCompositeDescript.java,v 1.5 2007-01-25 08:43:18 davidsch Exp $ + * @author David Schweinsberg + */ +public class GlyfCompositeDescript extends GlyfDescript { + + private ArrayList _components = + new ArrayList(); + + public GlyfCompositeDescript( + GlyfTable parentTable, + int glyphIndex, + DataInput di) throws IOException { + super(parentTable, glyphIndex, (short) -1, di); + + // Get all of the composite components + GlyfCompositeComp comp; + int firstIndex = 0; + int firstContour = 0; + try { + do { + _components.add(comp = new GlyfCompositeComp(firstIndex, firstContour, di)); + GlyfDescript desc = parentTable.getDescription(comp.getGlyphIndex()); + if (desc != null) { + firstIndex += desc.getPointCount(); + firstContour += desc.getContourCount(); + } + } while ((comp.getFlags() & GlyfCompositeComp.MORE_COMPONENTS) != 0); + + // Are there hinting intructions to read? + if ((comp.getFlags() & GlyfCompositeComp.WE_HAVE_INSTRUCTIONS) != 0) { + readInstructions(di, di.readShort()); + } + } catch (IOException e) { + throw e; +// } catch (Exception e) { +// int foo = 0; + } + } + + public int getEndPtOfContours(int i) { + GlyfCompositeComp c = getCompositeCompEndPt(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + return gd.getEndPtOfContours(i - c.getFirstContour()) + c.getFirstIndex(); + } + return 0; + } + + public byte getFlags(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + return gd.getFlags(i - c.getFirstIndex()); + } + return 0; + } + + public short getXCoordinate(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + int n = i - c.getFirstIndex(); + int x = gd.getXCoordinate(n); + int y = gd.getYCoordinate(n); + short x1 = (short) c.scaleX(x, y); + x1 += c.getXTranslate(); + return x1; + } + return 0; + } + + public short getYCoordinate(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + int n = i - c.getFirstIndex(); + int x = gd.getXCoordinate(n); + int y = gd.getYCoordinate(n); + short y1 = (short) c.scaleY(x, y); + y1 += c.getYTranslate(); + return y1; + } + return 0; + } + + public boolean isComposite() { + return true; + } + + public int getPointCount() { + GlyfCompositeComp c = _components.get(_components.size()-1); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (gd != null) { + return c.getFirstIndex() + gd.getPointCount(); + } else { + return 0; + } + } + + public int getContourCount() { + GlyfCompositeComp c = _components.get(_components.size()-1); + return c.getFirstContour() + _parentTable.getDescription(c.getGlyphIndex()).getContourCount(); + } + + public int getComponentIndex(int i) { + return _components.get(i).getFirstIndex(); + } + + public int getComponentCount() { + return _components.size(); + } + + public GlyfCompositeComp getComponent(int i) { + return _components.get(i); + } + + protected GlyfCompositeComp getCompositeComp(int i) { + GlyfCompositeComp c; + for (int n = 0; n < _components.size(); n++) { + c = _components.get(n); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (c.getFirstIndex() <= i && i < (c.getFirstIndex() + gd.getPointCount())) { + return c; + } + } + return null; + } + + protected GlyfCompositeComp getCompositeCompEndPt(int i) { + GlyfCompositeComp c; + for (int j = 0; j < _components.size(); j++) { + c = _components.get(j); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (c.getFirstContour() <= i && i < (c.getFirstContour() + gd.getContourCount())) { + return c; + } + } + return null; + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfDescript.java b/src/net/java/dev/typecast/ot/table/GlyfDescript.java new file mode 100644 index 000000000..49ae5b494 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfDescript.java @@ -0,0 +1,124 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: GlyfDescript.java,v 1.3 2007-01-24 09:47:48 davidsch Exp $ + * @author David Schweinsberg + */ +public abstract class GlyfDescript extends Program implements GlyphDescription { + + // flags + public static final byte onCurve = 0x01; + public static final byte xShortVector = 0x02; + public static final byte yShortVector = 0x04; + public static final byte repeat = 0x08; + public static final byte xDual = 0x10; + public static final byte yDual = 0x20; + + protected GlyfTable _parentTable; + private int _glyphIndex; + private int _numberOfContours; + private short _xMin; + private short _yMin; + private short _xMax; + private short _yMax; + + protected GlyfDescript( + GlyfTable parentTable, + int glyphIndex, + short numberOfContours, + DataInput di) throws IOException { + _parentTable = parentTable; + _numberOfContours = numberOfContours; + _xMin = di.readShort(); + _yMin = di.readShort(); + _xMax = di.readShort(); + _yMax = di.readShort(); + } + + public int getNumberOfContours() { + return _numberOfContours; + } + + public int getGlyphIndex() { + return _glyphIndex; + } + + public short getXMaximum() { + return _xMax; + } + + public short getXMinimum() { + return _xMin; + } + + public short getYMaximum() { + return _yMax; + } + + public short getYMinimum() { + return _yMin; + } + + public String toString() { + return new StringBuffer() + .append(" numberOfContours: ").append(_numberOfContours) + .append("\n xMin: ").append(_xMin) + .append("\n yMin: ").append(_yMin) + .append("\n xMax: ").append(_xMax) + .append("\n yMax: ").append(_yMax) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java b/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java new file mode 100644 index 000000000..e2c3a2c84 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java @@ -0,0 +1,245 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: GlyfSimpleDescript.java,v 1.3 2007-01-24 09:47:47 davidsch Exp $ + * @author David Schweinsberg + */ +public class GlyfSimpleDescript extends GlyfDescript { + + private int[] _endPtsOfContours; + private byte[] _flags; + private short[] _xCoordinates; + private short[] _yCoordinates; + private int _count; + + public GlyfSimpleDescript( + GlyfTable parentTable, + int glyphIndex, + short numberOfContours, + DataInput di) throws IOException { + super(parentTable, glyphIndex, numberOfContours, di); + + // Simple glyph description + _endPtsOfContours = new int[numberOfContours]; + for (int i = 0; i < numberOfContours; i++) { + _endPtsOfContours[i] = di.readShort(); + } + + // The last end point index reveals the total number of points + _count = _endPtsOfContours[numberOfContours-1] + 1; + _flags = new byte[_count]; + _xCoordinates = new short[_count]; + _yCoordinates = new short[_count]; + + int instructionCount = di.readShort(); + readInstructions(di, instructionCount); + readFlags(_count, di); + readCoords(_count, di); + } + + public int getEndPtOfContours(int i) { + return _endPtsOfContours[i]; + } + + public byte getFlags(int i) { + return _flags[i]; + } + + public short getXCoordinate(int i) { + return _xCoordinates[i]; + } + + public short getYCoordinate(int i) { + return _yCoordinates[i]; + } + + public boolean isComposite() { + return false; + } + + public int getPointCount() { + return _count; + } + + public int getContourCount() { + return getNumberOfContours(); + } + /* + public int getComponentIndex(int c) { + return 0; + } + + public int getComponentCount() { + return 1; + } + */ + /** + * The table is stored as relative values, but we'll store them as absolutes + */ + private void readCoords(int count, DataInput di) throws IOException { + short x = 0; + short y = 0; + for (int i = 0; i < count; i++) { + if ((_flags[i] & xDual) != 0) { + if ((_flags[i] & xShortVector) != 0) { + x += (short) di.readUnsignedByte(); + } + } else { + if ((_flags[i] & xShortVector) != 0) { + x += (short) -((short) di.readUnsignedByte()); + } else { + x += di.readShort(); + } + } + _xCoordinates[i] = x; + } + + for (int i = 0; i < count; i++) { + if ((_flags[i] & yDual) != 0) { + if ((_flags[i] & yShortVector) != 0) { + y += (short) di.readUnsignedByte(); + } + } else { + if ((_flags[i] & yShortVector) != 0) { + y += (short) -((short) di.readUnsignedByte()); + } else { + y += di.readShort(); + } + } + _yCoordinates[i] = y; + } + } + + /** + * The flags are run-length encoded + */ + private void readFlags(int flagCount, DataInput di) throws IOException { + try { + for (int index = 0; index < flagCount; index++) { + _flags[index] = di.readByte(); + if ((_flags[index] & repeat) != 0) { + int repeats = di.readByte(); + for (int i = 1; i <= repeats; i++) { + _flags[index + i] = _flags[index]; + } + index += repeats; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("error: array index out of bounds"); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(super.toString()); + sb.append("\n\n EndPoints\n ---------"); + for (int i = 0; i < _endPtsOfContours.length; i++) { + sb.append("\n ").append(i).append(": ").append(_endPtsOfContours[i]); + } + sb.append("\n\n Length of Instructions: "); + sb.append(getInstructions().length).append("\n"); + sb.append(Disassembler.disassemble(getInstructions(), 8)); + sb.append("\n Flags\n -----"); + for (int i = 0; i < _flags.length; i++) { + sb.append("\n ").append(i).append(": "); + if ((_flags[i] & 0x20) != 0) { + sb.append("YDual "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x10) != 0) { + sb.append("XDual "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x08) != 0) { + sb.append("Repeat "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x04) != 0) { + sb.append("Y-Short "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x02) != 0) { + sb.append("X-Short "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x01) != 0) { + sb.append("On"); + } else { + sb.append(" "); + } + } + sb.append("\n\n Coordinates\n -----------"); + short oldX = 0; + short oldY = 0; + for (int i = 0; i < _xCoordinates.length; i++) { + sb.append("\n ").append(i) + .append(": Rel (").append(_xCoordinates[i] - oldX) + .append(", ").append(_yCoordinates[i] - oldY) + .append(") -> Abs (").append(_xCoordinates[i]) + .append(", ").append(_yCoordinates[i]).append(")"); + oldX = _xCoordinates[i]; + oldY = _yCoordinates[i]; + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfTable.java b/src/net/java/dev/typecast/ot/table/GlyfTable.java new file mode 100644 index 000000000..03f519db2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfTable.java @@ -0,0 +1,132 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +/** + * @version $Id: GlyfTable.java,v 1.6 2010-08-10 11:46:30 davidsch Exp $ + * @author David Schweinsberg + */ +public class GlyfTable implements Table { + + private DirectoryEntry _de; + private GlyfDescript[] _descript; + + protected GlyfTable( + DirectoryEntry de, + DataInput di, + MaxpTable maxp, + LocaTable loca) throws IOException { + _de = (DirectoryEntry) de.clone(); + _descript = new GlyfDescript[maxp.getNumGlyphs()]; + + // Buffer the whole table so we can randomly access it + byte[] buf = new byte[de.getLength()]; + di.readFully(buf); + ByteArrayInputStream bais = new ByteArrayInputStream(buf); + + // Process all the simple glyphs + for (int i = 0; i < maxp.getNumGlyphs(); i++) { + int len = loca.getOffset(i + 1) - loca.getOffset(i); + if (len > 0) { + bais.reset(); + bais.skip(loca.getOffset(i)); + DataInputStream dis = new DataInputStream(bais); + short numberOfContours = dis.readShort(); + if (numberOfContours >= 0) { + _descript[i] = new GlyfSimpleDescript(this, i, numberOfContours, dis); + } + } else { + _descript[i] = null; + } + } + + // Now do all the composite glyphs + for (int i = 0; i < maxp.getNumGlyphs(); i++) { + int len = loca.getOffset(i + 1) - loca.getOffset(i); + if (len > 0) { + bais.reset(); + bais.skip(loca.getOffset(i)); + DataInputStream dis = new DataInputStream(bais); + short numberOfContours = dis.readShort(); + if (numberOfContours < 0) { + _descript[i] = new GlyfCompositeDescript(this, i, dis); + } + } + } + } + + public GlyfDescript getDescription(int i) { + if (i < _descript.length) { + return _descript[i]; + } else { + return null; + } + } + + public int getType() { + return glyf; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyphDescription.java b/src/net/java/dev/typecast/ot/table/GlyphDescription.java new file mode 100644 index 000000000..b23f31364 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyphDescription.java @@ -0,0 +1,86 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Specifies access to glyph description classes, simple and composite. + * @version $Id: GlyphDescription.java,v 1.3 2007-01-24 09:47:45 davidsch Exp $ + * @author David Schweinsberg + */ +public interface GlyphDescription { + + public int getGlyphIndex(); + + public int getEndPtOfContours(int i); + + public byte getFlags(int i); + + public short getXCoordinate(int i); + + public short getYCoordinate(int i); + + public short getXMaximum(); + + public short getXMinimum(); + + public short getYMaximum(); + + public short getYMinimum(); + + public boolean isComposite(); + + public int getPointCount(); + + public int getContourCount(); + + // public int getComponentIndex(int c); + // public int getComponentCount(); +} diff --git a/src/net/java/dev/typecast/ot/table/GposTable.java b/src/net/java/dev/typecast/ot/table/GposTable.java new file mode 100644 index 000000000..3efeeaa03 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GposTable.java @@ -0,0 +1,66 @@ +/* + * $Id: GposTable.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * TODO: To be implemented + * @author David Schweinsberg + * @version $Id: GposTable.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class GposTable implements Table { + + private DirectoryEntry _de; + + protected GposTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // GPOS Header + int version = di.readInt(); + int scriptList = di.readInt(); + int featureList = di.readInt(); + int lookupList = di.readInt(); + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return GPOS; + } + + public String toString() { + return "GPOS"; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GsubTable.java b/src/net/java/dev/typecast/ot/table/GsubTable.java new file mode 100644 index 000000000..d7f9c355f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GsubTable.java @@ -0,0 +1,181 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: GsubTable.java,v 1.3 2007-01-24 09:47:46 davidsch Exp $ + */ +public class GsubTable implements Table, LookupSubtableFactory { + + private DirectoryEntry _de; + private ScriptList _scriptList; + private FeatureList _featureList; + private LookupList _lookupList; + + protected GsubTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load into a temporary buffer, and create another input stream + byte[] buf = new byte[de.getLength()]; + di.readFully(buf); + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf)); + + // GSUB Header + int version = dis.readInt(); + int scriptListOffset = dis.readUnsignedShort(); + int featureListOffset = dis.readUnsignedShort(); + int lookupListOffset = dis.readUnsignedShort(); + + // Script List + _scriptList = new ScriptList(dis, scriptListOffset); + + // Feature List + _featureList = new FeatureList(dis, featureListOffset); + + // Lookup List + _lookupList = new LookupList(dis, lookupListOffset, this); + } + + /** + * 1 - Single - Replace one glyph with one glyph + * 2 - Multiple - Replace one glyph with more than one glyph + * 3 - Alternate - Replace one glyph with one of many glyphs + * 4 - Ligature - Replace multiple glyphs with one glyph + * 5 - Context - Replace one or more glyphs in context + * 6 - Chaining - Context Replace one or more glyphs in chained context + */ + public LookupSubtable read( + int type, + DataInputStream dis, + int offset) throws IOException { + LookupSubtable s = null; + switch (type) { + case 1: + s = SingleSubst.read(dis, offset); + break; + case 2: +// s = MultipleSubst.read(dis, offset); + break; + case 3: +// s = AlternateSubst.read(dis, offset); + break; + case 4: + s = LigatureSubst.read(dis, offset); + break; + case 5: +// s = ContextSubst.read(dis, offset); + break; + case 6: +// s = ChainingSubst.read(dis, offset); + break; + } + return s; + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return GSUB; + } + + public ScriptList getScriptList() { + return _scriptList; + } + + public FeatureList getFeatureList() { + return _featureList; + } + + public LookupList getLookupList() { + return _lookupList; + } + + public String toString() { + return "GSUB"; + } + + public static String lookupTypeAsString(int type) { + switch (type) { + case 1: + return "Single"; + case 2: + return "Multiple"; + case 3: + return "Alternate"; + case 4: + return "Ligature"; + case 5: + return "Context"; + case 6: + return "Chaining"; + } + return "Unknown"; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HdmxTable.java b/src/net/java/dev/typecast/ot/table/HdmxTable.java new file mode 100644 index 000000000..e47c0a316 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HdmxTable.java @@ -0,0 +1,117 @@ +/* + * $Id: HdmxTable.java,v 1.2 2007-07-26 11:12:30 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * The Horizontal Device Metrics table for TrueType outlines. This stores + * integer advance widths scaled to specific pixel sizes. + * @author David Schweinsberg + * @version $Id: HdmxTable.java,v 1.2 2007-07-26 11:12:30 davidsch Exp $ + */ +public class HdmxTable implements Table { + + public class DeviceRecord { + + private short _pixelSize; + private short _maxWidth; + private short[] _widths; + + protected DeviceRecord(int numGlyphs, DataInput di) throws IOException { + _pixelSize = di.readByte(); + _maxWidth = di.readByte(); + _widths = new short[numGlyphs]; + for (int i = 0; i < numGlyphs; ++i) { + _widths[i] = di.readByte(); + } + } + + public short getPixelSize() { + return _pixelSize; + } + + public short getMaxWidth() { + return _maxWidth; + } + + public short[] getWidths() { + return _widths; + } + } + + private DirectoryEntry _de; + private int _version; + private short _numRecords; + private int _sizeDeviceRecords; + private DeviceRecord[] _records; + + /** Creates a new instance of HdmxTable */ + protected HdmxTable(DirectoryEntry de, DataInput di, MaxpTable maxp) + throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numRecords = di.readShort(); + _sizeDeviceRecords = di.readInt(); + _records = new DeviceRecord[_numRecords]; + + // Read the device records + for (int i = 0; i < _numRecords; ++i) { + _records[i] = new DeviceRecord(maxp.getNumGlyphs(), di); + } + } + + public int getType() { + return hdmx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'hdmx' Table - Horizontal Device Metrics\n----------------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes\n") + .append("\t'hdmx' version: ").append(_version).append("\n") + .append("\t# device records: ").append(_numRecords).append("\n") + .append("\tRecord length: ").append(_sizeDeviceRecords).append("\n"); + for (int i = 0; i < _numRecords; ++i) { + sb.append("\tDevRec ").append(i) + .append(": ppem = ").append(_records[i].getPixelSize()) + .append(", maxWid = ").append(_records[i].getMaxWidth()) + .append("\n"); + for (int j = 0; j < _records[i].getWidths().length; ++j) { + sb.append(" ").append(j).append(". ") + .append(_records[i].getWidths()[j]).append("\n"); + } + sb.append("\n\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/HeadTable.java b/src/net/java/dev/typecast/ot/table/HeadTable.java new file mode 100644 index 000000000..c99ae768d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HeadTable.java @@ -0,0 +1,205 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: HeadTable.java,v 1.2 2004-12-21 10:23:20 davidsch Exp $ + * @author David Schweinsberg + */ +public class HeadTable implements Table { + + private DirectoryEntry _de; + private int _versionNumber; + private int _fontRevision; + private int _checkSumAdjustment; + private int _magicNumber; + private short _flags; + private short _unitsPerEm; + private long _created; + private long _modified; + private short _xMin; + private short _yMin; + private short _xMax; + private short _yMax; + private short _macStyle; + private short _lowestRecPPEM; + private short _fontDirectionHint; + private short _indexToLocFormat; + private short _glyphDataFormat; + + protected HeadTable(DirectoryEntry de, DataInput di) throws IOException { + this._de = (DirectoryEntry) de.clone(); + _versionNumber = di.readInt(); + _fontRevision = di.readInt(); + _checkSumAdjustment = di.readInt(); + _magicNumber = di.readInt(); + _flags = di.readShort(); + _unitsPerEm = di.readShort(); + _created = di.readLong(); + _modified = di.readLong(); + _xMin = di.readShort(); + _yMin = di.readShort(); + _xMax = di.readShort(); + _yMax = di.readShort(); + _macStyle = di.readShort(); + _lowestRecPPEM = di.readShort(); + _fontDirectionHint = di.readShort(); + _indexToLocFormat = di.readShort(); + _glyphDataFormat = di.readShort(); + } + + public int getCheckSumAdjustment() { + return _checkSumAdjustment; + } + + public long getCreated() { + return _created; + } + + public short getFlags() { + return _flags; + } + + public short getFontDirectionHint() { + return _fontDirectionHint; + } + + public int getFontRevision(){ + return _fontRevision; + } + + public short getGlyphDataFormat() { + return _glyphDataFormat; + } + + public short getIndexToLocFormat() { + return _indexToLocFormat; + } + + public short getLowestRecPPEM() { + return _lowestRecPPEM; + } + + public short getMacStyle() { + return _macStyle; + } + + public long getModified() { + return _modified; + } + + public int getType() { + return head; + } + + public short getUnitsPerEm() { + return _unitsPerEm; + } + + public int getVersionNumber() { + return _versionNumber; + } + + public short getXMax() { + return _xMax; + } + + public short getXMin() { + return _xMin; + } + + public short getYMax() { + return _yMax; + } + + public short getYMin() { + return _yMin; + } + + public String toString() { + return new StringBuffer() + .append("'head' Table - Font Header\n--------------------------") + .append("\n 'head' version: ").append(Fixed.floatValue(_versionNumber)) + .append("\n fontRevision: ").append(Fixed.roundedFloatValue(_fontRevision, 8)) + .append("\n checkSumAdjustment: 0x").append(Integer.toHexString(_checkSumAdjustment).toUpperCase()) + .append("\n magicNumber: 0x").append(Integer.toHexString(_magicNumber).toUpperCase()) + .append("\n flags: 0x").append(Integer.toHexString(_flags).toUpperCase()) + .append("\n unitsPerEm: ").append(_unitsPerEm) + .append("\n created: ").append(_created) + .append("\n modified: ").append(_modified) + .append("\n xMin: ").append(_xMin) + .append("\n yMin: ").append(_yMin) + .append("\n xMax: ").append(_xMax) + .append("\n yMax: ").append(_yMax) + .append("\n macStyle bits: ").append(Integer.toHexString(_macStyle).toUpperCase()) + .append("\n lowestRecPPEM: ").append(_lowestRecPPEM) + .append("\n fontDirectionHint: ").append(_fontDirectionHint) + .append("\n indexToLocFormat: ").append(_indexToLocFormat) + .append("\n glyphDataFormat: ").append(_glyphDataFormat) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HheaTable.java b/src/net/java/dev/typecast/ot/table/HheaTable.java new file mode 100644 index 000000000..4b49f41be --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HheaTable.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: HheaTable.java,v 1.2 2010-08-10 11:44:02 davidsch Exp $ + * @author David Schweinsberg + */ +public class HheaTable implements Table { + + private DirectoryEntry de; + private int version; + private short ascender; + private short descender; + private short lineGap; + private short advanceWidthMax; + private short minLeftSideBearing; + private short minRightSideBearing; + private short xMaxExtent; + private short caretSlopeRise; + private short caretSlopeRun; + private short metricDataFormat; + private int numberOfHMetrics; + + protected HheaTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + ascender = di.readShort(); + descender = di.readShort(); + lineGap = di.readShort(); + advanceWidthMax = di.readShort(); + minLeftSideBearing = di.readShort(); + minRightSideBearing = di.readShort(); + xMaxExtent = di.readShort(); + caretSlopeRise = di.readShort(); + caretSlopeRun = di.readShort(); + for (int i = 0; i < 5; i++) { + di.readShort(); + } + metricDataFormat = di.readShort(); + numberOfHMetrics = di.readUnsignedShort(); + } + + public short getAdvanceWidthMax() { + return advanceWidthMax; + } + + public short getAscender() { + return ascender; + } + + public short getCaretSlopeRise() { + return caretSlopeRise; + } + + public short getCaretSlopeRun() { + return caretSlopeRun; + } + + public short getDescender() { + return descender; + } + + public short getLineGap() { + return lineGap; + } + + public short getMetricDataFormat() { + return metricDataFormat; + } + + public short getMinLeftSideBearing() { + return minLeftSideBearing; + } + + public short getMinRightSideBearing() { + return minRightSideBearing; + } + + public int getNumberOfHMetrics() { + return numberOfHMetrics; + } + + public int getType() { + return hhea; + } + + public short getXMaxExtent() { + return xMaxExtent; + } + + public String toString() { + return new StringBuffer() + .append("'hhea' Table - Horizontal Header\n--------------------------------") + .append("\n 'hhea' version: ").append(Fixed.floatValue(version)) + .append("\n yAscender: ").append(ascender) + .append("\n yDescender: ").append(descender) + .append("\n yLineGap: ").append(lineGap) + .append("\n advanceWidthMax: ").append(advanceWidthMax) + .append("\n minLeftSideBearing: ").append(minLeftSideBearing) + .append("\n minRightSideBearing: ").append(minRightSideBearing) + .append("\n xMaxExtent: ").append(xMaxExtent) + .append("\n horizCaretSlopeNum: ").append(caretSlopeRise) + .append("\n horizCaretSlopeDenom: ").append(caretSlopeRun) + .append("\n reserved0: 0") + .append("\n reserved1: 0") + .append("\n reserved2: 0") + .append("\n reserved3: 0") + .append("\n reserved4: 0") + .append("\n metricDataFormat: ").append(metricDataFormat) + .append("\n numOf_LongHorMetrics: ").append(numberOfHMetrics) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HmtxTable.java b/src/net/java/dev/typecast/ot/table/HmtxTable.java new file mode 100644 index 000000000..7b4cbae40 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HmtxTable.java @@ -0,0 +1,141 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: HmtxTable.java,v 1.5 2007-07-26 11:11:48 davidsch Exp $ + * @author David Schweinsberg + */ +public class HmtxTable implements Table { + + private DirectoryEntry _de; + private int[] _hMetrics = null; + private short[] _leftSideBearing = null; + + protected HmtxTable( + DirectoryEntry de, + DataInput di, + HheaTable hhea, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _hMetrics = new int[hhea.getNumberOfHMetrics()]; + for (int i = 0; i < hhea.getNumberOfHMetrics(); ++i) { + _hMetrics[i] = + di.readUnsignedByte()<<24 + | di.readUnsignedByte()<<16 + | di.readUnsignedByte()<<8 + | di.readUnsignedByte(); + } + int lsbCount = maxp.getNumGlyphs() - hhea.getNumberOfHMetrics(); + _leftSideBearing = new short[lsbCount]; + for (int i = 0; i < lsbCount; ++i) { + _leftSideBearing[i] = di.readShort(); + } + } + + public int getAdvanceWidth(int i) { + if (_hMetrics == null) { + return 0; + } + if (i < _hMetrics.length) { + return _hMetrics[i] >> 16; + } else { + return _hMetrics[_hMetrics.length - 1] >> 16; + } + } + + public short getLeftSideBearing(int i) { + if (_hMetrics == null) { + return 0; + } + if (i < _hMetrics.length) { + return (short)(_hMetrics[i] & 0xffff); + } else { + return _leftSideBearing[i - _hMetrics.length]; + } + } + + public int getType() { + return hmtx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'hmtx' Table - Horizontal Metrics\n---------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_hMetrics.length).append(" entries\n"); + for (int i = 0; i < _hMetrics.length; i++) { + sb.append(" ").append(i) + .append(". advWid: ").append(getAdvanceWidth(i)) + .append(", LSdBear: ").append(getLeftSideBearing(i)) + .append("\n"); + } + for (int i = 0; i < _leftSideBearing.length; i++) { + sb.append(" LSdBear ").append(i + _hMetrics.length) + .append(": ").append(_leftSideBearing[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/ID.java b/src/net/java/dev/typecast/ot/table/ID.java new file mode 100644 index 000000000..5dc79d766 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ID.java @@ -0,0 +1,399 @@ +/* + * $Id: ID.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +/** + * + * @author David Schweinsberg + * @version $Id: ID.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public abstract class ID { + + // Platform IDs + public static final short platformUnicode = 0; + public static final short platformMacintosh = 1; + public static final short platformISO = 2; + public static final short platformMicrosoft = 3; + + // Unicode Encoding IDs + public static final short encodingUnicode10Semantics = 0; + public static final short encodingUnicode11Semantics = 1; + public static final short encodingISO10646Semantics = 2; + public static final short encodingUnicode20Semantics = 3; + + // Microsoft Encoding IDs +// public static final short encodingUndefined = 0; +// public static final short encodingUGL = 1; + public static final short encodingSymbol = 0; + public static final short encodingUnicode = 1; + public static final short encodingShiftJIS = 2; + public static final short encodingPRC = 3; + public static final short encodingBig5 = 4; + public static final short encodingWansung = 5; + public static final short encodingJohab = 6; + public static final short encodingUCS4 = 10; + + // Macintosh Encoding IDs + public static final short encodingRoman = 0; + public static final short encodingJapanese = 1; + public static final short encodingChinese = 2; + public static final short encodingKorean = 3; + public static final short encodingArabic = 4; + public static final short encodingHebrew = 5; + public static final short encodingGreek = 6; + public static final short encodingRussian = 7; + public static final short encodingRSymbol = 8; + public static final short encodingDevanagari = 9; + public static final short encodingGurmukhi = 10; + public static final short encodingGujarati = 11; + public static final short encodingOriya = 12; + public static final short encodingBengali = 13; + public static final short encodingTamil = 14; + public static final short encodingTelugu = 15; + public static final short encodingKannada = 16; + public static final short encodingMalayalam = 17; + public static final short encodingSinhalese = 18; + public static final short encodingBurmese = 19; + public static final short encodingKhmer = 20; + public static final short encodingThai = 21; + public static final short encodingLaotian = 22; + public static final short encodingGeorgian = 23; + public static final short encodingArmenian = 24; + public static final short encodingMaldivian = 25; + public static final short encodingTibetan = 26; + public static final short encodingMongolian = 27; + public static final short encodingGeez = 28; + public static final short encodingSlavic = 29; + public static final short encodingVietnamese = 30; + public static final short encodingSindhi = 31; + public static final short encodingUninterp = 32; + + // ISO Encoding IDs + public static final short encodingASCII = 0; + public static final short encodingISO10646 = 1; + public static final short encodingISO8859_1 = 2; + + // Microsoft Language IDs + public static final short languageSQI = 0x041c; + public static final short languageEUQ = 0x042d; + public static final short languageBEL = 0x0423; + public static final short languageBGR = 0x0402; + public static final short languageCAT = 0x0403; + public static final short languageSHL = 0x041a; + public static final short languageCSY = 0x0405; + public static final short languageDAN = 0x0406; + public static final short languageNLD = 0x0413; + public static final short languageNLB = 0x0813; + public static final short languageENU = 0x0409; + public static final short languageENG = 0x0809; + public static final short languageENA = 0x0c09; + public static final short languageENC = 0x1009; + public static final short languageENZ = 0x1409; + public static final short languageENI = 0x1809; + public static final short languageETI = 0x0425; + public static final short languageFIN = 0x040b; + public static final short languageFRA = 0x040c; + public static final short languageFRB = 0x080c; + public static final short languageFRC = 0x0c0c; + public static final short languageFRS = 0x100c; + public static final short languageFRL = 0x140c; + public static final short languageDEU = 0x0407; + public static final short languageDES = 0x0807; + public static final short languageDEA = 0x0c07; + public static final short languageDEL = 0x1007; + public static final short languageDEC = 0x1407; + public static final short languageELL = 0x0408; + public static final short languageHUN = 0x040e; + public static final short languageISL = 0x040f; + public static final short languageITA = 0x0410; + public static final short languageITS = 0x0810; + public static final short languageLVI = 0x0426; + public static final short languageLTH = 0x0427; + public static final short languageNOR = 0x0414; + public static final short languageNON = 0x0814; + public static final short languagePLK = 0x0415; + public static final short languagePTB = 0x0416; + public static final short languagePTG = 0x0816; + public static final short languageROM = 0x0418; + public static final short languageRUS = 0x0419; + public static final short languageSKY = 0x041b; + public static final short languageSLV = 0x0424; + public static final short languageESP = 0x040a; + public static final short languageESM = 0x080a; + public static final short languageESN = 0x0c0a; + public static final short languageSVE = 0x041d; + public static final short languageTRK = 0x041f; + public static final short languageUKR = 0x0422; + + // Macintosh Language IDs + public static final short languageEnglish = 0; + public static final short languageFrench = 1; + public static final short languageGerman = 2; + public static final short languageItalian = 3; + public static final short languageDutch = 4; + public static final short languageSwedish = 5; + public static final short languageSpanish = 6; + public static final short languageDanish = 7; + public static final short languagePortuguese = 8; + public static final short languageNorwegian = 9; + public static final short languageHebrew = 10; + public static final short languageJapanese = 11; + public static final short languageArabic = 12; + public static final short languageFinnish = 13; + public static final short languageGreek = 14; + public static final short languageIcelandic = 15; + public static final short languageMaltese = 16; + public static final short languageTurkish = 17; + public static final short languageYugoslavian = 18; + public static final short languageChinese = 19; + public static final short languageUrdu = 20; + public static final short languageHindi = 21; + public static final short languageThai = 22; + + // Name IDs + public static final short nameCopyrightNotice = 0; + public static final short nameFontFamilyName = 1; + public static final short nameFontSubfamilyName = 2; + public static final short nameUniqueFontIdentifier = 3; + public static final short nameFullFontName = 4; + public static final short nameVersionString = 5; + public static final short namePostscriptName = 6; + public static final short nameTrademark = 7; + public static final short nameManufacturerName = 8; + public static final short nameDesigner = 9; + public static final short nameDescription = 10; + public static final short nameURLVendor = 11; + public static final short nameURLDesigner = 12; + public static final short nameLicenseDescription = 13; + public static final short nameLicenseInfoURL = 14; + public static final short namePreferredFamily = 16; + public static final short namePreferredSubfamily = 17; + public static final short nameCompatibleFull = 18; + public static final short nameSampleText = 19; + public static final short namePostScriptCIDFindfontName = 20; + + public static String getPlatformName(short platformId) { + switch (platformId) { + case platformUnicode: return "Unicode"; + case platformMacintosh: return "Macintosh"; + case platformISO: return "ISO"; + case platformMicrosoft: return "Microsoft"; + default: return "Custom"; + } + } + + public static String getEncodingName(short platformId, short encodingId) { + + if (platformId == platformUnicode) { + + // Unicode specific encodings + switch (encodingId) { + case encodingUnicode10Semantics: return "Unicode 1.0 semantics"; + case encodingUnicode11Semantics: return "Unicode 1.1 semantics"; + case encodingISO10646Semantics: return "ISO 10646:1993 semantics"; + case encodingUnicode20Semantics: return "Unicode 2.0 and onwards semantics"; + default: return ""; + } + + } else if (platformId == platformMacintosh) { + + // Macintosh specific encodings + switch (encodingId) { + case encodingRoman: return "Roman"; + case encodingJapanese: return "Japanese"; + case encodingChinese: return "Chinese"; + case encodingKorean: return "Korean"; + case encodingArabic: return "Arabi"; + case encodingHebrew: return "Hebrew"; + case encodingGreek: return "Greek"; + case encodingRussian: return "Russian"; + case encodingRSymbol: return "RSymbol"; + case encodingDevanagari: return "Devanagari"; + case encodingGurmukhi: return "Gurmukhi"; + case encodingGujarati: return "Gujarati"; + case encodingOriya: return "Oriya"; + case encodingBengali: return "Bengali"; + case encodingTamil: return "Tamil"; + case encodingTelugu: return "Telugu"; + case encodingKannada: return "Kannada"; + case encodingMalayalam: return "Malayalam"; + case encodingSinhalese: return "Sinhalese"; + case encodingBurmese: return "Burmese"; + case encodingKhmer: return "Khmer"; + case encodingThai: return "Thai"; + case encodingLaotian: return "Laotian"; + case encodingGeorgian: return "Georgian"; + case encodingArmenian: return "Armenian"; + case encodingMaldivian: return "Maldivian"; + case encodingTibetan: return "Tibetan"; + case encodingMongolian: return "Mongolian"; + case encodingGeez: return "Geez"; + case encodingSlavic: return "Slavic"; + case encodingVietnamese: return "Vietnamese"; + case encodingSindhi: return "Sindhi"; + case encodingUninterp: return "Uninterpreted"; + default: return ""; + } + + } else if (platformId == platformISO) { + + // ISO specific encodings + switch (encodingId) { + case encodingASCII: return "7-bit ASCII"; + case encodingISO10646: return "ISO 10646"; + case encodingISO8859_1: return "ISO 8859-1"; + default: return ""; + } + + } else if (platformId == platformMicrosoft) { + + // Windows specific encodings + switch (encodingId) { + case encodingSymbol: return "Symbol"; + case encodingUnicode: return "Unicode"; + case encodingShiftJIS: return "ShiftJIS"; + case encodingPRC: return "PRC"; + case encodingBig5: return "Big5"; + case encodingWansung: return "Wansung"; + case encodingJohab: return "Johab"; + case 7: return "Reserved"; + case 8: return "Reserved"; + case 9: return "Reserved"; + case encodingUCS4: return "UCS-4"; + default: return ""; + } + } + return ""; + } + + public static String getLanguageName(short platformId, short languageId) { + + if (platformId == platformMacintosh) { + switch (languageId) { + case languageEnglish: return "English"; + case languageFrench: return "French"; + case languageGerman: return "German"; + case languageItalian: return "Italian"; + case languageDutch: return "Dutch"; + case languageSwedish: return "Swedish"; + case languageSpanish: return "Spanish"; + case languageDanish: return "Danish"; + case languagePortuguese: return "Portuguese"; + case languageNorwegian: return "Norwegian"; + case languageHebrew: return "Hebrew"; + case languageJapanese: return "Japanese"; + case languageArabic: return "Arabic"; + case languageFinnish: return "Finnish"; + case languageGreek: return "Greek"; + case languageIcelandic: return "Icelandic"; + case languageMaltese: return "Maltese"; + case languageTurkish: return "Turkish"; + case languageYugoslavian: return "Yugoslavian"; + case languageChinese: return "Chinese"; + case languageUrdu: return "Urdu"; + case languageHindi: return "Hindi"; + case languageThai: return "Thai"; + default: return ""; + } + } else if (platformId == platformMicrosoft) { + switch (languageId) { + case languageSQI: return "Albanian (Albania)"; + case languageEUQ: return "Basque (Basque)"; + case languageBEL: return "Byelorussian (Byelorussia)"; + case languageBGR: return "Bulgarian (Bulgaria)"; + case languageCAT: return "Catalan (Catalan)"; + case languageSHL: return "Croatian (Croatian)"; + case languageCSY: return "Czech (Czech)"; + case languageDAN: return "Danish (Danish)"; + case languageNLD: return "Dutch (Dutch (Standard))"; + case languageNLB: return "Dutch (Belgian (Flemish))"; + case languageENU: return "English (American)"; + case languageENG: return "English (British)"; + case languageENA: return "English (Australian)"; + case languageENC: return "English (Canadian)"; + case languageENZ: return "English (New Zealand)"; + case languageENI: return "English (Ireland)"; + case languageETI: return "Estonian (Estonia)"; + case languageFIN: return "Finnish (Finnish)"; + case languageFRA: return "French (French (Standard))"; + case languageFRB: return "French (Belgian)"; + case languageFRC: return "French (Canadian)"; + case languageFRS: return "French (Swiss)"; + case languageFRL: return "French (Luxembourg)"; + case languageDEU: return "German (German (Standard))"; + case languageDES: return "German (Swiss)"; + case languageDEA: return "German (Austrian)"; + case languageDEL: return "German (Luxembourg)"; + case languageDEC: return "German (Liechtenstein)"; + case languageELL: return "Greek (Greek)"; + case languageHUN: return "Hungarian (Hungarian)"; + case languageISL: return "Icelandic (Icelandic)"; + case languageITA: return "Italian (Italian (Standard))"; + case languageITS: return "Italian (Swiss)"; + case languageLVI: return "Latvian (Latvia)"; + case languageLTH: return "Lithuanian (Lithuania)"; + case languageNOR: return "Norwegian (Norwegian (Bokmal))"; + case languageNON: return "Norwegian (Norwegian (Nynorsk))"; + case languagePLK: return "Polish (Polish)"; + case languagePTB: return "Portuguese (Portuguese (Brazilian))"; + case languagePTG: return "Portuguese (Portuguese (Standard))"; + case languageROM: return "Romanian (Romania)"; + case languageRUS: return "Russian (Russian)"; + case languageSKY: return "Slovak (Slovak)"; + case languageSLV: return "Slovenian (Slovenia)"; + case languageESP: return "Spanish (Spanish (Traditional Sort))"; + case languageESM: return "Spanish (Mexican)"; + case languageESN: return "Spanish (Spanish (Modern Sort))"; + case languageSVE: return "Swedish (Swedish)"; + case languageTRK: return "Turkish (Turkish)"; + case languageUKR: return "Ukrainian (Ukraine)"; + default: return ""; + } + } + return ""; + } + + public static String getNameName(short nameId) { + switch (nameId) { + case nameCopyrightNotice: return "Copyright notice"; + case nameFontFamilyName: return "Font Family name"; + case nameFontSubfamilyName: return "Font Subfamily name"; + case nameUniqueFontIdentifier: return "Unique font identifier"; + case nameFullFontName: return "Full font name"; + case nameVersionString: return "Version string"; + case namePostscriptName: return "Postscript name"; + case nameTrademark: return "Trademark"; + case nameManufacturerName: return "Manufacturer Name"; + case nameDesigner: return "Designer"; + case nameDescription: return "Description"; + case nameURLVendor: return "URL Vendor"; + case nameURLDesigner: return "URL Designer"; + case nameLicenseDescription: return "License Description"; + case nameLicenseInfoURL: return "License Info URL"; + case namePreferredFamily: return "Preferred Family"; + case namePreferredSubfamily: return "Preferred Subfamily"; + case nameCompatibleFull: return "Compatible Full"; + case nameSampleText: return "Sample text"; + case namePostScriptCIDFindfontName: return "PostScript CID findfont name"; + default: return ""; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtable.java b/src/net/java/dev/typecast/ot/table/KernSubtable.java new file mode 100644 index 000000000..f55fa04fb --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtable.java @@ -0,0 +1,49 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: KernSubtable.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public abstract class KernSubtable { + + /** Creates new KernSubtable */ + protected KernSubtable() { + } + + public abstract int getKerningPairCount(); + + public abstract KerningPair getKerningPair(int i); + + public static KernSubtable read(DataInput di) throws IOException { + KernSubtable table = null; + int version = di.readUnsignedShort(); + int length = di.readUnsignedShort(); + int coverage = di.readUnsignedShort(); + int format = coverage >> 8; + + switch (format) { + case 0: + table = new KernSubtableFormat0(di); + break; + case 2: + table = new KernSubtableFormat2(di); + break; + default: + break; + } + return table; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java b/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java new file mode 100644 index 000000000..e3b1c9cf9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: KernSubtableFormat0.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernSubtableFormat0 extends KernSubtable { + + private int nPairs; + private int searchRange; + private int entrySelector; + private int rangeShift; + private KerningPair[] kerningPairs; + + /** Creates new KernSubtableFormat0 */ + protected KernSubtableFormat0(DataInput di) throws IOException { + nPairs = di.readUnsignedShort(); + searchRange = di.readUnsignedShort(); + entrySelector = di.readUnsignedShort(); + rangeShift = di.readUnsignedShort(); + kerningPairs = new KerningPair[nPairs]; + for (int i = 0; i < nPairs; i++) { + kerningPairs[i] = new KerningPair(di); + } + } + + public int getKerningPairCount() { + return nPairs; + } + + public KerningPair getKerningPair(int i) { + return kerningPairs[i]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java b/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java new file mode 100644 index 000000000..5ff37c291 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java @@ -0,0 +1,42 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: KernSubtableFormat2.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernSubtableFormat2 extends KernSubtable { + + private int rowWidth; + private int leftClassTable; + private int rightClassTable; + private int array; + + /** Creates new KernSubtableFormat2 */ + protected KernSubtableFormat2(DataInput di) throws IOException { + rowWidth = di.readUnsignedShort(); + leftClassTable = di.readUnsignedShort(); + rightClassTable = di.readUnsignedShort(); + array = di.readUnsignedShort(); + } + + public int getKerningPairCount() { + return 0; + } + + public KerningPair getKerningPair(int i) { + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernTable.java b/src/net/java/dev/typecast/ot/table/KernTable.java new file mode 100644 index 000000000..81c4a998f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernTable.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: KernTable.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernTable implements Table { + + private DirectoryEntry de; + private int version; + private int nTables; + private KernSubtable[] tables; + + /** Creates new KernTable */ + protected KernTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + nTables = di.readUnsignedShort(); + tables = new KernSubtable[nTables]; + for (int i = 0; i < nTables; i++) { + tables[i] = KernSubtable.read(di); + } + } + + public int getSubtableCount() { + return nTables; + } + + public KernSubtable getSubtable(int i) { + return tables[i]; + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return kern; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KerningPair.java b/src/net/java/dev/typecast/ot/table/KerningPair.java new file mode 100644 index 000000000..de614235f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KerningPair.java @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: KerningPair.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public class KerningPair { + + private int left; + private int right; + private short value; + + /** Creates new KerningPair */ + protected KerningPair(DataInput di) throws IOException { + left = di.readUnsignedShort(); + right = di.readUnsignedShort(); + value = di.readShort(); + } + + public int getLeft() { + return left; + } + + public int getRight() { + return right; + } + + public short getValue() { + return value; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LangSys.java b/src/net/java/dev/typecast/ot/table/LangSys.java new file mode 100644 index 000000000..9963bf6af --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LangSys.java @@ -0,0 +1,105 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LangSys.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LangSys { + + private int _lookupOrder; + private int _reqFeatureIndex; + private int _featureCount; + private int[] _featureIndex; + + /** Creates new LangSys */ + protected LangSys(DataInput di) throws IOException { + _lookupOrder = di.readUnsignedShort(); + _reqFeatureIndex = di.readUnsignedShort(); + _featureCount = di.readUnsignedShort(); + _featureIndex = new int[_featureCount]; + for (int i = 0; i < _featureCount; i++) { + _featureIndex[i] = di.readUnsignedShort(); + } + } + + public int getLookupOrder() { + return _lookupOrder; + } + + public int getReqFeatureIndex() { + return _reqFeatureIndex; + } + + public int getFeatureCount() { + return _featureCount; + } + + public int getFeatureIndex(int i) { + return _featureIndex[i]; + } + + protected boolean isFeatureIndexed(int n) { + for (int i = 0; i < _featureCount; i++) { + if (_featureIndex[i] == n) { + return true; + } + } + return false; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LangSysRecord.java b/src/net/java/dev/typecast/ot/table/LangSysRecord.java new file mode 100644 index 000000000..a69c12a44 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LangSysRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LangSysRecord.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class LangSysRecord { + + private int _tag; + private int _offset; + + /** Creates new LangSysRecord */ + public LangSysRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/Ligature.java b/src/net/java/dev/typecast/ot/table/Ligature.java new file mode 100644 index 000000000..36969ba7a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Ligature.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: Ligature.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class Ligature { + + private int _ligGlyph; + private int _compCount; + private int[] _components; + + /** Creates new Ligature */ + public Ligature(DataInput di) throws IOException { + _ligGlyph = di.readUnsignedShort(); + _compCount = di.readUnsignedShort(); + _components = new int[_compCount - 1]; + for (int i = 0; i < _compCount - 1; i++) { + _components[i] = di.readUnsignedShort(); + } + } + + public int getGlyphCount() { + return _compCount; + } + + public int getGlyphId(int i) { + return (i == 0) ? _ligGlyph : _components[i-1]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LigatureSet.java b/src/net/java/dev/typecast/ot/table/LigatureSet.java new file mode 100644 index 000000000..fe6db0445 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSet.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LigatureSet.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class LigatureSet { + + private int _ligatureCount; + private int[] _ligatureOffsets; + private Ligature[] _ligatures; + + /** Creates new LigatureSet */ + public LigatureSet(DataInputStream dis, int offset) throws IOException { + dis.reset(); + dis.skipBytes(offset); + _ligatureCount = dis.readUnsignedShort(); + _ligatureOffsets = new int[_ligatureCount]; + _ligatures = new Ligature[_ligatureCount]; + for (int i = 0; i < _ligatureCount; i++) { + _ligatureOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _ligatureCount; i++) { + dis.reset(); + dis.skipBytes(offset + _ligatureOffsets[i]); + _ligatures[i] = new Ligature(dis); + } + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LigatureSubst.java b/src/net/java/dev/typecast/ot/table/LigatureSubst.java new file mode 100644 index 000000000..73a8b9d36 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSubst.java @@ -0,0 +1,73 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LigatureSubst.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public abstract class LigatureSubst extends LookupSubtable { + + public static LigatureSubst read(DataInputStream dis, int offset) throws IOException { + dis.reset(); + dis.skipBytes(offset); + int format = dis.readUnsignedShort(); + if (format == 1) { + return new LigatureSubstFormat1(dis, offset); + } + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java b/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java new file mode 100644 index 000000000..b19b07111 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java @@ -0,0 +1,95 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LigatureSubstFormat1.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LigatureSubstFormat1 extends LigatureSubst { + + private int _coverageOffset; + private int _ligSetCount; + private int[] _ligatureSetOffsets; + private Coverage _coverage; + private LigatureSet[] _ligatureSets; + + /** Creates new LigatureSubstFormat1 */ + protected LigatureSubstFormat1( + DataInputStream dis, + int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _ligSetCount = dis.readUnsignedShort(); + _ligatureSetOffsets = new int[_ligSetCount]; + _ligatureSets = new LigatureSet[_ligSetCount]; + for (int i = 0; i < _ligSetCount; i++) { + _ligatureSetOffsets[i] = dis.readUnsignedShort(); + } + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + for (int i = 0; i < _ligSetCount; i++) { + _ligatureSets[i] = new LigatureSet(dis, offset + _ligatureSetOffsets[i]); + } + } + + public int getFormat() { + return 1; + } + + public String getTypeAsString() { + return "LigatureSubstFormat1"; + } +} diff --git a/src/net/java/dev/typecast/ot/table/LocaTable.java b/src/net/java/dev/typecast/ot/table/LocaTable.java new file mode 100644 index 000000000..5f62940df --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LocaTable.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: LocaTable.java,v 1.4 2010-08-10 11:45:43 davidsch Exp $ + * @author David Schweinsberg + */ +public class LocaTable implements Table { + + private DirectoryEntry _de; + private int[] _offsets = null; + private short _factor = 0; + + protected LocaTable( + DirectoryEntry de, + DataInput di, + HeadTable head, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _offsets = new int[maxp.getNumGlyphs() + 1]; + boolean shortEntries = head.getIndexToLocFormat() == 0; + if (shortEntries) { + _factor = 2; + for (int i = 0; i <= maxp.getNumGlyphs(); i++) { + _offsets[i] = di.readUnsignedShort(); + } + } else { + _factor = 1; + for (int i = 0; i <= maxp.getNumGlyphs(); i++) { + _offsets[i] = di.readInt(); + } + } + } + + public int getOffset(int i) { + if (_offsets == null) { + return 0; + } + return _offsets[i] * _factor; + } + + public int getType() { + return loca; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'loca' Table - Index To Location Table\n--------------------------------------\n") + .append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_offsets.length).append(" entries\n"); + for (int i = 0; i < _offsets.length; i++) { + sb.append(" Idx ").append(i) + .append(" -> glyfOff 0x").append(getOffset(i)).append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Lookup.java b/src/net/java/dev/typecast/ot/table/Lookup.java new file mode 100644 index 000000000..d6e46cd91 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Lookup.java @@ -0,0 +1,110 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: Lookup.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class Lookup { + + // LookupFlag bit enumeration + public static final int IGNORE_BASE_GLYPHS = 0x0002; + public static final int IGNORE_BASE_LIGATURES = 0x0004; + public static final int IGNORE_BASE_MARKS = 0x0008; + public static final int MARK_ATTACHMENT_TYPE = 0xFF00; + + private int _type; + private int _flag; + private int _subTableCount; + private int[] _subTableOffsets; + private LookupSubtable[] _subTables; + + /** Creates new Lookup */ + public Lookup(LookupSubtableFactory factory, DataInputStream dis, int offset) + throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _type = dis.readUnsignedShort(); + _flag = dis.readUnsignedShort(); + _subTableCount = dis.readUnsignedShort(); + _subTableOffsets = new int[_subTableCount]; + _subTables = new LookupSubtable[_subTableCount]; + for (int i = 0; i < _subTableCount; i++) { + _subTableOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _subTableCount; i++) { + _subTables[i] = factory.read(_type, dis, offset + _subTableOffsets[i]); + } + } + + public int getType() { + return _type; + } + + public int getSubtableCount() { + return _subTableCount; + } + + public LookupSubtable getSubtable(int i) { + return _subTables[i]; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LookupList.java b/src/net/java/dev/typecast/ot/table/LookupList.java new file mode 100644 index 000000000..9ac76aba5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupList.java @@ -0,0 +1,108 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LookupList.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LookupList { + + private int _lookupCount; + private int[] _lookupOffsets; + private Lookup[] _lookups; + + /** Creates new LookupList */ + public LookupList(DataInputStream dis, int offset, LookupSubtableFactory factory) + throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _lookupCount = dis.readUnsignedShort(); + _lookupOffsets = new int[_lookupCount]; + _lookups = new Lookup[_lookupCount]; + for (int i = 0; i < _lookupCount; i++) { + _lookupOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _lookupCount; i++) { + _lookups[i] = new Lookup(factory, dis, offset + _lookupOffsets[i]); + } + } + + public int getLookupCount() { + return _lookupCount; + } + + public int getLookupOffset(int i) { + return _lookupOffsets[i]; + } + + public Lookup getLookup(int i) { + return _lookups[i]; + } + + public Lookup getLookup(Feature feature, int index) { + if (feature.getLookupCount() > index) { + int i = feature.getLookupListIndex(index); + return _lookups[i]; + } + return null; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LookupSubtable.java b/src/net/java/dev/typecast/ot/table/LookupSubtable.java new file mode 100644 index 000000000..4d8dbb180 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupSubtable.java @@ -0,0 +1,60 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * + * @author David Schweinsberg + * @version $Id: LookupSubtable.java,v 1.2 2007-01-24 09:47:45 davidsch Exp $ + */ +public abstract class LookupSubtable { + public abstract String getTypeAsString(); +} diff --git a/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java b/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java new file mode 100644 index 000000000..2081e2ea6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java @@ -0,0 +1,64 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: LookupSubtableFactory.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public interface LookupSubtableFactory { + public LookupSubtable read(int type, DataInputStream dis, int offset) + throws IOException; +} diff --git a/src/net/java/dev/typecast/ot/table/LtshTable.java b/src/net/java/dev/typecast/ot/table/LtshTable.java new file mode 100644 index 000000000..12dca01f4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LtshTable.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: LtshTable.java,v 1.1.1.1 2004-12-05 23:14:51 davidsch Exp $ + * @author David Schweinsberg + */ +public class LtshTable implements Table { + + private DirectoryEntry de; + private int version; + private int numGlyphs; + private int[] yPels; + + /** Creates new LtshTable */ + protected LtshTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + numGlyphs = di.readUnsignedShort(); + yPels = new int[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + yPels[i] = di.readUnsignedByte(); + } + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return LTSH; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'LTSH' Table - Linear Threshold Table\n-------------------------------------") + .append("\n 'LTSH' Version: ").append(version) + .append("\n Number of Glyphs: ").append(numGlyphs) + .append("\n\n Glyph # Threshold\n ------- ---------\n"); + for (int i = 0; i < numGlyphs; i++) { + sb.append(" ").append(i).append(". ").append(yPels[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/MaxpTable.java b/src/net/java/dev/typecast/ot/table/MaxpTable.java new file mode 100644 index 000000000..571d3ebfd --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/MaxpTable.java @@ -0,0 +1,162 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: MaxpTable.java,v 1.1.1.1 2004-12-05 23:14:52 davidsch Exp $ + * @author David Schweinsberg + */ +public class MaxpTable implements Table { + + private DirectoryEntry de; + private int versionNumber; + private int numGlyphs; + private int maxPoints; + private int maxContours; + private int maxCompositePoints; + private int maxCompositeContours; + private int maxZones; + private int maxTwilightPoints; + private int maxStorage; + private int maxFunctionDefs; + private int maxInstructionDefs; + private int maxStackElements; + private int maxSizeOfInstructions; + private int maxComponentElements; + private int maxComponentDepth; + + protected MaxpTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + versionNumber = di.readInt(); + + // CFF fonts use version 0.5, TrueType fonts use version 1.0 + if (versionNumber == 0x00005000) { + numGlyphs = di.readUnsignedShort(); + } else if (versionNumber == 0x00010000) { + numGlyphs = di.readUnsignedShort(); + maxPoints = di.readUnsignedShort(); + maxContours = di.readUnsignedShort(); + maxCompositePoints = di.readUnsignedShort(); + maxCompositeContours = di.readUnsignedShort(); + maxZones = di.readUnsignedShort(); + maxTwilightPoints = di.readUnsignedShort(); + maxStorage = di.readUnsignedShort(); + maxFunctionDefs = di.readUnsignedShort(); + maxInstructionDefs = di.readUnsignedShort(); + maxStackElements = di.readUnsignedShort(); + maxSizeOfInstructions = di.readUnsignedShort(); + maxComponentElements = di.readUnsignedShort(); + maxComponentDepth = di.readUnsignedShort(); + } + } + + public int getVersionNumber() { + return versionNumber; + } + + public int getMaxComponentDepth() { + return maxComponentDepth; + } + + public int getMaxComponentElements() { + return maxComponentElements; + } + + public int getMaxCompositeContours() { + return maxCompositeContours; + } + + public int getMaxCompositePoints() { + return maxCompositePoints; + } + + public int getMaxContours() { + return maxContours; + } + + public int getMaxFunctionDefs() { + return maxFunctionDefs; + } + + public int getMaxInstructionDefs() { + return maxInstructionDefs; + } + + public int getMaxPoints() { + return maxPoints; + } + + public int getMaxSizeOfInstructions() { + return maxSizeOfInstructions; + } + + public int getMaxStackElements() { + return maxStackElements; + } + + public int getMaxStorage() { + return maxStorage; + } + + public int getMaxTwilightPoints() { + return maxTwilightPoints; + } + + public int getMaxZones() { + return maxZones; + } + + public int getNumGlyphs() { + return numGlyphs; + } + + public int getType() { + return maxp; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'maxp' Table - Maximum Profile\n------------------------------") + .append("\n 'maxp' version: ").append(Fixed.floatValue(versionNumber)) + .append("\n numGlyphs: ").append(numGlyphs); + if (versionNumber == 0x00010000) { + sb.append("\n maxPoints: ").append(maxPoints) + .append("\n maxContours: ").append(maxContours) + .append("\n maxCompositePoints: ").append(maxCompositePoints) + .append("\n maxCompositeContours: ").append(maxCompositeContours) + .append("\n maxZones: ").append(maxZones) + .append("\n maxTwilightPoints: ").append(maxTwilightPoints) + .append("\n maxStorage: ").append(maxStorage) + .append("\n maxFunctionDefs: ").append(maxFunctionDefs) + .append("\n maxInstructionDefs: ").append(maxInstructionDefs) + .append("\n maxStackElements: ").append(maxStackElements) + .append("\n maxSizeOfInstructions: ").append(maxSizeOfInstructions) + .append("\n maxComponentElements: ").append(maxComponentElements) + .append("\n maxComponentDepth: ").append(maxComponentDepth); + } else { + sb.append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/NameRecord.java b/src/net/java/dev/typecast/ot/table/NameRecord.java new file mode 100644 index 000000000..cdba03ef9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/NameRecord.java @@ -0,0 +1,145 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: NameRecord.java,v 1.2 2004-12-09 23:47:23 davidsch Exp $ + * @author David Schweinsberg + */ +public class NameRecord { + + private short _platformId; + private short _encodingId; + private short _languageId; + private short _nameId; + private short _stringLength; + private short _stringOffset; + private String _record; + + protected NameRecord(DataInput di) throws IOException { + _platformId = di.readShort(); + _encodingId = di.readShort(); + _languageId = di.readShort(); + _nameId = di.readShort(); + _stringLength = di.readShort(); + _stringOffset = di.readShort(); + } + + public short getEncodingId() { + return _encodingId; + } + + public short getLanguageId() { + return _languageId; + } + + public short getNameId() { + return _nameId; + } + + public short getPlatformId() { + return _platformId; + } + + public String getRecordString() { + return _record; + } + + protected void loadString(DataInput di) throws IOException { + StringBuffer sb = new StringBuffer(); + di.skipBytes(_stringOffset); + if (_platformId == ID.platformUnicode) { + + // Unicode (big-endian) + for (int i = 0; i < _stringLength/2; i++) { + sb.append(di.readChar()); + } + } else if (_platformId == ID.platformMacintosh) { + + // Macintosh encoding, ASCII + for (int i = 0; i < _stringLength; i++) { + sb.append((char) di.readByte()); + } + } else if (_platformId == ID.platformISO) { + + // ISO encoding, ASCII + for (int i = 0; i < _stringLength; i++) { + sb.append((char) di.readByte()); + } + } else if (_platformId == ID.platformMicrosoft) { + + // Microsoft encoding, Unicode + char c; + for (int i = 0; i < _stringLength/2; i++) { + c = di.readChar(); + sb.append(c); + } + } + _record = sb.toString(); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append(" Platform ID: ").append(_platformId) + .append("\n Specific ID: ").append(_encodingId) + .append("\n Language ID: ").append(_languageId) + .append("\n Name ID: ").append(_nameId) + .append("\n Length: ").append(_stringLength) + .append("\n Offset: ").append(_stringOffset) + .append("\n\n").append(_record); + + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/NameTable.java b/src/net/java/dev/typecast/ot/table/NameTable.java new file mode 100644 index 000000000..05f823427 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/NameTable.java @@ -0,0 +1,131 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +/** + * The naming table allows multilingual strings to be associated with the + * OpenType font file. These strings can represent copyright notices, font + * names, family names, style names, and so on. + * @version $Id: NameTable.java,v 1.2 2004-12-09 23:47:23 davidsch Exp $ + * @author David Schweinsberg + */ +public class NameTable implements Table { + + private DirectoryEntry _de; + private short _formatSelector; + private short _numberOfNameRecords; + private short _stringStorageOffset; + private NameRecord[] _records; + + protected NameTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _formatSelector = di.readShort(); + _numberOfNameRecords = di.readShort(); + _stringStorageOffset = di.readShort(); + _records = new NameRecord[_numberOfNameRecords]; + + // Load the records, which contain the encoding information and string + // offsets + for (int i = 0; i < _numberOfNameRecords; i++) { + _records[i] = new NameRecord(di); + } + + // Load the string data into a buffer so the records can copy out the + // bits they are interested in + byte[] buffer = new byte[_de.getLength() - _stringStorageOffset]; + di.readFully(buffer); + + // Now let the records get their hands on them + for (int i = 0; i < _numberOfNameRecords; i++) { + _records[i].loadString( + new DataInputStream(new ByteArrayInputStream(buffer))); + } + } + + public short getNumberOfNameRecords() { + return _numberOfNameRecords; + } + + public NameRecord getRecord(int i) { + return _records[i]; + } + + public String getRecordString(short nameId) { + + // Search for the first instance of this name ID + for (int i = 0; i < _numberOfNameRecords; i++) { + if (_records[i].getNameId() == nameId) { + return _records[i].getRecordString(); + } + } + return ""; + } + + public int getType() { + return name; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Os2Table.java b/src/net/java/dev/typecast/ot/table/Os2Table.java new file mode 100644 index 000000000..bb3b60101 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Os2Table.java @@ -0,0 +1,358 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: Os2Table.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author David Schweinsberg + */ +public class Os2Table implements Table { + + private DirectoryEntry _de; + private int _version; + private short _xAvgCharWidth; + private int _usWeightClass; + private int _usWidthClass; + private short _fsType; + private short _ySubscriptXSize; + private short _ySubscriptYSize; + private short _ySubscriptXOffset; + private short _ySubscriptYOffset; + private short _ySuperscriptXSize; + private short _ySuperscriptYSize; + private short _ySuperscriptXOffset; + private short _ySuperscriptYOffset; + private short _yStrikeoutSize; + private short _yStrikeoutPosition; + private short _sFamilyClass; + private Panose _panose; + private int _ulUnicodeRange1; + private int _ulUnicodeRange2; + private int _ulUnicodeRange3; + private int _ulUnicodeRange4; + private int _achVendorID; + private short _fsSelection; + private int _usFirstCharIndex; + private int _usLastCharIndex; + private short _sTypoAscender; + private short _sTypoDescender; + private short _sTypoLineGap; + private int _usWinAscent; + private int _usWinDescent; + private int _ulCodePageRange1; + private int _ulCodePageRange2; + private short _sxHeight; + private short _sCapHeight; + private int _usDefaultChar; + private int _usBreakChar; + private int _usMaxContext; + + protected Os2Table(DirectoryEntry de, DataInput di) throws IOException { + this._de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _xAvgCharWidth = di.readShort(); + _usWeightClass = di.readUnsignedShort(); + _usWidthClass = di.readUnsignedShort(); + _fsType = di.readShort(); + _ySubscriptXSize = di.readShort(); + _ySubscriptYSize = di.readShort(); + _ySubscriptXOffset = di.readShort(); + _ySubscriptYOffset = di.readShort(); + _ySuperscriptXSize = di.readShort(); + _ySuperscriptYSize = di.readShort(); + _ySuperscriptXOffset = di.readShort(); + _ySuperscriptYOffset = di.readShort(); + _yStrikeoutSize = di.readShort(); + _yStrikeoutPosition = di.readShort(); + _sFamilyClass = di.readShort(); + byte[] buf = new byte[10]; + di.readFully(buf); + _panose = new Panose(buf); + _ulUnicodeRange1 = di.readInt(); + _ulUnicodeRange2 = di.readInt(); + _ulUnicodeRange3 = di.readInt(); + _ulUnicodeRange4 = di.readInt(); + _achVendorID = di.readInt(); + _fsSelection = di.readShort(); + _usFirstCharIndex = di.readUnsignedShort(); + _usLastCharIndex = di.readUnsignedShort(); + _sTypoAscender = di.readShort(); + _sTypoDescender = di.readShort(); + _sTypoLineGap = di.readShort(); + _usWinAscent = di.readUnsignedShort(); + _usWinDescent = di.readUnsignedShort(); + _ulCodePageRange1 = di.readInt(); + _ulCodePageRange2 = di.readInt(); + + // OpenType 1.3 + if (_version == 2) { + _sxHeight = di.readShort(); + _sCapHeight = di.readShort(); + _usDefaultChar = di.readUnsignedShort(); + _usBreakChar = di.readUnsignedShort(); + _usMaxContext = di.readUnsignedShort(); + } + } + + public int getVersion() { + return _version; + } + + public short getAvgCharWidth() { + return _xAvgCharWidth; + } + + public int getWeightClass() { + return _usWeightClass; + } + + public int getWidthClass() { + return _usWidthClass; + } + + public short getLicenseType() { + return _fsType; + } + + public short getSubscriptXSize() { + return _ySubscriptXSize; + } + + public short getSubscriptYSize() { + return _ySubscriptYSize; + } + + public short getSubscriptXOffset() { + return _ySubscriptXOffset; + } + + public short getSubscriptYOffset() { + return _ySubscriptYOffset; + } + + public short getSuperscriptXSize() { + return _ySuperscriptXSize; + } + + public short getSuperscriptYSize() { + return _ySuperscriptYSize; + } + + public short getSuperscriptXOffset() { + return _ySuperscriptXOffset; + } + + public short getSuperscriptYOffset() { + return _ySuperscriptYOffset; + } + + public short getStrikeoutSize() { + return _yStrikeoutSize; + } + + public short getStrikeoutPosition() { + return _yStrikeoutPosition; + } + + public short getFamilyClass() { + return _sFamilyClass; + } + + public Panose getPanose() { + return _panose; + } + + public int getUnicodeRange1() { + return _ulUnicodeRange1; + } + + public int getUnicodeRange2() { + return _ulUnicodeRange2; + } + + public int getUnicodeRange3() { + return _ulUnicodeRange3; + } + + public int getUnicodeRange4() { + return _ulUnicodeRange4; + } + + public int getVendorID() { + return _achVendorID; + } + + public short getSelection() { + return _fsSelection; + } + + public int getFirstCharIndex() { + return _usFirstCharIndex; + } + + public int getLastCharIndex() { + return _usLastCharIndex; + } + + public short getTypoAscender() { + return _sTypoAscender; + } + + public short getTypoDescender() { + return _sTypoDescender; + } + + public short getTypoLineGap() { + return _sTypoLineGap; + } + + public int getWinAscent() { + return _usWinAscent; + } + + public int getWinDescent() { + return _usWinDescent; + } + + public int getCodePageRange1() { + return _ulCodePageRange1; + } + + public int getCodePageRange2() { + return _ulCodePageRange2; + } + + public short getXHeight() { + return _sxHeight; + } + + public short getCapHeight() { + return _sCapHeight; + } + + public int getDefaultChar() { + return _usDefaultChar; + } + + public int getBreakChar() { + return _usBreakChar; + } + + public int getMaxContext() { + return _usMaxContext; + } + + public int getType() { + return OS_2; + } + + public String toString() { + return new StringBuffer() + .append("'OS/2' Table - OS/2 and Windows Metrics\n---------------------------------------") + .append("\n 'OS/2' version: ").append(_version) + .append("\n xAvgCharWidth: ").append(_xAvgCharWidth) + .append("\n usWeightClass: ").append(_usWeightClass) + .append("\n usWidthClass: ").append(_usWidthClass) + .append("\n fsType: 0x").append(Integer.toHexString(_fsType).toUpperCase()) + .append("\n ySubscriptXSize: ").append(_ySubscriptXSize) + .append("\n ySubscriptYSize: ").append(_ySubscriptYSize) + .append("\n ySubscriptXOffset: ").append(_ySubscriptXOffset) + .append("\n ySubscriptYOffset: ").append(_ySubscriptYOffset) + .append("\n ySuperscriptXSize: ").append(_ySuperscriptXSize) + .append("\n ySuperscriptYSize: ").append(_ySuperscriptYSize) + .append("\n ySuperscriptXOffset: ").append(_ySuperscriptXOffset) + .append("\n ySuperscriptYOffset: ").append(_ySuperscriptYOffset) + .append("\n yStrikeoutSize: ").append(_yStrikeoutSize) + .append("\n yStrikeoutPosition: ").append(_yStrikeoutPosition) + .append("\n sFamilyClass: ").append(_sFamilyClass>>8) + .append(" subclass = ").append(_sFamilyClass&0xff) + .append("\n PANOSE: ").append(_panose.toString()) + .append("\n Unicode Range 1( Bits 0 - 31 ): ").append(Integer.toHexString(_ulUnicodeRange1).toUpperCase()) + .append("\n Unicode Range 2( Bits 32- 63 ): ").append(Integer.toHexString(_ulUnicodeRange2).toUpperCase()) + .append("\n Unicode Range 3( Bits 64- 95 ): ").append(Integer.toHexString(_ulUnicodeRange3).toUpperCase()) + .append("\n Unicode Range 4( Bits 96-127 ): ").append(Integer.toHexString(_ulUnicodeRange4).toUpperCase()) + .append("\n achVendID: '").append(getVendorIDAsString()) + .append("'\n fsSelection: 0x").append(Integer.toHexString(_fsSelection).toUpperCase()) + .append("\n usFirstCharIndex: 0x").append(Integer.toHexString(_usFirstCharIndex).toUpperCase()) + .append("\n usLastCharIndex: 0x").append(Integer.toHexString(_usLastCharIndex).toUpperCase()) + .append("\n sTypoAscender: ").append(_sTypoAscender) + .append("\n sTypoDescender: ").append(_sTypoDescender) + .append("\n sTypoLineGap: ").append(_sTypoLineGap) + .append("\n usWinAscent: ").append(_usWinAscent) + .append("\n usWinDescent: ").append(_usWinDescent) + .append("\n CodePage Range 1( Bits 0 - 31 ): ").append(Integer.toHexString(_ulCodePageRange1).toUpperCase()) + .append("\n CodePage Range 2( Bits 32- 63 ): ").append(Integer.toHexString(_ulCodePageRange2).toUpperCase()) + .toString(); + } + + private String getVendorIDAsString() { + return new StringBuffer() + .append((char)((_achVendorID>>24)&0xff)) + .append((char)((_achVendorID>>16)&0xff)) + .append((char)((_achVendorID>>8)&0xff)) + .append((char)((_achVendorID)&0xff)) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Panose.java b/src/net/java/dev/typecast/ot/table/Panose.java new file mode 100644 index 000000000..fe0a357d2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Panose.java @@ -0,0 +1,96 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +/** + * @version $Id: Panose.java,v 1.1.1.1 2004-12-05 23:14:54 davidsch Exp $ + * @author David Schweinsberg + */ +public class Panose { + + byte bFamilyType = 0; + byte bSerifStyle = 0; + byte bWeight = 0; + byte bProportion = 0; + byte bContrast = 0; + byte bStrokeVariation = 0; + byte bArmStyle = 0; + byte bLetterform = 0; + byte bMidline = 0; + byte bXHeight = 0; + + /** Creates new Panose */ + public Panose(byte[] panose) { + bFamilyType = panose[0]; + bSerifStyle = panose[1]; + bWeight = panose[2]; + bProportion = panose[3]; + bContrast = panose[4]; + bStrokeVariation = panose[5]; + bArmStyle = panose[6]; + bLetterform = panose[7]; + bMidline = panose[8]; + bXHeight = panose[9]; + } + + public byte getFamilyType() { + return bFamilyType; + } + + public byte getSerifStyle() { + return bSerifStyle; + } + + public byte getWeight() { + return bWeight; + } + + public byte getProportion() { + return bProportion; + } + + public byte getContrast() { + return bContrast; + } + + public byte getStrokeVariation() { + return bStrokeVariation; + } + + public byte getArmStyle() { + return bArmStyle; + } + + public byte getLetterForm() { + return bLetterform; + } + + public byte getMidline() { + return bMidline; + } + + public byte getXHeight() { + return bXHeight; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(String.valueOf(bFamilyType)).append(" ") + .append(String.valueOf(bSerifStyle)).append(" ") + .append(String.valueOf(bWeight)).append(" ") + .append(String.valueOf(bProportion)).append(" ") + .append(String.valueOf(bContrast)).append(" ") + .append(String.valueOf(bStrokeVariation)).append(" ") + .append(String.valueOf(bArmStyle)).append(" ") + .append(String.valueOf(bLetterform)).append(" ") + .append(String.valueOf(bMidline)).append(" ") + .append(String.valueOf(bXHeight)); + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/PcltTable.java b/src/net/java/dev/typecast/ot/table/PcltTable.java new file mode 100644 index 000000000..457aec2e1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PcltTable.java @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: PcltTable.java,v 1.1.1.1 2004-12-05 23:14:54 davidsch Exp $ + * @author David Schweinsberg + */ +public class PcltTable implements Table { + + private DirectoryEntry de; + private int version; + private long fontNumber; + private int pitch; + private int xHeight; + private int style; + private int typeFamily; + private int capHeight; + private int symbolSet; + private char[] typeface = new char[16]; + private short[] characterComplement = new short[8]; + private char[] fileName = new char[6]; + private short strokeWeight; + private short widthType; + private byte serifStyle; + private byte reserved; + + /** Creates new PcltTable */ + protected PcltTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + fontNumber = di.readInt(); + pitch = di.readUnsignedShort(); + xHeight = di.readUnsignedShort(); + style = di.readUnsignedShort(); + typeFamily = di.readUnsignedShort(); + capHeight = di.readUnsignedShort(); + symbolSet = di.readUnsignedShort(); + for (int i = 0; i < 16; i++) { + typeface[i] = (char) di.readUnsignedByte(); + } + for (int i = 0; i < 8; i++) { + characterComplement[i] = (short) di.readUnsignedByte(); + } + for (int i = 0; i < 6; i++) { + fileName[i] = (char) di.readUnsignedByte(); + } + strokeWeight = (short) di.readUnsignedByte(); + widthType = (short) di.readUnsignedByte(); + serifStyle = di.readByte(); + reserved = di.readByte(); + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return PCLT; + } + + public String toString() { + return new StringBuffer() + .append("'PCLT' Table - Printer Command Language Table\n---------------------------------------------") + .append("\n version: 0x").append(Integer.toHexString(version).toUpperCase()) + .append("\n fontNumber: ").append(fontNumber).append(" (0x").append(Long.toHexString(fontNumber).toUpperCase()) + .append(")\n pitch: ").append(pitch) + .append("\n xHeight: ").append(xHeight) + .append("\n style: 0x").append(style) + .append("\n typeFamily: 0x").append(typeFamily>>12) + .append(" ").append(typeFamily & 0xfff) + .append("\n capHeight: ").append(capHeight) + .append("\n symbolSet: ").append(symbolSet) + .append("\n typeFace: ").append(new String(typeface)) + .append("\n characterComplement 0x") + .append(Integer.toHexString(characterComplement[0]).toUpperCase()) + .append("\n fileName: ").append(new String(fileName)) + .append("\n strokeWeight: ").append(strokeWeight) + .append("\n widthType: ").append(widthType) + .append("\n serifStyle: ").append(serifStyle) + .append("\n reserved: ").append(reserved) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/PostTable.java b/src/net/java/dev/typecast/ot/table/PostTable.java new file mode 100644 index 000000000..4a1b0650b --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PostTable.java @@ -0,0 +1,422 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * + * @author David Schweinsberg + * @version $Id: PostTable.java,v 1.1.1.1 2004-12-05 23:14:56 davidsch Exp $ + */ +public class PostTable implements Table { + + /** + * TODO: Mac Glyph names for 210 & 257 + */ + private static final String[] macGlyphName = { + ".notdef", // 0 + "null", // 1 + "CR", // 2 + "space", // 3 + "exclam", // 4 + "quotedbl", // 5 + "numbersign", // 6 + "dollar", // 7 + "percent", // 8 + "ampersand", // 9 + "quotesingle", // 10 + "parenleft", // 11 + "parenright", // 12 + "asterisk", // 13 + "plus", // 14 + "comma", // 15 + "hyphen", // 16 + "period", // 17 + "slash", // 18 + "zero", // 19 + "one", // 20 + "two", // 21 + "three", // 22 + "four", // 23 + "five", // 24 + "six", // 25 + "seven", // 26 + "eight", // 27 + "nine", // 28 + "colon", // 29 + "semicolon", // 30 + "less", // 31 + "equal", // 32 + "greater", // 33 + "question", // 34 + "at", // 35 + "A", // 36 + "B", // 37 + "C", // 38 + "D", // 39 + "E", // 40 + "F", // 41 + "G", // 42 + "H", // 43 + "I", // 44 + "J", // 45 + "K", // 46 + "L", // 47 + "M", // 48 + "N", // 49 + "O", // 50 + "P", // 51 + "Q", // 52 + "R", // 53 + "S", // 54 + "T", // 55 + "U", // 56 + "V", // 57 + "W", // 58 + "X", // 59 + "Y", // 60 + "Z", // 61 + "bracketleft", // 62 + "backslash", // 63 + "bracketright", // 64 + "asciicircum", // 65 + "underscore", // 66 + "grave", // 67 + "a", // 68 + "b", // 69 + "c", // 70 + "d", // 71 + "e", // 72 + "f", // 73 + "g", // 74 + "h", // 75 + "i", // 76 + "j", // 77 + "k", // 78 + "l", // 79 + "m", // 80 + "n", // 81 + "o", // 82 + "p", // 83 + "q", // 84 + "r", // 85 + "s", // 86 + "t", // 87 + "u", // 88 + "v", // 89 + "w", // 90 + "x", // 91 + "y", // 92 + "z", // 93 + "braceleft", // 94 + "bar", // 95 + "braceright", // 96 + "asciitilde", // 97 + "Adieresis", // 98 + "Aring", // 99 + "Ccedilla", // 100 + "Eacute", // 101 + "Ntilde", // 102 + "Odieresis", // 103 + "Udieresis", // 104 + "aacute", // 105 + "agrave", // 106 + "acircumflex", // 107 + "adieresis", // 108 + "atilde", // 109 + "aring", // 110 + "ccedilla", // 111 + "eacute", // 112 + "egrave", // 113 + "ecircumflex", // 114 + "edieresis", // 115 + "iacute", // 116 + "igrave", // 117 + "icircumflex", // 118 + "idieresis", // 119 + "ntilde", // 120 + "oacute", // 121 + "ograve", // 122 + "ocircumflex", // 123 + "odieresis", // 124 + "otilde", // 125 + "uacute", // 126 + "ugrave", // 127 + "ucircumflex", // 128 + "udieresis", // 129 + "dagger", // 130 + "degree", // 131 + "cent", // 132 + "sterling", // 133 + "section", // 134 + "bullet", // 135 + "paragraph", // 136 + "germandbls", // 137 + "registered", // 138 + "copyright", // 139 + "trademark", // 140 + "acute", // 141 + "dieresis", // 142 + "notequal", // 143 + "AE", // 144 + "Oslash", // 145 + "infinity", // 146 + "plusminus", // 147 + "lessequal", // 148 + "greaterequal", // 149 + "yen", // 150 + "mu", // 151 + "partialdiff", // 152 + "summation", // 153 + "product", // 154 + "pi", // 155 + "integral'", // 156 + "ordfeminine", // 157 + "ordmasculine", // 158 + "Omega", // 159 + "ae", // 160 + "oslash", // 161 + "questiondown", // 162 + "exclamdown", // 163 + "logicalnot", // 164 + "radical", // 165 + "florin", // 166 + "approxequal", // 167 + "increment", // 168 + "guillemotleft",// 169 + "guillemotright",//170 + "ellipsis", // 171 + "nbspace", // 172 + "Agrave", // 173 + "Atilde", // 174 + "Otilde", // 175 + "OE", // 176 + "oe", // 177 + "endash", // 178 + "emdash", // 179 + "quotedblleft", // 180 + "quotedblright",// 181 + "quoteleft", // 182 + "quoteright", // 183 + "divide", // 184 + "lozenge", // 185 + "ydieresis", // 186 + "Ydieresis", // 187 + "fraction", // 188 + "currency", // 189 + "guilsinglleft",// 190 + "guilsinglright",//191 + "fi", // 192 + "fl", // 193 + "daggerdbl", // 194 + "middot", // 195 + "quotesinglbase",//196 + "quotedblbase", // 197 + "perthousand", // 198 + "Acircumflex", // 199 + "Ecircumflex", // 200 + "Aacute", // 201 + "Edieresis", // 202 + "Egrave", // 203 + "Iacute", // 204 + "Icircumflex", // 205 + "Idieresis", // 206 + "Igrave", // 207 + "Oacute", // 208 + "Ocircumflex", // 209 + "", // 210 + "Ograve", // 211 + "Uacute", // 212 + "Ucircumflex", // 213 + "Ugrave", // 214 + "dotlessi", // 215 + "circumflex", // 216 + "tilde", // 217 + "overscore", // 218 + "breve", // 219 + "dotaccent", // 220 + "ring", // 221 + "cedilla", // 222 + "hungarumlaut", // 223 + "ogonek", // 224 + "caron", // 225 + "Lslash", // 226 + "lslash", // 227 + "Scaron", // 228 + "scaron", // 229 + "Zcaron", // 230 + "zcaron", // 231 + "brokenbar", // 232 + "Eth", // 233 + "eth", // 234 + "Yacute", // 235 + "yacute", // 236 + "Thorn", // 237 + "thorn", // 238 + "minus", // 239 + "multiply", // 240 + "onesuperior", // 241 + "twosuperior", // 242 + "threesuperior",// 243 + "onehalf", // 244 + "onequarter", // 245 + "threequarters",// 246 + "franc", // 247 + "Gbreve", // 248 + "gbreve", // 249 + "Idot", // 250 + "Scedilla", // 251 + "scedilla", // 252 + "Cacute", // 253 + "cacute", // 254 + "Ccaron", // 255 + "ccaron", // 256 + "" // 257 + }; + + private DirectoryEntry de; + private int version; + private int italicAngle; + private short underlinePosition; + private short underlineThickness; + private int isFixedPitch; + private int minMemType42; + private int maxMemType42; + private int minMemType1; + private int maxMemType1; + + // v2 + private int numGlyphs; + private int[] glyphNameIndex; + private String[] psGlyphName; + + /** Creates new PostTable */ + protected PostTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + italicAngle = di.readInt(); + underlinePosition = di.readShort(); + underlineThickness = di.readShort(); + isFixedPitch = di.readInt(); + minMemType42 = di.readInt(); + maxMemType42 = di.readInt(); + minMemType1 = di.readInt(); + maxMemType1 = di.readInt(); + + if (version == 0x00020000) { + numGlyphs = di.readUnsignedShort(); + glyphNameIndex = new int[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + glyphNameIndex[i] = di.readUnsignedShort(); + } + int h = highestGlyphNameIndex(); + if (h > 257) { + h -= 257; + psGlyphName = new String[h]; + for (int i = 0; i < h; i++) { + int len = di.readUnsignedByte(); + byte[] buf = new byte[len]; + di.readFully(buf); + psGlyphName[i] = new String(buf); + } + } + } else if (version == 0x00025000) { + } else if (version == 0x00030000) { + } + } + + public int getVersion() { + return version; + } + + private int highestGlyphNameIndex() { + int high = 0; + for (int i = 0; i < numGlyphs; i++) { + if (high < glyphNameIndex[i]) { + high = glyphNameIndex[i]; + } + } + return high; + } + + public String getGlyphName(int i) { + if (version == 0x00020000) { + return (glyphNameIndex[i] > 257) + ? psGlyphName[glyphNameIndex[i] - 258] + : macGlyphName[glyphNameIndex[i]]; + } else { + return null; + } + } + + private boolean isMacGlyphName(int i) { + if (version == 0x00020000) { + return glyphNameIndex[i] <= 257; + } else { + return false; + } + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return post; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'post' Table - PostScript Metrics\n---------------------------------\n") + .append("\n 'post' version: ").append(Fixed.floatValue(version)) + .append("\n italicAngle: ").append(Fixed.floatValue(italicAngle)) + .append("\n underlinePosition: ").append(underlinePosition) + .append("\n underlineThickness: ").append(underlineThickness) + .append("\n isFixedPitch: ").append(isFixedPitch) + .append("\n minMemType42: ").append(minMemType42) + .append("\n maxMemType42: ").append(maxMemType42) + .append("\n minMemType1: ").append(minMemType1) + .append("\n maxMemType1: ").append(maxMemType1); + + if (version == 0x00020000) { + sb.append("\n\n Format 2.0: Non-Standard (for PostScript) TrueType Glyph Set.\n"); + sb.append(" numGlyphs: ").append(numGlyphs).append("\n"); + for (int i = 0; i < numGlyphs; i++) { + sb.append(" Glyf ").append(i).append(" -> "); + if (isMacGlyphName(i)) { + sb.append("Mac Glyph # ").append(glyphNameIndex[i]) + .append(", '").append(macGlyphName[glyphNameIndex[i]]).append("'\n"); + } else { + sb.append("PSGlyf Name # ").append(glyphNameIndex[i] - 257) + .append(", name= '").append(psGlyphName[glyphNameIndex[i] - 258]).append("'\n"); + } + } + sb.append("\n Full List of PSGlyf Names\n ------------------------\n"); + for (int i = 0; i < psGlyphName.length; i++) { + sb.append(" PSGlyf Name # ").append(i + 1) + .append(": ").append(psGlyphName[i]) + .append("\n"); + } + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/PrepTable.java b/src/net/java/dev/typecast/ot/table/PrepTable.java new file mode 100644 index 000000000..938b9b840 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PrepTable.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: PrepTable.java,v 1.1.1.1 2004-12-05 23:14:57 davidsch Exp $ + * @author David Schweinsberg + */ +public class PrepTable extends Program implements Table { + + private DirectoryEntry de; + + public PrepTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + readInstructions(di, de.getLength()); + } + + public int getType() { + return prep; + } + + public String toString() { + return Disassembler.disassemble(getInstructions(), 0); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Program.java b/src/net/java/dev/typecast/ot/table/Program.java new file mode 100644 index 000000000..6fd02a469 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Program.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import java.io.ByteArrayInputStream; + +/** + * @version $Id: Program.java,v 1.1.1.1 2004-12-05 23:14:57 davidsch Exp $ + * @author David Schweinsberg + */ +public abstract class Program { + + private short[] instructions; + + public short[] getInstructions() { + return instructions; + } + + protected void readInstructions(DataInput di, int count) throws IOException { + instructions = new short[count]; + for (int i = 0; i < count; i++) { + instructions[i] = (short) di.readUnsignedByte(); + } + } +/* + protected void readInstructions(ByteArrayInputStream bais, int count) { + instructions = new short[count]; + for (int i = 0; i < count; i++) { + instructions[i] = (short) bais.read(); + } + } +*/ +} diff --git a/src/net/java/dev/typecast/ot/table/RangeRecord.java b/src/net/java/dev/typecast/ot/table/RangeRecord.java new file mode 100644 index 000000000..3bcb9ccb5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/RangeRecord.java @@ -0,0 +1,87 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Coverage Index (GlyphID) = StartCoverageIndex + GlyphID - Start GlyphID + * + * @author David Schweinsberg + * @version $Id: RangeRecord.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class RangeRecord { + + private int _start; + private int _end; + private int _startCoverageIndex; + + /** Creates new RangeRecord */ + public RangeRecord(DataInput di) throws IOException { + _start = di.readUnsignedShort(); + _end = di.readUnsignedShort(); + _startCoverageIndex = di.readUnsignedShort(); + } + + public boolean isInRange(int glyphId) { + return (_start <= glyphId && glyphId <= _end); + } + + public int getCoverageIndex(int glyphId) { + if (isInRange(glyphId)) { + return _startCoverageIndex + glyphId - _start; + } + return -1; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/Script.java b/src/net/java/dev/typecast/ot/table/Script.java new file mode 100644 index 000000000..e3022c116 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Script.java @@ -0,0 +1,118 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: Script.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class Script { + + private int _defaultLangSysOffset; + private int _langSysCount; + private LangSysRecord[] _langSysRecords; + private LangSys _defaultLangSys; + private LangSys[] _langSys; + + /** Creates new ScriptTable */ + protected Script(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _defaultLangSysOffset = dis.readUnsignedShort(); + _langSysCount = dis.readUnsignedShort(); + if (_langSysCount > 0) { + _langSysRecords = new LangSysRecord[_langSysCount]; + for (int i = 0; i < _langSysCount; i++) { + _langSysRecords[i] = new LangSysRecord(dis); + } + } + + // Read the LangSys tables + if (_langSysCount > 0) { + _langSys = new LangSys[_langSysCount]; + for (int i = 0; i < _langSysCount; i++) { + dis.reset(); + dis.skipBytes(offset + _langSysRecords[i].getOffset()); + _langSys[i] = new LangSys(dis); + } + } + if (_defaultLangSysOffset > 0) { + dis.reset(); + dis.skipBytes(offset + _defaultLangSysOffset); + _defaultLangSys = new LangSys(dis); + } + } + + public int getLangSysCount() { + return _langSysCount; + } + + public LangSysRecord getLangSysRecord(int i) { + return _langSysRecords[i]; + } + + public LangSys getDefaultLangSys() { + return _defaultLangSys; + } + + public LangSys getLangSys(int i) { + return _langSys[i]; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/ScriptList.java b/src/net/java/dev/typecast/ot/table/ScriptList.java new file mode 100644 index 000000000..bd82a052f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptList.java @@ -0,0 +1,115 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ScriptList.java,v 1.3 2007-01-24 09:54:44 davidsch Exp $ + */ +public class ScriptList { + + private int _scriptCount = 0; + private ScriptRecord[] _scriptRecords; + private Script[] _scripts; + + /** Creates new ScriptList */ + protected ScriptList(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _scriptCount = dis.readUnsignedShort(); + _scriptRecords = new ScriptRecord[_scriptCount]; + _scripts = new Script[_scriptCount]; + for (int i = 0; i < _scriptCount; i++) { + _scriptRecords[i] = new ScriptRecord(dis); + } + for (int i = 0; i < _scriptCount; i++) { + _scripts[i] = new Script(dis, offset + _scriptRecords[i].getOffset()); + } + } + + public int getScriptCount() { + return _scriptCount; + } + + public ScriptRecord getScriptRecord(int i) { + return _scriptRecords[i]; + } + + public Script getScript(int i) { + return _scripts[i]; + } + + public Script findScript(String tag) { + if (tag.length() != 4) { + return null; + } + int tagVal = ((tag.charAt(0)<<24) + | (tag.charAt(1)<<16) + | (tag.charAt(2)<<8) + | tag.charAt(3)); + for (int i = 0; i < _scriptCount; i++) { + if (_scriptRecords[i].getTag() == tagVal) { + return _scripts[i]; + } + } + return null; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/ScriptRecord.java b/src/net/java/dev/typecast/ot/table/ScriptRecord.java new file mode 100644 index 000000000..aea0bf0df --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: ScriptRecord.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class ScriptRecord { + + private int _tag; + private int _offset; + + /** Creates new ScriptRecord */ + protected ScriptRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/ScriptTags.java b/src/net/java/dev/typecast/ot/table/ScriptTags.java new file mode 100644 index 000000000..eeb4f8e25 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptTags.java @@ -0,0 +1,61 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Definition of Script tags + * + * @version $Id: ScriptTags.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + * @author Vincent Hardy + */ +public interface ScriptTags { + public static final String SCRIPT_TAG_ARAB = "arab"; +} diff --git a/src/net/java/dev/typecast/ot/table/SignatureBlock.java b/src/net/java/dev/typecast/ot/table/SignatureBlock.java new file mode 100644 index 000000000..2e4acf525 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SignatureBlock.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: SignatureBlock.java,v 1.1.1.1 2004-12-05 23:14:58 davidsch Exp $ + * @author David Schweinsberg + */ +public class SignatureBlock { + + private int reserved1; + private int reserved2; + private int signatureLen; + private byte[] signature; + + /** Creates new SignatureBlock */ + protected SignatureBlock(DataInput di) throws IOException { + reserved1 = di.readUnsignedShort(); + reserved2 = di.readUnsignedShort(); + signatureLen = di.readInt(); + signature = new byte[signatureLen]; + di.readFully(signature); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < signatureLen; i += 16) { + if (signatureLen - i >= 16) { + sb.append(new String(signature, i, 16)).append("\n"); + } else { + sb.append(new String(signature, i, signatureLen - i)).append("\n"); + } + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/SingleSubst.java b/src/net/java/dev/typecast/ot/table/SingleSubst.java new file mode 100644 index 000000000..91c985883 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubst.java @@ -0,0 +1,81 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: SingleSubst.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public abstract class SingleSubst extends LookupSubtable { + + public abstract int getFormat(); + + public abstract int substitute(int glyphId); + + public static SingleSubst read(DataInputStream dis, int offset) throws IOException { + SingleSubst s = null; + dis.reset(); + dis.skipBytes(offset); + int format = dis.readUnsignedShort(); + if (format == 1) { + s = new SingleSubstFormat1(dis, offset); + } else if (format == 2) { + s = new SingleSubstFormat2(dis, offset); + } + return s; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java b/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java new file mode 100644 index 000000000..538c57f6d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java @@ -0,0 +1,92 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: SingleSubstFormat1.java,v 1.2 2007-01-24 09:47:45 davidsch Exp $ + */ +public class SingleSubstFormat1 extends SingleSubst { + + private int _coverageOffset; + private short _deltaGlyphID; + private Coverage _coverage; + + /** Creates new SingleSubstFormat1 */ + protected SingleSubstFormat1(DataInputStream dis, int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _deltaGlyphID = dis.readShort(); + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + } + + public int getFormat() { + return 1; + } + + public int substitute(int glyphId) { + int i = _coverage.findGlyph(glyphId); + if (i > -1) { + return glyphId + _deltaGlyphID; + } + return glyphId; + } + + public String getTypeAsString() { + return "SingleSubstFormat1"; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java b/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java new file mode 100644 index 000000000..74c68f71f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java @@ -0,0 +1,97 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author David Schweinsberg + * @version $Id: SingleSubstFormat2.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class SingleSubstFormat2 extends SingleSubst { + + private int _coverageOffset; + private int _glyphCount; + private int[] _substitutes; + private Coverage _coverage; + + /** Creates new SingleSubstFormat2 */ + protected SingleSubstFormat2(DataInputStream dis, int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _glyphCount = dis.readUnsignedShort(); + _substitutes = new int[_glyphCount]; + for (int i = 0; i < _glyphCount; i++) { + _substitutes[i] = dis.readUnsignedShort(); + } + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + } + + public int getFormat() { + return 2; + } + + public int substitute(int glyphId) { + int i = _coverage.findGlyph(glyphId); + if (i > -1) { + return _substitutes[i]; + } + return glyphId; + } + + public String getTypeAsString() { + return "SingleSubstFormat2"; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/TTCHeader.java b/src/net/java/dev/typecast/ot/table/TTCHeader.java new file mode 100644 index 000000000..2f38d33f4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TTCHeader.java @@ -0,0 +1,59 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: TTCHeader.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + * @author David Schweinsberg + */ +public class TTCHeader { + + public static final int ttcf = 0x74746366; + + private int ttcTag; + private int version; + private int directoryCount; + private int[] tableDirectory; + private int dsigTag; + private int dsigLength; + private int dsigOffset; + + /** Creates new TTCHeader */ + public TTCHeader(DataInput di) throws IOException { + ttcTag = di.readInt(); + version = di.readInt(); + directoryCount = di.readInt(); + tableDirectory = new int[directoryCount]; + for (int i = 0; i < directoryCount; i++) { + tableDirectory[i] = di.readInt(); + } + if (version == 0x00010000) { + dsigTag = di.readInt(); + } + dsigLength = di.readInt(); + dsigOffset = di.readInt(); + } + + public int getDirectoryCount() { + return directoryCount; + } + + public int getTableDirectory(int i) { + return tableDirectory[i]; + } + + public static boolean isTTC(DataInput di) throws IOException { + int ttcTag = di.readInt(); + return ttcTag == ttcf; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Table.java b/src/net/java/dev/typecast/ot/table/Table.java new file mode 100644 index 000000000..ddbdc49e2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Table.java @@ -0,0 +1,67 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +/** + * @version $Id: Table.java,v 1.1.1.1 2004-12-05 23:14:59 davidsch Exp $ + * @author David Schweinsberg + */ +public interface Table { + + // Table constants + public static final int BASE = 0x42415345; // Baseline data [OpenType] + public static final int CFF = 0x43464620; // PostScript font program (compact font format) [PostScript] + public static final int DSIG = 0x44534947; // Digital signature + public static final int EBDT = 0x45424454; // Embedded bitmap data + public static final int EBLC = 0x45424c43; // Embedded bitmap location data + public static final int EBSC = 0x45425343; // Embedded bitmap scaling data + public static final int GDEF = 0x47444546; // Glyph definition data [OpenType] + public static final int GPOS = 0x47504f53; // Glyph positioning data [OpenType] + public static final int GSUB = 0x47535542; // Glyph substitution data [OpenType] + public static final int JSTF = 0x4a535446; // Justification data [OpenType] + public static final int LTSH = 0x4c545348; // Linear threshold table + public static final int MMFX = 0x4d4d4658; // Multiple master font metrics [PostScript] + public static final int MMSD = 0x4d4d5344; // Multiple master supplementary data [PostScript] + public static final int OS_2 = 0x4f532f32; // OS/2 and Windows specific metrics [r] + public static final int PCLT = 0x50434c54; // PCL5 + public static final int VDMX = 0x56444d58; // Vertical Device Metrics table + public static final int cmap = 0x636d6170; // character to glyph mapping [r] + public static final int cvt = 0x63767420; // Control Value Table + public static final int fpgm = 0x6670676d; // font program + public static final int fvar = 0x66766172; // Apple's font variations table [PostScript] + public static final int gasp = 0x67617370; // grid-fitting and scan conversion procedure (grayscale) + public static final int glyf = 0x676c7966; // glyph data [r] + public static final int hdmx = 0x68646d78; // horizontal device metrics + public static final int head = 0x68656164; // font header [r] + public static final int hhea = 0x68686561; // horizontal header [r] + public static final int hmtx = 0x686d7478; // horizontal metrics [r] + public static final int kern = 0x6b65726e; // kerning + public static final int loca = 0x6c6f6361; // index to location [r] + public static final int maxp = 0x6d617870; // maximum profile [r] + public static final int name = 0x6e616d65; // naming table [r] + public static final int prep = 0x70726570; // CVT Program + public static final int post = 0x706f7374; // PostScript information [r] + public static final int vhea = 0x76686561; // Vertical Metrics header + public static final int vmtx = 0x766d7478; // Vertical Metrics + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType(); + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry(); + +} diff --git a/src/net/java/dev/typecast/ot/table/TableDirectory.java b/src/net/java/dev/typecast/ot/table/TableDirectory.java new file mode 100644 index 000000000..2eff53dd9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableDirectory.java @@ -0,0 +1,129 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: TableDirectory.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author David Schweinsberg + */ +public class TableDirectory { + + private int _version = 0; + private short _numTables = 0; + private short _searchRange = 0; + private short _entrySelector = 0; + private short _rangeShift = 0; + private DirectoryEntry[] _entries; + + public TableDirectory(DataInput di) throws IOException { + _version = di.readInt(); + _numTables = di.readShort(); + _searchRange = di.readShort(); + _entrySelector = di.readShort(); + _rangeShift = di.readShort(); + _entries = new DirectoryEntry[_numTables]; + for (int i = 0; i < _numTables; i++) { + _entries[i] = new DirectoryEntry(di); + } + } + + public DirectoryEntry getEntry(int index) { + return _entries[index]; + } + + public DirectoryEntry getEntryByTag(int tag) { + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getTag() == tag) { + return _entries[i]; + } + } + return null; + } + + public short getEntrySelector() { + return _entrySelector; + } + + public short getNumTables() { + return _numTables; + } + + public short getRangeShift() { + return _rangeShift; + } + + public short getSearchRange() { + return _searchRange; + } + + public int getVersion() { + return _version; + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("Offset Table\n------ -----") + .append("\n sfnt version: ").append(Fixed.floatValue(_version)) + .append("\n numTables = ").append(_numTables) + .append("\n searchRange = ").append(_searchRange) + .append("\n entrySelector = ").append(_entrySelector) + .append("\n rangeShift = ").append(_rangeShift) + .append("\n\n"); + for (int i = 0; i < _numTables; i++) { + sb.append(i).append(". ").append(_entries[i].toString()).append("\n"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/TableException.java b/src/net/java/dev/typecast/ot/table/TableException.java new file mode 100644 index 000000000..02bc49eb5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableException.java @@ -0,0 +1,46 @@ +/* + * $Id: TableException.java,v 1.1.1.1 2004-12-05 23:15:00 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +/** + * + * @author David Schweinsberg + * @version $Id: TableException.java,v 1.1.1.1 2004-12-05 23:15:00 davidsch Exp $ + */ +public class TableException extends java.lang.Exception { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance of TableException without detail message. + */ + public TableException() { + } + + + /** + * Constructs an instance of TableException with the specified detail message. + * @param msg the detail message. + */ + public TableException(String msg) { + super(msg); + } +} diff --git a/src/net/java/dev/typecast/ot/table/TableFactory.java b/src/net/java/dev/typecast/ot/table/TableFactory.java new file mode 100644 index 000000000..632abcf44 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableFactory.java @@ -0,0 +1,185 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.IOException; +import net.java.dev.typecast.ot.OTFont; +import net.java.dev.typecast.ot.OTFontCollection; + +/** + * + * @version $Id: TableFactory.java,v 1.7 2007-02-05 12:39:51 davidsch Exp $ + * @author David Schweinsberg + */ +public class TableFactory { + + public static Table create( + OTFontCollection fc, + OTFont font, + DirectoryEntry de, + DataInputStream dis) throws IOException { + Table t = null; + + // First, if we have a font collection, look for the table there + if (fc != null) { + t = fc.getTable(de); + if (t != null) { + return t; + } + } + + // Create the table + switch (de.getTag()) { + case Table.BASE: + t = new BaseTable(de, dis); + break; + case Table.CFF: + t = new CffTable(de, dis); + break; + case Table.DSIG: + t = new DsigTable(de, dis); + break; + case Table.EBDT: + break; + case Table.EBLC: + break; + case Table.EBSC: + break; + case Table.GDEF: + break; + case Table.GPOS: + t = new GposTable(de, dis); + break; + case Table.GSUB: + t = new GsubTable(de, dis); + break; + case Table.JSTF: + break; + case Table.LTSH: + t = new LtshTable(de, dis); + break; + case Table.MMFX: + break; + case Table.MMSD: + break; + case Table.OS_2: + t = new Os2Table(de, dis); + break; + case Table.PCLT: + t = new PcltTable(de, dis); + break; + case Table.VDMX: + t = new VdmxTable(de, dis); + break; + case Table.cmap: + t = new CmapTable(de, dis); + break; + case Table.cvt: + t = new CvtTable(de, dis); + break; + case Table.fpgm: + t = new FpgmTable(de, dis); + break; + case Table.fvar: + break; + case Table.gasp: + t = new GaspTable(de, dis); + break; + case Table.glyf: + t = new GlyfTable(de, dis, font.getMaxpTable(), font.getLocaTable()); + break; + case Table.hdmx: + t = new HdmxTable(de, dis, font.getMaxpTable()); + break; + case Table.head: + t = new HeadTable(de, dis); + break; + case Table.hhea: + t = new HheaTable(de, dis); + break; + case Table.hmtx: + t = new HmtxTable(de, dis, font.getHheaTable(), font.getMaxpTable()); + break; + case Table.kern: + t = new KernTable(de, dis); + break; + case Table.loca: + t = new LocaTable(de, dis, font.getHeadTable(), font.getMaxpTable()); + break; + case Table.maxp: + t = new MaxpTable(de, dis); + break; + case Table.name: + t = new NameTable(de, dis); + break; + case Table.prep: + t = new PrepTable(de, dis); + break; + case Table.post: + t = new PostTable(de, dis); + break; + case Table.vhea: + t = new VheaTable(de, dis); + break; + case Table.vmtx: + t = new VmtxTable(de, dis, font.getVheaTable(), font.getMaxpTable()); + break; + } + + // If we have a font collection, add this table to it + if ((fc != null) && (t != null)) { + fc.addTable(t); + } + return t; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VdmxTable.java b/src/net/java/dev/typecast/ot/table/VdmxTable.java new file mode 100644 index 000000000..907133b6d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VdmxTable.java @@ -0,0 +1,197 @@ +/* + * $Id: VdmxTable.java,v 1.1 2007-01-30 05:25:35 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * The Vertical Device Metrics table for TrueType outlines. + * @author David Schweinsberg + * @version $Id: VdmxTable.java,v 1.1 2007-01-30 05:25:35 davidsch Exp $ + */ +public class VdmxTable implements Table { + + private class Ratio { + + private byte _bCharSet; + private byte _xRatio; + private byte _yStartRatio; + private byte _yEndRatio; + + protected Ratio(DataInput di) throws IOException { + _bCharSet = di.readByte(); + _xRatio = di.readByte(); + _yStartRatio = di.readByte(); + _yEndRatio = di.readByte(); + } + + public byte getBCharSet() { + return _bCharSet; + } + + public byte getXRatio() { + return _xRatio; + } + + public byte getYStartRatio() { + return _yStartRatio; + } + + public byte getYEndRatio() { + return _yEndRatio; + } + } + + private class VTableRecord { + + private int _yPelHeight; + private short _yMax; + private short _yMin; + + protected VTableRecord(DataInput di) throws IOException { + _yPelHeight = di.readUnsignedShort(); + _yMax = di.readShort(); + _yMin = di.readShort(); + } + + public int getYPelHeight() { + return _yPelHeight; + } + + public short getYMax() { + return _yMax; + } + + public short getYMin() { + return _yMin; + } + } + + private class Group { + + private int _recs; + private int _startsz; + private int _endsz; + private VTableRecord[] _entry; + + protected Group(DataInput di) throws IOException { + _recs = di.readUnsignedShort(); + _startsz = di.readUnsignedByte(); + _endsz = di.readUnsignedByte(); + _entry = new VTableRecord[_recs]; + for (int i = 0; i < _recs; ++i) { + _entry[i] = new VTableRecord(di); + } + } + + public int getRecs() { + return _recs; + } + + public int getStartSZ() { + return _startsz; + } + + public int getEndSZ() { + return _endsz; + } + + public VTableRecord[] getEntry() { + return _entry; + } + } + + private DirectoryEntry _de; + private int _version; + private int _numRecs; + private int _numRatios; + private Ratio[] _ratRange; + private int _offset[]; + private Group[] _groups; + + /** Creates a new instance of VdmxTable */ + protected VdmxTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numRecs = di.readUnsignedShort(); + _numRatios = di.readUnsignedShort(); + _ratRange = new Ratio[_numRatios]; + for (int i = 0; i < _numRatios; ++i) { + _ratRange[i] = new Ratio(di); + } + _offset = new int[_numRatios]; + for (int i = 0; i < _numRatios; ++i) { + _offset[i] = di.readUnsignedShort(); + } + _groups = new Group[_numRecs]; + for (int i = 0; i < _numRecs; ++i) { + _groups[i] = new Group(di); + } + } + + public int getType() { + return VDMX; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'VDMX' Table - Precomputed Vertical Device Metrics\n") + .append("--------------------------------------------------\n") + .append(" Version: ").append(_version).append("\n") + .append(" Number of Hgt Records: ").append(_numRecs).append("\n") + .append(" Number of Ratio Records: ").append(_numRatios).append("\n"); + for (int i = 0; i < _numRatios; ++i) { + sb.append("\n Ratio Record #").append(i + 1).append("\n") + .append("\tCharSetId ").append(_ratRange[i].getBCharSet()).append("\n") + .append("\txRatio ").append(_ratRange[i].getXRatio()).append("\n") + .append("\tyStartRatio ").append(_ratRange[i].getYStartRatio()).append("\n") + .append("\tyEndRatio ").append(_ratRange[i].getYEndRatio()).append("\n") + .append("\tRecord Offset ").append(_offset[i]).append("\n"); + } + sb.append("\n VDMX Height Record Groups\n") + .append(" -------------------------\n"); + for (int i = 0; i < _numRecs; ++i) { + Group group = _groups[i]; + sb.append(" ").append(i + 1) + .append(". Number of Hgt Records ").append(group.getRecs()).append("\n") + .append(" Starting Y Pel Height ").append(group.getStartSZ()).append("\n") + .append(" Ending Y Pel Height ").append(group.getEndSZ()).append("\n"); + for (int j = 0; j < group.getRecs(); ++j) { + sb.append("\n ").append(j + 1) + .append(". Pel Height= ").append(group.getEntry()[j].getYPelHeight()).append("\n") + .append(" yMax= ").append(group.getEntry()[j].getYMax()).append("\n") + .append(" yMin= ").append(group.getEntry()[j].getYMin()).append("\n"); + } + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VheaTable.java b/src/net/java/dev/typecast/ot/table/VheaTable.java new file mode 100644 index 000000000..3863080cf --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VheaTable.java @@ -0,0 +1,147 @@ +/* + * $Id: VheaTable.java,v 1.1 2007-01-31 01:17:40 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * Vertical Header Table + * @version $Id: VheaTable.java,v 1.1 2007-01-31 01:17:40 davidsch Exp $ + * @author David Schweinsberg + */ +public class VheaTable implements Table { + + private DirectoryEntry _de; + private int _version; + private short _ascent; + private short _descent; + private short _lineGap; + private short _advanceHeightMax; + private short _minTopSideBearing; + private short _minBottomSideBearing; + private short _yMaxExtent; + private short _caretSlopeRise; + private short _caretSlopeRun; + private short _metricDataFormat; + private int _numberOfLongVerMetrics; + + protected VheaTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readInt(); + _ascent = di.readShort(); + _descent = di.readShort(); + _lineGap = di.readShort(); + _advanceHeightMax = di.readShort(); + _minTopSideBearing = di.readShort(); + _minBottomSideBearing = di.readShort(); + _yMaxExtent = di.readShort(); + _caretSlopeRise = di.readShort(); + _caretSlopeRun = di.readShort(); + for (int i = 0; i < 5; ++i) { + di.readShort(); + } + _metricDataFormat = di.readShort(); + _numberOfLongVerMetrics = di.readUnsignedShort(); + } + + public short getAdvanceHeightMax() { + return _advanceHeightMax; + } + + public short getAscent() { + return _ascent; + } + + public short getCaretSlopeRise() { + return _caretSlopeRise; + } + + public short getCaretSlopeRun() { + return _caretSlopeRun; + } + + public short getDescent() { + return _descent; + } + + public short getLineGap() { + return _lineGap; + } + + public short getMetricDataFormat() { + return _metricDataFormat; + } + + public short getMinTopSideBearing() { + return _minTopSideBearing; + } + + public short getMinBottomSideBearing() { + return _minBottomSideBearing; + } + + public int getNumberOfLongVerMetrics() { + return _numberOfLongVerMetrics; + } + + public int getType() { + return vhea; + } + + public short getYMaxExtent() { + return _yMaxExtent; + } + + public String toString() { + return new StringBuffer() + .append("'vhea' Table - Vertical Header\n------------------------------") + .append("\n 'vhea' version: ").append(Fixed.floatValue(_version)) + .append("\n xAscender: ").append(_ascent) + .append("\n xDescender: ").append(_descent) + .append("\n xLineGap: ").append(_lineGap) + .append("\n advanceHeightMax: ").append(_advanceHeightMax) + .append("\n minTopSideBearing: ").append(_minTopSideBearing) + .append("\n minBottomSideBearing: ").append(_minBottomSideBearing) + .append("\n yMaxExtent: ").append(_yMaxExtent) + .append("\n horizCaretSlopeNum: ").append(_caretSlopeRise) + .append("\n horizCaretSlopeDenom: ").append(_caretSlopeRun) + .append("\n reserved0: 0") + .append("\n reserved1: 0") + .append("\n reserved2: 0") + .append("\n reserved3: 0") + .append("\n reserved4: 0") + .append("\n metricDataFormat: ").append(_metricDataFormat) + .append("\n numOf_LongVerMetrics: ").append(_numberOfLongVerMetrics) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VmtxTable.java b/src/net/java/dev/typecast/ot/table/VmtxTable.java new file mode 100644 index 000000000..b2d9a3c3e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VmtxTable.java @@ -0,0 +1,112 @@ +/* + * $Id: VmtxTable.java,v 1.1 2007-01-31 01:18:04 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Vertical Metrics Table + * @version $Id: VmtxTable.java,v 1.1 2007-01-31 01:18:04 davidsch Exp $ + * @author David Schweinsberg + */ +public class VmtxTable implements Table { + + private DirectoryEntry _de; + private int[] _vMetrics = null; + private short[] _topSideBearing = null; + + protected VmtxTable( + DirectoryEntry de, + DataInput di, + VheaTable vhea, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _vMetrics = new int[vhea.getNumberOfLongVerMetrics()]; + for (int i = 0; i < vhea.getNumberOfLongVerMetrics(); ++i) { + _vMetrics[i] = + di.readUnsignedByte()<<24 + | di.readUnsignedByte()<<16 + | di.readUnsignedByte()<<8 + | di.readUnsignedByte(); + } + int tsbCount = maxp.getNumGlyphs() - vhea.getNumberOfLongVerMetrics(); + _topSideBearing = new short[tsbCount]; + for (int i = 0; i < tsbCount; ++i) { + _topSideBearing[i] = di.readShort(); + } + } + + public int getAdvanceHeight(int i) { + if (_vMetrics == null) { + return 0; + } + if (i < _vMetrics.length) { + return _vMetrics[i] >> 16; + } else { + return _vMetrics[_vMetrics.length - 1] >> 16; + } + } + + public short getTopSideBearing(int i) { + if (_vMetrics == null) { + return 0; + } + if (i < _vMetrics.length) { + return (short)(_vMetrics[i] & 0xffff); + } else { + return _topSideBearing[i - _vMetrics.length]; + } + } + + public int getType() { + return vmtx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'vmtx' Table - Vertical Metrics\n-------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_vMetrics.length).append(" entries\n"); + for (int i = 0; i < _vMetrics.length; i++) { + sb.append(" ").append(i) + .append(". advHeight: ").append(getAdvanceHeight(i)) + .append(", TSdBear: ").append(getTopSideBearing(i)) + .append("\n"); + } + for (int i = 0; i < _topSideBearing.length; i++) { + sb.append(" TSdBear ").append(i + _vMetrics.length) + .append(": ").append(_topSideBearing[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/t2/T2Interpreter.java b/src/net/java/dev/typecast/t2/T2Interpreter.java new file mode 100644 index 000000000..6ae59cf8d --- /dev/null +++ b/src/net/java/dev/typecast/t2/T2Interpreter.java @@ -0,0 +1,1043 @@ +/* + * $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.t2; + +import java.util.ArrayList; + +import net.java.dev.typecast.ot.Point; + +import net.java.dev.typecast.ot.table.CharstringType2; + +/** + * Type 2 Charstring Interpreter. Operator descriptions are quoted from + * Adobe's Type 2 Charstring Format document -- 5117.Type2.pdf. + * @author David Schweinsberg + * @version $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ + */ +public class T2Interpreter { + + private static final int ARGUMENT_STACK_LIMIT = 48; + private static final int SUBR_STACK_LIMIT = 10; + private static final int TRANSIENT_ARRAY_ELEMENT_COUNT = 32; + + private Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT]; + private int _argStackIndex = 0; + private int[] _subrStack = new int[SUBR_STACK_LIMIT]; + private int _subrStackIndex = 0; + private Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; + + private ArrayList _points; + + /** Creates a new instance of T2Interpreter */ + public T2Interpreter() { + } + + /** + * Moves the current point to a position at the relative coordinates + * (dx1, dy1). + */ + private void _rmoveto() { + int dy1 = popArg().intValue(); + int dx1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x + dx1, lastPoint.y + dy1); + } + + /** + * Moves the current point dx1 units in the horizontal direction. + */ + private void _hmoveto() { + int dx1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x + dx1, lastPoint.y); + } + + /** + * Moves the current point dy1 units in the vertical direction. + */ + private void _vmoveto() { + int dy1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x, lastPoint.y + dy1); + } + + /** + * Appends a line from the current point to a position at the + * relative coordinates dxa, dya. Additional rlineto operations are + * performed for all subsequent argument pairs. The number of + * lines is determined from the number of arguments on the stack. + */ + private void _rlineto() { + int count = getArgCount() / 2; + int[] dx = new int[count]; + int[] dy = new int[count]; + for (int i = 0; i < count; ++i) { + dy[count - i - 1] = popArg().intValue(); + dx[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + lineTo(lastPoint.x + dx[i], lastPoint.y + dy[i]); + } + clearArg(); + } + + /** + * Appends a horizontal line of length dx1 to the current point. + * With an odd number of arguments, subsequent argument pairs + * are interpreted as alternating values of dy and dx, for which + * additional lineto operators draw alternating vertical and + * horizontal lines. With an even number of arguments, the + * arguments are interpreted as alternating horizontal and + * vertical lines. The number of lines is determined from the + * number of arguments on the stack. + */ + private void _hlineto() { + int count = getArgCount(); + Number[] nums = new Number[count]; + for (int i = 0; i < count; ++i) { + nums[count - i - 1] = popArg(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + if (i % 2 == 0) { + lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); + } else { + lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); + } + } + clearArg(); + } + + /** + * Appends a vertical line of length dy1 to the current point. With + * an odd number of arguments, subsequent argument pairs are + * interpreted as alternating values of dx and dy, for which + * additional lineto operators draw alternating horizontal and + * vertical lines. With an even number of arguments, the + * arguments are interpreted as alternating vertical and + * horizontal lines. The number of lines is determined from the + * number of arguments on the stack. + */ + private void _vlineto() { + int count = getArgCount(); + Number[] nums = new Number[count]; + for (int i = 0; i < count; ++i) { + nums[count - i - 1] = popArg(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + if (i % 2 == 0) { + lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); + } else { + lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); + } + } + clearArg(); + } + + /** + * Appends a Bezier curve, defined by dxa...dyc, to the current + * point. For each subsequent set of six arguments, an additional + * curve is appended to the current point. The number of curve + * segments is determined from the number of arguments on the + * number stack and is limited only by the size of the number + * stack. + */ + private void _rrcurveto() { + int count = getArgCount() / 6; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dyc = new int[count]; + for (int i = 0; i < count; ++i) { + dyc[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb + dyc[i]; + curveTo(xa, ya, xb, yb, xc, yc); + } + clearArg(); + } + + /** + * Appends one or more Bezier curves, as described by the + * dxa...dxc set of arguments, to the current point. For each curve, + * if there are 4 arguments, the curve starts and ends horizontal. + * The first curve need not start horizontal (the odd argument + * case). Note the argument order for the odd argument case. + */ + private void _hhcurveto() { + int count = getArgCount() / 4; + int dy1 = 0; + int[] dxa = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + for (int i = 0; i < count; ++i) { + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + if (getArgCount() == 1) { + dy1 = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + (i == 0 ? dy1 : 0); + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + curveTo(xa, ya, xb, yb, xc, yc); + } + clearArg(); + } + + /** + * Appends one or more Bezier curves to the current point. The + * tangent for the first Bezier must be horizontal, and the second + * must be vertical (except as noted below). + * If there is a multiple of four arguments, the curve starts + * horizontal and ends vertical. Note that the curves alternate + * between start horizontal, end vertical, and start vertical, and + * end horizontal. The last curve (the odd argument case) need not + * end horizontal/vertical. + */ + private void _hvcurveto() { + if (getArgCount() % 8 <= 1) { + int count = getArgCount() / 8; + int[] dxa = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dyc = new int[count]; + int[] dyd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dxf = new int[count]; + int dyf = 0; + if (getArgCount() % 8 == 1) { + dyf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dxf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dyd[count - i - 1] = popArg().intValue(); + dyc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb; + int yc = yb + dyc[i]; + int xd = xc; + int yd = yc + dyd[i]; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf[i]; + int yf = ye + dyf; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + } + } else { + int count = getArgCount() / 8; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dxd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dyf = new int[count]; + int dxf = 0; + if (getArgCount() % 8 == 1) { + dxf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dyf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dxd[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + } + int dy3 = popArg().intValue(); + int dy2 = popArg().intValue(); + int dx2 = popArg().intValue(); + int dx1 = popArg().intValue(); + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + int xd = xc + dxd[i]; + int yd = yc; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf; + int yf = ye + dyf[i]; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + + // What on earth do we do with dx1, dx2, dy2 and dy3? + } + } + clearArg(); + } + + /** + * Is equivalent to one rrcurveto for each set of six arguments + * dxa...dyc, followed by exactly one rlineto using the dxd, dyd + * arguments. The number of curves is determined from the count + * on the argument stack. + */ + private void _rcurveline() { + int count = (getArgCount() - 2) / 6; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dyc = new int[count]; + int dyd = popArg().intValue(); + int dxd = popArg().intValue(); + for (int i = 0; i < count; ++i) { + dyc[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + int xc = 0; + int yc = 0; + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + xc = xb + dxc[i]; + yc = yb + dyc[i]; + curveTo(xa, ya, xb, yb, xc, yc); + } + lineTo(xc + dxd, yc + dyd); + clearArg(); + } + + /** + * Is equivalent to one rlineto for each pair of arguments beyond + * the six arguments dxb...dyd needed for the one rrcurveto + * command. The number of lines is determined from the count of + * items on the argument stack. + */ + private void _rlinecurve() { + int count = (getArgCount() - 6) / 2; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int dyd = popArg().intValue(); + int dxd = popArg().intValue(); + int dyc = popArg().intValue(); + int dxc = popArg().intValue(); + int dyb = popArg().intValue(); + int dxb = popArg().intValue(); + for (int i = 0; i < count; ++i) { + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + int xa = 0; + int ya = 0; + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + xa = lastPoint.x + dxa[i]; + ya = lastPoint.y + dya[i]; + lineTo(xa, ya); + } + int xb = xa + dxb; + int yb = ya + dyb; + int xc = xb + dxc; + int yc = yb + dyc; + int xd = xc + dxd; + int yd = yc + dyd; + curveTo(xb, yb, xc, yc, xd, yd); + clearArg(); + } + + /** + * Appends one or more Bezier curves to the current point, where + * the first tangent is vertical and the second tangent is horizontal. + * This command is the complement of hvcurveto; see the + * description of hvcurveto for more information. + */ + private void _vhcurveto() { + if (getArgCount() % 8 <= 1) { + int count = getArgCount() / 8; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dxd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dyf = new int[count]; + int dxf = 0; + if (getArgCount() % 8 == 1) { + dxf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dyf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dxd[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + int xd = xc + dxd[i]; + int yd = yc; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf; + int yf = ye + dyf[i]; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + } + } else { + int foo = 0; + } + clearArg(); + } + + /** + * Appends one or more curves to the current point. If the argument + * count is a multiple of four, the curve starts and ends vertical. If + * the argument count is odd, the first curve does not begin with a + * vertical tangent. + */ + private void _vvcurveto() { + + clearArg(); + } + + /** + * Causes two Bézier curves, as described by the arguments (as + * shown in Figure 2 below), to be rendered as a straight line when + * the flex depth is less than fd /100 device pixels, and as curved lines + * when the flex depth is greater than or equal to fd/100 device + * pixels. + */ + private void _flex() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments dx1...dx6 to + * be rendered as a straight line when the flex depth is less than + * 0.5 (that is, fd is 50) device pixels, and as curved lines when the + * flex depth is greater than or equal to 0.5 device pixels. + */ + private void _hflex() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments to be + * rendered as a straight line when the flex depth is less than 0.5 + * device pixels, and as curved lines when the flex depth is greater + * than or equal to 0.5 device pixels. + */ + private void _hflex1() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments to be + * rendered as a straight line when the flex depth is less than 0.5 + * device pixels, and as curved lines when the flex depth is greater + * than or equal to 0.5 device pixels. + */ + private void _flex1() { + + clearArg(); + } + + /** + * Finishes a charstring outline definition, and must be the + * last operator in a character’s outline. + */ + private void _endchar() { + endContour(); + clearArg(); + } + + private void _hstem() { + + clearArg(); + } + + private void _vstem() { + + clearArg(); + } + + private void _hstemhm() { + + clearArg(); + } + + private void _vstemhm() { + + clearArg(); + } + + private void _hintmask() { + + clearArg(); + } + + private void _cntrmask() { + + clearArg(); + } + + /** + * Returns the absolute value of num. + */ + private void _abs() { + double num = popArg().doubleValue(); + pushArg(Math.abs(num)); + } + + /** + * Returns the sum of the two numbers num1 and num2. + */ + private void _add() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 + num2); + } + + /** + * Returns the result of subtracting num2 from num1. + */ + private void _sub() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 - num2); + } + + /** + * Returns the quotient of num1 divided by num2. The result is + * undefined if overflow occurs and is zero for underflow. + */ + private void _div() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 / num2); + } + + /** + * Returns the negative of num. + */ + private void _neg() { + double num = popArg().doubleValue(); + pushArg(-num); + } + + /** + * Returns a pseudo random number num2 in the range (0,1], that + * is, greater than zero and less than or equal to one. + */ + private void _random() { + pushArg(1.0 - Math.random()); + } + + /** + * Returns the product of num1 and num2. If overflow occurs, the + * result is undefined, and zero is returned for underflow. + */ + private void _mul() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 * num2); + } + + /** + * Returns the square root of num. If num is negative, the result is + * undefined. + */ + private void _sqrt() { + double num = popArg().doubleValue(); + pushArg(Math.sqrt(num)); + } + + /** + * Removes the top element num from the Type 2 argument stack. + */ + private void _drop() { + popArg(); + } + + /** + * Exchanges the top two elements on the argument stack. + */ + private void _exch() { + Number num2 = popArg(); + Number num1 = popArg(); + pushArg(num2); + pushArg(num1); + } + + /** + * Retrieves the element i from the top of the argument stack and + * pushes a copy of that element onto that stack. If i is negative, + * the top element is copied. If i is greater than X, the operation is + * undefined. + */ + private void _index() { + int i = popArg().intValue(); + Number[] nums = new Number[i]; + for (int j = 0; j < i; ++j) { + nums[j] = popArg(); + } + for (int j = i - 1; j >= 0; --j) { + pushArg(nums[j]); + } + pushArg(nums[i]); + } + + /** + * Performs a circular shift of the elements num(N–1) ... num0 on + * the argument stack by the amount J. Positive J indicates upward + * motion of the stack; negative J indicates downward motion. + * The value N must be a non-negative integer, otherwise the + * operation is undefined. + */ + private void _roll() { + int j = popArg().intValue(); + int n = popArg().intValue(); + Number[] nums = new Number[n]; + for (int i = 0; i < n; ++i) { + nums[i] = popArg(); + } + for (int i = n - 1; i >= 0; --i) { + pushArg(nums[(n + i + j) % n]); + } + } + + /** + * Duplicates the top element on the argument stack. + */ + private void _dup() { + Number any = popArg(); + pushArg(any); + pushArg(any); + } + + /** + * Stores val into the transient array at the location given by i. + */ + private void _put() { + int i = popArg().intValue(); + Number val = popArg(); + _transientArray[i] = val; + } + + /** + * Retrieves the value stored in the transient array at the location + * given by i and pushes the value onto the argument stack. If get + * is executed prior to put for i during execution of the current + * charstring, the value returned is undefined. + */ + private void _get() { + int i = popArg().intValue(); + pushArg(_transientArray[i]); + } + + /** + * Puts a 1 on the stack if num1 and num2 are both non-zero, and + * puts a 0 on the stack if either argument is zero. + */ + private void _and() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) && (num2!=0.0) ? 1 : 0); + } + + /** + * Puts a 1 on the stack if either num1 or num2 are non-zero, and + * puts a 0 on the stack if both arguments are zero. + */ + private void _or() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) || (num2!=0.0) ? 1 : 0); + } + + /** + * Returns a 0 if num1 is non-zero; returns a 1 if num1 is zero. + */ + private void _not() { + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) ? 0 : 1); + } + + /** + * Puts a 1 on the stack if num1 equals num2, otherwise a 0 (zero) + * is put on the stack. + */ + private void _eq() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 == num2 ? 1 : 0); + } + + /** + * Leaves the value s1 on the stack if v1 ? v2, or leaves s2 on the + * stack if v1 > v2. The value of s1 and s2 is usually the biased + * number of a subroutine. + */ + private void _ifelse() { + double v2 = popArg().doubleValue(); + double v1 = popArg().doubleValue(); + Number s2 = popArg(); + Number s1 = popArg(); + pushArg(v1 <= v2 ? s1 : s2); + } + + /** + * Calls a charstring subroutine with index subr# (actually the subr + * number plus the subroutine bias number, as described in section + * 2.3) in the Subrs array. Each element of the Subrs array is a + * charstring encoded like any other charstring. Arguments + * pushed on the Type 2 argument stack prior to calling the + * subroutine, and results pushed on this stack by the subroutine, + * act according to the manner in which the subroutine is coded. + * Calling an undefined subr (gsubr) has undefined results. + */ + private void _callsubr() { + + } + + /** + * Operates in the same manner as callsubr except that it calls a + * global subroutine. + */ + private void _callgsubr() { + + } + + /** + * Returns from either a local or global charstring subroutine, and + * continues execution after the corresponding call(g)subr. + */ + private void _return() { + + } + + public Point[] execute(CharstringType2 cs) { + _points = new ArrayList(); + cs.resetIP(); + while (cs.moreBytes()) { + while (cs.isOperandAtIndex()) { + pushArg(cs.nextOperand()); + } + int operator = cs.nextByte(); + if (operator == 12) { + operator = cs.nextByte(); + + // Two-byte operators + switch (operator) { + case T2Mnemonic.AND: + _and(); + break; + case T2Mnemonic.OR: + _or(); + break; + case T2Mnemonic.NOT: + _not(); + break; + case T2Mnemonic.ABS: + _abs(); + break; + case T2Mnemonic.ADD: + _add(); + break; + case T2Mnemonic.SUB: + _sub(); + break; + case T2Mnemonic.DIV: + _div(); + break; + case T2Mnemonic.NEG: + _neg(); + break; + case T2Mnemonic.EQ: + _eq(); + break; + case T2Mnemonic.DROP: + _drop(); + break; + case T2Mnemonic.PUT: + _put(); + break; + case T2Mnemonic.GET: + _get(); + break; + case T2Mnemonic.IFELSE: + _ifelse(); + break; + case T2Mnemonic.RANDOM: + _random(); + break; + case T2Mnemonic.MUL: + _mul(); + break; + case T2Mnemonic.SQRT: + _sqrt(); + break; + case T2Mnemonic.DUP: + _dup(); + break; + case T2Mnemonic.EXCH: + _exch(); + break; + case T2Mnemonic.INDEX: + _index(); + break; + case T2Mnemonic.ROLL: + _roll(); + break; + case T2Mnemonic.HFLEX: + _hflex(); + break; + case T2Mnemonic.FLEX: + _flex(); + break; + case T2Mnemonic.HFLEX1: + _hflex1(); + break; + case T2Mnemonic.FLEX1: + _flex1(); + break; + default: + //throw new Exception(); + return null; + } + } else { + + // One-byte operators + switch (operator) { + case T2Mnemonic.HSTEM: + _hstem(); + break; + case T2Mnemonic.VSTEM: + _vstem(); + break; + case T2Mnemonic.VMOVETO: + _vmoveto(); + break; + case T2Mnemonic.RLINETO: + _rlineto(); + break; + case T2Mnemonic.HLINETO: + _hlineto(); + break; + case T2Mnemonic.VLINETO: + _vlineto(); + break; + case T2Mnemonic.RRCURVETO: + _rrcurveto(); + break; + case T2Mnemonic.CALLSUBR: + _callsubr(); + break; + case T2Mnemonic.RETURN: + _return(); + break; + case T2Mnemonic.ENDCHAR: + _endchar(); + break; + case T2Mnemonic.HSTEMHM: + _hstemhm(); + break; + case T2Mnemonic.HINTMASK: + _hintmask(); + break; + case T2Mnemonic.CNTRMASK: + _cntrmask(); + break; + case T2Mnemonic.RMOVETO: + _rmoveto(); + break; + case T2Mnemonic.HMOVETO: + _hmoveto(); + break; + case T2Mnemonic.VSTEMHM: + _vstemhm(); + break; + case T2Mnemonic.RCURVELINE: + _rcurveline(); + break; + case T2Mnemonic.RLINECURVE: + _rlinecurve(); + break; + case T2Mnemonic.VVCURVETO: + _vvcurveto(); + break; + case T2Mnemonic.HHCURVETO: + _hhcurveto(); + break; + case T2Mnemonic.CALLGSUBR: + _callgsubr(); + break; + case T2Mnemonic.VHCURVETO: + _vhcurveto(); + break; + case T2Mnemonic.HVCURVETO: + _hvcurveto(); + break; + default: + //throw new Exception(); + return null; + } + } + } + Point[] pointArray = new Point[_points.size()]; + _points.toArray(pointArray); + return pointArray; + } + + /** + * The number of arguments on the argument stack + */ + private int getArgCount() { + return _argStackIndex; + } + + /** + * Pop a value off the argument stack + */ + private Number popArg() { + return _argStack[--_argStackIndex]; + } + + /** + * Push a value on to the argument stack + */ + private void pushArg(Number n) { + _argStack[_argStackIndex++] = n; + } + + /** + * Pop a value off the subroutine stack + */ + private int popSubr() { + return _subrStack[--_subrStackIndex]; + } + + /** + * Push a value on to the subroutine stack + */ + private void pushSubr(int n) { + _subrStack[_subrStackIndex++] = n; + } + + /** + * Clear the argument stack + */ + private void clearArg() { + _argStackIndex = 0; + } + + private Point getLastPoint() { + int size = _points.size(); + if (size > 0) { + return _points.get(size - 1); + } else { + return new Point(0, 0, true, false); + } + } + + private void moveTo(int x, int y) { + endContour(); + _points.add(new Point(x, y, true, false)); + } + + private void lineTo(int x, int y) { + _points.add(new Point(x, y, true, false)); + } + + private void curveTo(int cx1, int cy1, int cx2, int cy2, int x, int y) { + _points.add(new Point(cx1, cy1, false, false)); + _points.add(new Point(cx2, cy2, false, false)); + _points.add(new Point(x, y, true, false)); + } + + private void endContour() { + Point lastPoint = getLastPoint(); + if (lastPoint != null) { + lastPoint.endOfContour = true; + } + } +} diff --git a/src/net/java/dev/typecast/t2/T2Mnemonic.java b/src/net/java/dev/typecast/t2/T2Mnemonic.java new file mode 100644 index 000000000..810aea159 --- /dev/null +++ b/src/net/java/dev/typecast/t2/T2Mnemonic.java @@ -0,0 +1,86 @@ +/* + * $Id: T2Mnemonic.java,v 1.1 2007-02-21 12:30:48 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * 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 net.java.dev.typecast.t2; + +/** + * The Mnemonic representations of the Type 2 charstring instruction set. + * @author David Schweinsberg + * @version $Id: T2Mnemonic.java,v 1.1 2007-02-21 12:30:48 davidsch Exp $ + */ +public class T2Mnemonic { + + /** + * One byte operators + */ + public static final short HSTEM = 0x01; + public static final short VSTEM = 0x03; + public static final short VMOVETO = 0x04; + public static final short RLINETO = 0x05; + public static final short HLINETO = 0x06; + public static final short VLINETO = 0x07; + public static final short RRCURVETO = 0x08; + public static final short CALLSUBR = 0x0a; + public static final short RETURN = 0x0b; + public static final short ESCAPE = 0x0c; + public static final short ENDCHAR = 0x0e; + public static final short HSTEMHM = 0x12; + public static final short HINTMASK = 0x13; + public static final short CNTRMASK = 0x14; + public static final short RMOVETO = 0x15; + public static final short HMOVETO = 0x16; + public static final short VSTEMHM = 0x17; + public static final short RCURVELINE = 0x18; + public static final short RLINECURVE = 0x19; + public static final short VVCURVETO = 0x1a; + public static final short HHCURVETO = 0x1b; + public static final short CALLGSUBR = 0x1d; + public static final short VHCURVETO = 0x1e; + public static final short HVCURVETO = 0x1f; + + /** + * Two byte operators + */ + public static final short DOTSECTION = 0x00; + public static final short AND = 0x03; + public static final short OR = 0x04; + public static final short NOT = 0x05; + public static final short ABS = 0x09; + public static final short ADD = 0x0a; + public static final short SUB = 0x0b; + public static final short DIV = 0x0c; + public static final short NEG = 0x0e; + public static final short EQ = 0x0f; + public static final short DROP = 0x12; + public static final short PUT = 0x14; + public static final short GET = 0x15; + public static final short IFELSE = 0x16; + public static final short RANDOM = 0x17; + public static final short MUL = 0x18; + public static final short SQRT = 0x1a; + public static final short DUP = 0x1b; + public static final short EXCH = 0x1c; + public static final short INDEX = 0x1d; + public static final short ROLL = 0x1e; + public static final short HFLEX = 0x22; + public static final short FLEX = 0x23; + public static final short HFLEX1 = 0x24; + public static final short FLEX1 = 0x25; +} diff --git a/src/net/java/dev/typecast/tt/engine/GraphicsState.java b/src/net/java/dev/typecast/tt/engine/GraphicsState.java new file mode 100644 index 000000000..1c36bd3de --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/GraphicsState.java @@ -0,0 +1,50 @@ +/* + * $Id: GraphicsState.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.tt.engine; + +/** + * Maintains the graphics state whilst interpreting hinting instructions. + * @author David Schweinsberg + * @version $Id: GraphicsState.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + */ +class GraphicsState { + + public boolean auto_flip = true; + public int control_value_cut_in = 0; + public int delta_base = 9; + public int delta_shift = 3; + public int dual_projection_vectors; + public int[] freedom_vector = new int[2]; + public int zp0 = 1; + public int zp1 = 1; + public int zp2 = 1; + public int instruction_control = 0; + public int loop = 1; + public int minimum_distance = 1; + public int[] projection_vector = new int[2]; + public int round_state = 1; + public int rp0 = 0; + public int rp1 = 0; + public int rp2 = 0; + public int scan_control = 0; + public int single_width_cut_in = 0; + public int single_width_value = 0; +} diff --git a/src/net/java/dev/typecast/tt/engine/Interpreter.java b/src/net/java/dev/typecast/tt/engine/Interpreter.java new file mode 100644 index 000000000..6f436d764 --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/Interpreter.java @@ -0,0 +1,1357 @@ +/* + * $Id: Interpreter.java,v 1.1.1.1 2004-12-05 23:15:05 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.tt.engine; + +import net.java.dev.typecast.ot.Mnemonic; +import net.java.dev.typecast.ot.Point; + +/** + * The interpreter shall remain ignorant of the table structure - the table + * data will be extracted by supporting classes, whether it be the Parser + * or some other. + * @author David Schweinsberg + * @version $Id: Interpreter.java,v 1.1.1.1 2004-12-05 23:15:05 davidsch Exp $ + */ +public class Interpreter { + + private Parser parser = null; + private GraphicsState gs = new GraphicsState(); + private Point[][] zone = new Point[2][]; + private int[] stack = null; + private int[] store = null; + private int[] cvt = new int[256]; + private int[] functionMap = null; + private int stackIndex = 0; + private boolean inFuncDef = false; + + public Interpreter(int stackMax, int storeMax, int funcMax) { + zone[0] = new Point[256]; + zone[1] = new Point[256]; + stack = new int[stackMax]; + store = new int[storeMax]; + functionMap = new int[funcMax]; + } + + /** + * ABSolute value + */ + private void _abs() { + int n = pop(); + if (n >= 0) { + push(n); + } else { + push(-n); + } + } + + /** + * ADD + */ + private void _add() { + int n1 = pop(); + int n2 = pop(); + push(n2 + n1); + } + + private void _alignpts() { + pop(); + pop(); + } + + /** + * + * + * USES: loop + */ + private void _alignrp() { + while (gs.loop-- > 0) { + pop(); + } + gs.loop = 1; + } + + /** + * logical AND + */ + private void _and() { + int e2 = pop(); + int e1 = pop(); + push(((e1 != 0) && (e2 != 0)) ? 1 : 0); + } + + /** + * CALL function + */ + private void _call() { + execute(functionMap[pop()]); + } + + /** + * CEILING + */ + private void _ceiling() { + int n = pop(); + if (n >= 0) { + push((n & 0xffc0) + (((n & 0x3f) != 0) ? 0x40 : 0)); + } else { + push(n & 0xffc0); + } + } + + /** + * Copy the INDEXed element to the top of the stack + */ + private void _cindex() { + push(stack[stackIndex - pop()]); + } + + /** + * CLEAR the entire stack + */ + private void _clear() { + stackIndex = 0; + } + + private void _debug() { + pop(); + } + + /** + * DELTA exception C1 + */ + private void _deltac1() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception C2 + */ + private void _deltac2() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception C3 + */ + private void _deltac3() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P1 + */ + private void _deltap1() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P2 + */ + private void _deltap2() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P3 + */ + private void _deltap3() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * Returns the DEPTH of the stack + */ + private void _depth() { + push(stackIndex); + } + + /** + * DIVide + */ + private void _div() { + int n1 = pop(); + int n2 = pop(); + push((n2 / n1) >> 6); + } + + /** + * DUPlicate top stack element + */ + private void _dup() { + int n = pop(); + push(n); + push(n); + } + + /** + * ELSE + */ + private int _else(int instructionIndex) { + return parser.handleElse(instructionIndex); + } + + /** + * EQual + */ + private void _eq() { + int e2 = pop(); + int e1 = pop(); + push((e1 == e2) ? 1 : 0); + } + + private void _even() { + pop(); + push(0); + } + + /** + * Function DEFinition + */ + private void _fdef(int instructionIndex) { + functionMap[pop()] = instructionIndex; + inFuncDef = true; + } + + /** + * Set the auto_FLIP boolean to OFF + */ + private void _flipoff() { + gs.auto_flip = false; + } + + /** + * Set the auto_FLIP boolean to ON + */ + private void _flipon() { + gs.auto_flip = true; + } + + /** + * FLIP PoinT + * + * USES: loop + */ + private void _flippt() { + while(gs.loop-- > 0) { + int index = pop(); + zone[gs.zp0][index].onCurve = !zone[gs.zp0][index].onCurve; + } + gs.loop = 1; + } + + /** + * FLIP RanGe OFF + */ + private void _fliprgoff() { + int end = pop(); + int start = pop(); + for (int i = start; i <= end; i++) { + zone[1][i].onCurve = false; + } + } + + /** + * FLIP RanGe ON + */ + private void _fliprgon() { + int end = pop(); + int start = pop(); + for (int i = start; i <= end; i++) { + zone[1][i].onCurve = true; + } + } + + /** + * FLOOR + */ + private void _floor() { + int n = pop(); + if (n >= 0) { + push(n & 0xffc0); + } else { + push((n & 0xffc0) - (((n & 0x3f) != 0) ? 0x40 : 0)); + } + } + + private void _gc(short param) { + pop(); + push(0); + } + + private void _getinfo() { + pop(); + push(0); + } + + /** + * Get Freedom_Vector + */ + private void _gfv() { + push(gs.freedom_vector[0]); + push(gs.freedom_vector[1]); + } + + /** + * Get Projection_Vector + */ + private void _gpv() { + push(gs.projection_vector[0]); + push(gs.projection_vector[1]); + } + + /** + * Greater Than + */ + private void _gt() { + int e2 = pop(); + int e1 = pop(); + push((e1 > e2) ? 1 : 0); + } + + /** + * Greater Than or EQual + */ + private void _gteq() { + int e2 = pop(); + int e1 = pop(); + push((e1 >= e2) ? 1 : 0); + } + + /** + * Instruction DEFinition + */ + private void _idef() { + pop(); + inFuncDef = true; + } + + /** + * IF test + */ + private int _if(int instructionIndex) { + return parser.handleIf(pop() != 0, instructionIndex); + } + + /** + * INSTruction Execution ConTRol + * + * INSTCTRL[] + * + * Code Range + * 0x8E + * + * Pops + * s: selector flag (int32) + * value: USHORT (padded to 32 bits) used to set value of instruction_control. + * + * Pushes + * - + * + * Sets + * instruction_control + * + * Sets the instruction control state variable making it possible to turn on or off + * the execution of instructions and to regulate use of parameters set in the CVT + * program. INSTCTRL[ ] can only be executed in the CVT program. + * + * This instruction clears and sets various control flags in the rasterizer. The + * selector flag determines valid values for the value argument. The value determines + * the new setting of the raterizer control flag. In version 1.0 there are only two + * flags in use: + * + * Selector flag 1 is used to inhibit grid-fitting. If s=1, valid values for the + * value argument are 0 (FALSE) and 1 (TRUE). If the value argument is set to TRUE + * (v=1), any instructions associated with glyphs will not be executed. For example, + * to inhibit grid-fitting when a glyph is being rotated or stretched, use the + * following sequence on the preprogram: + * + * PUSHB[000] 6 ; ask GETINFO to check for stretching or rotation + * GETINFO[] ; will push TRUE if glyph is stretched or rotated + * IF[] ; tests value at top of stack + * PUSHB[000] 1 ; value for INSTCTRL + * PUSHB[000] 1 ; selector for INSTCTRL + * INSTRCTRL[] ; based on selector and value will turn grid-fitting off + * EIF[] + * + * Selector flag 2 is used to establish that any parameters set in the CVT program + * should be ignored when instructions associated with glyphs are executed. These + * include, for example, the values for scantype and the CVT cut-in. If s=1, valid + * values for the value argument are 0 (FALSE) and 2 (TRUE). If the value argument is + * set to TRUE (v=2), the default values of those parameters will be used regardless + * of any changes that may have been made in those values by the preprogram. If the + * value argument is set to FALSE (v=0), parameter values changed by the CVT program + * will be used in glyph instructions. + */ + private void _instctrl() { + int s = pop(); + int v = pop(); + if (s == 1) { + gs.instruction_control |= v; + } else if (s == 2) { + gs.instruction_control |= v; + } + } + + private void _ip() { + pop(); + } + + private void _isect() { + pop(); + pop(); + pop(); + pop(); + pop(); + } + + private void _iup(short param) { + } + + /** + * JuMP Relative + */ + private int _jmpr(int instructionIndex) { + return instructionIndex += pop() - 1; + } + + /** + * Jump Relative On False + */ + private int _jrof(int instructionIndex) { + boolean test = pop() != 0; + int offset = pop(); + if (!test) { + instructionIndex += offset - 1; + } + return instructionIndex; + } + + /** + * Jump Relative On True + */ + private int _jrot(int instructionIndex) { + boolean test = pop() != 0; + int offset = pop(); + if (test) { + instructionIndex += offset - 1; + } + return instructionIndex; + } + + /** + * LOOP and CALL function + */ + private void _loopcall() { + int index = pop(); + int count = pop(); + for (int i = 0; i < count; i++) { + execute(functionMap[i]); + } + } + + /** + * Less Than + */ + private void _lt() { + int e2 = pop(); + int e1 = pop(); + push((e1 < e2) ? 1 : 0); + } + + /** + * Less Than or EQual + */ + private void _lteq() { + int e2 = pop(); + int e1 = pop(); + push((e1 <= e2) ? 1 : 0); + } + + /** + * MAXimum of top two stack elements + */ + private void _max() { + int n1 = pop(); + int n2 = pop(); + push((n1 > n2) ? n1 : n2); + } + + private void _md(short param) { + pop(); + pop(); + push(0); + } + + private void _mdap(short param) { + pop(); + } + + private void _mdrp(short param) { + pop(); + } + + private void _miap(short param) { + pop(); + pop(); + } + /** + * MINimum of top two stack elements + */ + private void _min() { + int n1 = pop(); + int n2 = pop(); + push((n1 < n2) ? n1 : n2); + } + + /** + * Move the INDEXed element to the top of the stack + */ + private void _mindex() { + // Move the indexed element to stackIndex, and shift the others down + int k = pop(); + int e = stack[stackIndex - k]; + for (int i = stackIndex - k; i < stackIndex - 1; i++) { + stack[i] = stack[i+1]; + } + stack[stackIndex - 1] = e; + } + + private void _mirp(short param) { + pop(); + pop(); + } + + private void _mppem() { + push(0); + } + + private void _mps() { + push(0); + } + + private void _msirp(short param) { + pop(); + pop(); + } + + /** + * MULtiply + */ + private void _mul() { + int n1 = pop(); + int n2 = pop(); + push((n1 * n2) >> 6); + } + + /** + * NEGate + */ + private void _neg() { + push(-pop()); + } + + /** + * Not EQual + */ + private void _neq() { + int e2 = pop(); + int e1 = pop(); + push((e1 != e2) ? 1 : 0); + } + + /** + * logical NOT + */ + private void _not() { + push((pop() != 0) ? 0 : 1); + } + + private void _nround(short param) { + pop(); + push(0); + } + + private void _odd() { + pop(); + push(0); + } + + /** + * logical OR + */ + private void _or() { + int e2 = pop(); + int e1 = pop(); + push(((e1 != 0) || (e2 != 0)) ? 1 : 0); + } + + /** + * PUSH N Bytes + * PUSH N Words + * PUSH Bytes + * PUSH Words + */ + private void _push(int[] data) { + for (int j = 0; j < data.length; j++) { + push(data[j]); + } + } + + /** + * Read Control Value Table + */ + private void _rcvt() { + push(cvt[pop()]); + } + + /** + * Round Down To Grid + */ + private void _rdtg() { + gs.round_state = 3; + } + + /** + * Round OFF + */ + private void _roff() { + gs.round_state = 5; + } + + /** + * ROLL the top three stack elements + */ + private void _roll() { + int a = pop(); + int b = pop(); + int c = pop(); + push(b); + push(a); + push(c); + } + + private void _round(short param) { + pop(); + push(0); + } + + /** + * Read Store + */ + private void _rs() { + push(store[pop()]); + } + + /** + * Round To Double Grid + */ + private void _rtdg() { + gs.round_state = 2; + } + + /** + * Round To Grid + */ + private void _rtg() { + gs.round_state = 1; + } + + /** + * Round To Half Grid + */ + private void _rthg() { + gs.round_state = 0; + } + + /** + * Round Up To Grid + */ + private void _rutg() { + gs.round_state = 4; + } + + private void _s45round() { + pop(); + } + + /** + * SCAN conversion ConTRoL + * + * SCANCTRL[ ] + * + * Code Range + * 0x85 + * + * Pops + * n: flags indicating when to turn on dropout control mode (16 bit word padded + * to 32 bits) + * + * Pushes + * - + * + * Sets + * scan_control + * + * SCANCTRL is used to set the value of the Graphics State variable scan_control + * which in turn determines whether the scan converter will activate dropout + * control for this glyph. Use of the dropout control mode is determined by three + * conditions: + * + * Is the glyph rotated? + * + * Is the glyph stretched? + * + * Is the current setting for ppem less than a specified threshold? + * + * The interpreter pops a word from the stack and looks at the lower 16 bits. + * + * Bits 0-7 represent the threshold value for ppem. A value of FF in bits 0-7 + * means invoke dropout_control for all sizes. A value of 0 in bits 0-7 means + * never invoke dropout_control. + * + * Bits 8-13 are used to turn on dropout_control in cases where the specified + * conditions are met. Bits 8, 9 and 10 are used to turn on the dropout_control + * mode (assuming other conditions do not block it). Bits 11, 12, and 13 are + * used to turn off the dropout mode unless other conditions force it. Bits 14 + * and 15 are reserved for future use. + * + * Bit Meaning if set + * --- -------------- + * 8 Set dropout_control to TRUE if other conditions do not block and ppem + * is less than or equal to the threshold value. + * + * 9 Set dropout_control to TRUE if other conditions do not block and the + * glyph is rotated. + * + * 10 Set dropout_control to TRUE if other conditions do not block and the + * glyph is stretched. + * + * 11 Set dropout_control to FALSE unless ppem is less than or equal to the + * threshold value. + * + * 12 Set dropout_control to FALSE unless the glyph is rotated. + * + * 13 Set dropout_control to FALSE unless the glyph is stretched. + * + * 14 Reserved for future use. + * + * 15 Reserved for future use. + * + * For example + * 0x0000 No dropout control is invoked + * 0x01FF Always do dropout control + * 0x0A10 Do dropout control if the glyph is rotated and has less than 16 + * pixels per-em + * + * The scan converter can operate in either a "normal" mode or in a "fix dropout" + * mode depending on the value of a set of enabling and disabling flags. + */ + private void _scanctrl() { + gs.scan_control = pop(); + } + + /** + * SCANTYPE + * + * SCANTYPE[] + * + * Code Range + * 0x8D + * + * Pops + * n: 16 bit integer + * + * Pushes + * - + * + * Sets + * scan_control + * + * Pops a 16-bit integer whose value is used to determine which rules the scan + * converter will use. If the value of the argument is 0, the fast scan converter + * will be used. If the value of the integer is 1 or 2, simple dropout control will + * be used. If the value of the integer is 4 or 5, smart dropout control will be + * used. More specifically, + * + * if n=0 rules 1, 2, and 3 are invoked (simple dropout control scan conversion + * including stubs) + * + * if n=1 rules 1, 2, and 4 are invoked (simple dropout control scan conversion + * excluding stubs) + * + * if n=2 rules 1 and 2 only are invoked (fast scan conversion; dropout control + * turned off) + * + * if n=3 same as n = 2 + * + * if n = 4 rules 1, 2, and 5 are invoked (smart dropout control scan conversion + * including stubs) + * + * if n = 5 rules 1, 2, and 6 are invoked (smart dropout control scan conversion + * excluding stubs) + * + * if n = 6 same as n = 2 + * + * if n = 7 same as n = 2 + * + * The scan conversion rules are shown here: + * + * Rule 1 + * If a pixel's center falls within the glyph outline, that pixel is turned on. + * + * Rule 2 + * If a contour falls exactly on a pixel's center, that pixel is turned on. + * + * Rule 3 + * If a scan line between two adjacent pixel centers (either vertical or + * horizontal) is intersected by both an on-Transition contour and an off-Transition + * contour and neither of the pixels was already turned on by rules 1 and 2, turn on + * the left-most pixel (horizontal scan line) or the bottom-most pixel (vertical scan + * line). This is "Simple" dropout control. + * + * Rule 4 + * Apply Rule 3 only if the two contours continue to intersect other scan lines in + * both directions. That is, do not turn on pixels for 'stubs.' The scanline segments + * that form a square with the intersected scan line segment are examined to verify + * that they are intersected by two contours. It is possible that these could be + * different contours than the ones intersecting the dropout scan line segment. This + * is very unlikely but may have to be controlled with grid-fitting in some exotic + * glyphs. + * + * Rule 5 + * If a scan line between two adjacent pixel centers (either vertical or horizontal) + * is intersected by both an on-Transition contour and an off-Transition contour and + * neither of the pixels was already turned on by rules 1 and 2, turn on the pixel + * which is closer to the midpoint between the on-Transition contour and off- + * Transition contour. This is "Smart" dropout control. + * + * Rule 6 + * Apply Rule 5 only if the two contours continue to intersect other scan lines in + * both directions. That is, do not turn on pixels for 'stubs.' + * + * New fonts wishing to use the new modes of the ScanType instruction, but still + * wishing to work correctly on old rasterizers that don't recognize the new modes + * should: + * + * First execute a ScanType instruction using an old mode which will give the best + * approximation to the desired new mode (e.g. Simple Stubs for Smart Stubs), and + * then + * + * Immediately execute another ScanType instruction with the desired new mode. + */ + private void _scantype() { + pop(); + } + + private void _scfs() { + pop(); + pop(); + } + + /** + * Set Control Value Table Cut In + */ + private void _scvtci() { + gs.control_value_cut_in = pop(); + } + + /** + * Set Delta_Base in the graphics state + */ + private void _sdb() { + gs.delta_base = pop(); + } + + /** + * Set Dual Projection_Vector To Line + */ + private void _sdpvtl(short param) { + pop(); + pop(); + } + + /** + * Set Delta_Shift in the graphics state + */ + private void _sds() { + gs.delta_shift = pop(); + } + + /** + * Set Freedom_Vector From Stack + */ + private void _sfvfs() { + gs.freedom_vector[1] = pop(); // y + gs.freedom_vector[0] = pop(); // x + } + + /* + * Set Freedom_Vector to Coordinate Axis + */ + private void _sfvtca(short param) { + if (param == 1) { + gs.freedom_vector[0] = 0x4000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x4000; + } + } + + /* + * Set Freedom_Vector To Line + */ + private void _sfvtl(short param) { + pop(); + pop(); + if (param == 1) { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x0000; + } + } + + /** + * Set Freedom_Vector To Projection Vector + */ + private void _sfvtpv() { + gs.freedom_vector[0] = gs.projection_vector[0]; + gs.freedom_vector[1] = gs.projection_vector[1]; + } + + private void _shc(short param) { + pop(); + } + + /** + * SHift Point by the last point + * + * USES: loop + */ + private void _shp(short param) { + while(gs.loop-- > 0) { + pop(); + if(param == 0) { + } else { + } + } + gs.loop = 1; + } + + /** + * SHift Point by a PIXel amount + * + * USES: loop + */ + private void _shpix() { + pop(); // amount + while (gs.loop-- > 0) { + pop(); // p + } + gs.loop = 1; + } + + private void _shz(short param) { + pop(); + } + + /** + * Set LOOP variable + */ + private void _sloop() { + gs.loop = pop(); + } + + /** + * Set Minimum_Distance + */ + private void _smd() { + gs.minimum_distance = pop(); + } + + /** + * Set Projection_Vector From Stack + */ + private void _spvfs() { + gs.projection_vector[1] = pop(); // y + gs.projection_vector[0] = pop(); // x + } + + /* + * Set Projection_Vector To Coordinate Axis + */ + private void _spvtca(short param) { + if (param == 1) { + gs.projection_vector[0] = 0x4000; + gs.projection_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x4000; + } + } + + /** + * Set Projection_Vector To Line + */ + private void _spvtl(short param) { + + // We'll get a copy of the line and normalize it - + // divide the x- and y-coords by the vector's dot product. + Point p1 = zone[gs.zp2][pop()]; + Point p2 = zone[gs.zp1][pop()]; + int x = p2.x - p1.x; + int y = p2.y - p1.y; + if(param == 1) { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x0000; + } + } + + private void _sround() { + pop(); + } + + /** + * Set Reference Point 0 + */ + private void _srp0() { + gs.rp0 = pop(); + } + + /** + * Set Reference Point 1 + */ + private void _srp1() { + gs.rp1 = pop(); + } + + /** + * Set Reference Point 2 + */ + private void _srp2() { + gs.rp2 = pop(); + } + + /** + * Set Single-Width + */ + private void _ssw() { + gs.single_width_value = pop(); + } + + /** + * Set Single_Width_Cut_In + */ + private void _sswci() { + gs.single_width_cut_in = pop(); + } + + /** + * SUBtract + */ + private void _sub() { + int n1 = pop(); + int n2 = pop(); + push(n2 - n1); + } + + /** + * Set freedom and projection Vectors To Coordinate Axis + */ + private void _svtca(short param) { + if (param == 1) { + gs.projection_vector[0] = 0x4000; + gs.projection_vector[1] = 0x0000; + gs.freedom_vector[0] = 0x4000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x4000; + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x4000; + } + } + + /** + * SWAP the top two elements on the stack + */ + private void _swap() { + int n1 = pop(); + int n2 = pop(); + push(n1); + push(n2); + } + + /** + * Set Zone Pointer 0 + */ + private void _szp0() { + gs.zp0 = pop(); + } + + /** + * Set Zone Pointer 1 + */ + private void _szp1() { + gs.zp1 = pop(); + } + + /** + * Set Zone Pointer 2 + */ + private void _szp2() { + gs.zp2 = pop(); + } + + /** + * Set Zone PointerS + */ + private void _szps() { + gs.zp0 = gs.zp1 = gs.zp2 = pop(); + } + + private void _utp() { + pop(); + } + + /** + * Write Control Value Table in FUnits + */ + private void _wcvtf() { + int value = pop(); + // Conversion of value goes here + cvt[pop()] = value; + } + + /** + * Write Control Value Table in Pixel units + */ + private void _wcvtp() { + int value = pop(); + // Conversion of value goes here + cvt[pop()] = value; + } + + /** + * Write Store + */ + private void _ws() { + store[pop()] = pop(); + } + + public void execute(int ip) { + while (ip < ((ip & 0xffff0000) | parser.getISLength(ip >> 16))) { + short opcode = parser.getOpcode(ip); + if (inFuncDef) { + + // We're within a function definition, so don't execute the code + if (opcode == Mnemonic.ENDF) { + inFuncDef = false; + } + ip = parser.advanceIP(ip); + continue; + } + if (opcode >= Mnemonic.MIRP) _mirp((short)(opcode & 31)); + else if (opcode >= Mnemonic.MDRP) _mdrp((short)(opcode & 31)); + else if (opcode >= Mnemonic.PUSHW) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.PUSHB) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.INSTCTRL) _instctrl(); + else if (opcode >= Mnemonic.SCANTYPE) _scantype(); + else if (opcode >= Mnemonic.MIN) _min(); + else if (opcode >= Mnemonic.MAX) _max(); + else if (opcode >= Mnemonic.ROLL) _roll(); + else if (opcode >= Mnemonic.IDEF) _idef(); + else if (opcode >= Mnemonic.GETINFO) _getinfo(); + else if (opcode >= Mnemonic.SDPVTL) _sdpvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SCANCTRL) _scanctrl(); + else if (opcode >= Mnemonic.FLIPRGOFF) _fliprgoff(); + else if (opcode >= Mnemonic.FLIPRGON) _fliprgon(); + else if (opcode >= Mnemonic.FLIPPT) _flippt(); + else if (opcode >= Mnemonic.AA); // AA (ignored) + else if (opcode >= Mnemonic.SANGW); // SANGW (ignored) + else if (opcode >= Mnemonic.RDTG) _rdtg(); + else if (opcode >= Mnemonic.RUTG) _rutg(); + else if (opcode >= Mnemonic.ROFF) _roff(); + else if (opcode >= Mnemonic.JROF) ip = _jrof(ip); + else if (opcode >= Mnemonic.JROT) ip = _jrot(ip); + else if (opcode >= Mnemonic.S45ROUND) _s45round(); + else if (opcode >= Mnemonic.SROUND) _sround(); + else if (opcode >= Mnemonic.DELTAC3) _deltac3(); + else if (opcode >= Mnemonic.DELTAC2) _deltac2(); + else if (opcode >= Mnemonic.DELTAC1) _deltac1(); + else if (opcode >= Mnemonic.DELTAP3) _deltap3(); + else if (opcode >= Mnemonic.DELTAP2) _deltap2(); + else if (opcode >= Mnemonic.WCVTF) _wcvtf(); + else if (opcode >= Mnemonic.NROUND) _nround((short)(opcode & 3)); + else if (opcode >= Mnemonic.ROUND) _round((short)(opcode & 3)); + else if (opcode >= Mnemonic.CEILING) _ceiling(); + else if (opcode >= Mnemonic.FLOOR) _floor(); + else if (opcode >= Mnemonic.NEG) _neg(); + else if (opcode >= Mnemonic.ABS) _abs(); + else if (opcode >= Mnemonic.MUL) _mul(); + else if (opcode >= Mnemonic.DIV) _div(); + else if (opcode >= Mnemonic.SUB) _sub(); + else if (opcode >= Mnemonic.ADD) _add(); + else if (opcode >= Mnemonic.SDS) _sds(); + else if (opcode >= Mnemonic.SDB) _sdb(); + else if (opcode >= Mnemonic.DELTAP1) _deltap1(); + else if (opcode >= Mnemonic.NOT) _not(); + else if (opcode >= Mnemonic.OR) _or(); + else if (opcode >= Mnemonic.AND) _and(); + else if (opcode >= Mnemonic.EIF); // EIF + else if (opcode >= Mnemonic.IF) ip = _if(ip); + else if (opcode >= Mnemonic.EVEN) _even(); + else if (opcode >= Mnemonic.ODD) _odd(); + else if (opcode >= Mnemonic.NEQ) _neq(); + else if (opcode >= Mnemonic.EQ) _eq(); + else if (opcode >= Mnemonic.GTEQ) _gteq(); + else if (opcode >= Mnemonic.GT) _gt(); + else if (opcode >= Mnemonic.LTEQ) _lteq(); + else if (opcode >= Mnemonic.LT) _lt(); + else if (opcode >= Mnemonic.DEBUG) _debug(); + else if (opcode >= Mnemonic.FLIPOFF) _flipoff(); + else if (opcode >= Mnemonic.FLIPON) _flipon(); + else if (opcode >= Mnemonic.MPS) _mps(); + else if (opcode >= Mnemonic.MPPEM) _mppem(); + else if (opcode >= Mnemonic.MD) _md((short)(opcode & 1)); + else if (opcode >= Mnemonic.SCFS) _scfs(); + else if (opcode >= Mnemonic.GC) _gc((short)(opcode & 1)); + else if (opcode >= Mnemonic.RCVT) _rcvt(); + else if (opcode >= Mnemonic.WCVTP) _wcvtp(); + else if (opcode >= Mnemonic.RS) _rs(); + else if (opcode >= Mnemonic.WS) _ws(); + else if (opcode >= Mnemonic.NPUSHW) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.NPUSHB) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.MIAP) _miap((short)(opcode & 1)); + else if (opcode >= Mnemonic.RTDG) _rtdg(); + else if (opcode >= Mnemonic.ALIGNRP) _alignrp(); + else if (opcode >= Mnemonic.IP) _ip(); + else if (opcode >= Mnemonic.MSIRP) _msirp((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHPIX) _shpix(); + else if (opcode >= Mnemonic.SHZ) _shz((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHC) _shc((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHP) _shp((short)(opcode & 1)); + else if (opcode >= Mnemonic.IUP) _iup((short)(opcode & 1)); + else if (opcode >= Mnemonic.MDAP) _mdap((short)(opcode & 1)); + else if (opcode >= Mnemonic.ENDF) return; + else if (opcode >= Mnemonic.FDEF) _fdef(ip + 1); + else if (opcode >= Mnemonic.CALL) _call(); + else if (opcode >= Mnemonic.LOOPCALL) _loopcall(); + else if (opcode >= Mnemonic.UTP) _utp(); + else if (opcode >= Mnemonic.ALIGNPTS) _alignpts(); + else if (opcode >= Mnemonic.MINDEX) _mindex(); + else if (opcode >= Mnemonic.CINDEX) _cindex(); + else if (opcode >= Mnemonic.DEPTH) _depth(); + else if (opcode >= Mnemonic.SWAP) _swap(); + else if (opcode >= Mnemonic.CLEAR) _clear(); + else if (opcode >= Mnemonic.POP) pop(); + else if (opcode >= Mnemonic.DUP) _dup(); + else if (opcode >= Mnemonic.SSW) _ssw(); + else if (opcode >= Mnemonic.SSWCI) _sswci(); + else if (opcode >= Mnemonic.SCVTCI) _scvtci(); + else if (opcode >= Mnemonic.JMPR) ip = _jmpr(ip); + else if (opcode >= Mnemonic.ELSE) ip = _else(ip); + else if (opcode >= Mnemonic.SMD) _smd(); + else if (opcode >= Mnemonic.RTHG) _rthg(); + else if (opcode >= Mnemonic.RTG) _rtg(); + else if (opcode >= Mnemonic.SLOOP) _sloop(); + else if (opcode >= Mnemonic.SZPS) _szps(); + else if (opcode >= Mnemonic.SZP2) _szp2(); + else if (opcode >= Mnemonic.SZP1) _szp1(); + else if (opcode >= Mnemonic.SZP0) _szp0(); + else if (opcode >= Mnemonic.SRP2) _srp2(); + else if (opcode >= Mnemonic.SRP1) _srp1(); + else if (opcode >= Mnemonic.SRP0) _srp0(); + else if (opcode >= Mnemonic.ISECT) _isect(); + else if (opcode >= Mnemonic.SFVTPV) _sfvtpv(); + else if (opcode >= Mnemonic.GFV) _gfv(); + else if (opcode >= Mnemonic.GPV) _gpv(); + else if (opcode >= Mnemonic.SFVFS) _sfvfs(); + else if (opcode >= Mnemonic.SPVFS) _spvfs(); + else if (opcode >= Mnemonic.SFVTL) _sfvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SPVTL) _spvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SFVTCA) _sfvtca((short)(opcode & 1)); + else if (opcode >= Mnemonic.SPVTCA) _spvtca((short)(opcode & 1)); + else if (opcode >= Mnemonic.SVTCA) _svtca((short)(opcode & 1)); + ip = parser.advanceIP(ip); + } + } + + public Point[][] getZones() { + return zone; + } + + private int pop() { + return stack[--stackIndex]; + } + + private void push(int i) { + stack[stackIndex++] = i; + } + + public void runCvtProgram() { + execute(0x00010000); + } + + public void runFontProgram() { + execute(0); + } + + public void runGlyphProgram() { + // instruction_control can be set to stop glyphs grid-fitting + if ((gs.instruction_control & 1) == 0) { + execute(0x00020000); + } + } + + public void setParser(Parser p) { + parser = p; + } +} diff --git a/src/net/java/dev/typecast/tt/engine/Parser.java b/src/net/java/dev/typecast/tt/engine/Parser.java new file mode 100644 index 000000000..bfae53197 --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/Parser.java @@ -0,0 +1,192 @@ +/* + * $Id: Parser.java,v 1.1.1.1 2004-12-05 23:15:06 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * 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 net.java.dev.typecast.tt.engine; + +import net.java.dev.typecast.ot.Mnemonic; + +/** + * @author David Schweinsberg + * @version $Id: Parser.java,v 1.1.1.1 2004-12-05 23:15:06 davidsch Exp $ + */ +public class Parser { + + private short[][] instructions = new short[3][]; + + /** + * Advance the instruction pointer to the next executable opcode. + * This will be the next byte, unless the current opcode is a push + * instruction, in which case it will be the byte immediately beyond + * the last data byte. + * @param ip The current instruction pointer + * @return The new instruction pointer + */ + public int advanceIP(int ip) { + + // The high word specifies font, cvt, or glyph program + int prog = ip >> 16; + int i = ip & 0xffff; + int dataCount; + ip++; + if (Mnemonic.NPUSHB == instructions[prog][i]) { + // Next byte is the data byte count + dataCount = instructions[prog][++i]; + ip += dataCount + 1; + } else if (Mnemonic.NPUSHW == instructions[prog][i]) { + // Next byte is the data word count + dataCount = instructions[prog][++i]; + ip += dataCount*2 + 1; + } else if (Mnemonic.PUSHB == (instructions[prog][i] & 0xf8)) { + dataCount = (short)((instructions[prog][i] & 0x07) + 1); + ip += dataCount; + } else if (Mnemonic.PUSHW == (instructions[prog][i] & 0xf8)) { + dataCount = (short)((instructions[prog][i] & 0x07) + 1); + ip += dataCount*2; + } + return ip; + } + + public int getISLength(int prog) { + return instructions[prog].length; + } + + public short getOpcode(int ip) { + return instructions[ip >> 16][ip & 0xffff]; + } + + public short getPushCount(int ip) { + short instr = instructions[ip >> 16][ip & 0xffff]; + if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) { + return instructions[ip >> 16][(ip & 0xffff) + 1]; + } else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) { + return (short)((instr & 0x07) + 1); + } + return 0; + } + + public int[] getPushData(int ip) { + int count = getPushCount(ip); + int[] data = new int[count]; + int prog = ip >> 16; + int i = ip & 0xffff; + short instr = instructions[prog][i]; + if (Mnemonic.NPUSHB == instr) { + for (int j = 0; j < count; j++) { + data[j] = instructions[prog][i + j + 2]; + } + } else if (Mnemonic.PUSHB == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = instructions[prog][i + j + 1]; + } + } else if (Mnemonic.NPUSHW == instr) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[prog][i + j*2 + 2] << 8) | instructions[prog][i + j*2 + 3]; + } + } else if (Mnemonic.PUSHW == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[prog][i + j*2 + 1] << 8) | instructions[prog][i + j*2 + 2]; + } + } + return data; + } + + public int handleElse(int ip) { + while (instructions[ip >> 16][ip & 0xffff] != Mnemonic.EIF) { + ip = advanceIP(ip); + } + return ip; + } + + public int handleIf(boolean test, int ip) { + if (test == false) { + // The TrueType spec says that we merely jump to the *next* ELSE or EIF + // instruction in the instruction stream. So therefore no nesting! + // Looking at actual code, IF-ELSE-EIF can be nested! + while ((instructions[ip >> 16][ip & 0xffff] != Mnemonic.ELSE) + && (instructions[ip >> 16][ip & 0xffff] != Mnemonic.EIF)) { + ip = advanceIP(ip); + } + } + return ip; + } + + /** + * This program is run everytime we scale the font + */ + public void setCvtProgram(short[] program) { + instructions[1] = program; + } + + /** + * This program is only run once + */ + public void setFontProgram(short[] program) { + instructions[0] = program; + } + + /** + * This program is run everytime we scale the glyph + */ + public void setGlyphProgram(short[] program) { + instructions[2] = program; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + int ip = 0; + while (ip < instructions[0].length) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if (getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for(int j = 0; j < data.length; j++) + sb.append(" ").append(data[j]); + } + sb.append("\n"); + ip = advanceIP(ip); + } + sb.append("\n"); + ip = 0x10000; + while (ip < (0x10000 | instructions[1].length)) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if(getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for (int j = 0; j < data.length; j++) { + sb.append(" ").append(data[j]); + } + } + sb.append("\n"); + ip = advanceIP(ip); + } + sb.append("\n"); + ip = 0x20000; + while (ip < (0x20000 | instructions[2].length)) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if (getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for (int j = 0; j < data.length; j++) { + sb.append(" ").append(data[j]); + } + } + sb.append("\n"); + ip = advanceIP(ip); + } + return sb.toString(); + } +} -- cgit v1.2.3 From 5b627f588b1bb0e4cef57ffe1f9cd5efdf0f9e42 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 02:37:14 +0100 Subject: Minor changes, OTGlyph: remove redundant/errorneous add-on points (origin, advanced). --- src/net/java/dev/typecast/ot/Glyph.java | 159 ---------------------------- src/net/java/dev/typecast/ot/OTFont.java | 23 ++-- src/net/java/dev/typecast/ot/OTGlyph.java | 168 ++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 166 deletions(-) delete mode 100644 src/net/java/dev/typecast/ot/Glyph.java create mode 100644 src/net/java/dev/typecast/ot/OTGlyph.java diff --git a/src/net/java/dev/typecast/ot/Glyph.java b/src/net/java/dev/typecast/ot/Glyph.java deleted file mode 100644 index a59d62684..000000000 --- a/src/net/java/dev/typecast/ot/Glyph.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - - ============================================================================ - The Apache Software License, Version 1.1 - ============================================================================ - - Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. - - Redistribution and use in source and binary forms, with or without modifica- - tion, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - 3. The end-user documentation included with the redistribution, if any, must - include the following acknowledgment: "This product includes software - developed by the Apache Software Foundation (http://www.apache.org/)." - Alternately, this acknowledgment may appear in the software itself, if - and wherever such third-party acknowledgments normally appear. - - 4. The names "Batik" and "Apache Software Foundation" must not be - used to endorse or promote products derived from this software without - prior written permission. For written permission, please contact - apache@apache.org. - - 5. Products derived from this software may not be called "Apache", nor may - "Apache" appear in their name, without prior written permission of the - Apache Software Foundation. - - THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- - DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This software consists of voluntary contributions made by many individuals - on behalf of the Apache Software Foundation. For more information on the - Apache Software Foundation, please see . - -*/ - -package net.java.dev.typecast.ot; - -import net.java.dev.typecast.ot.table.GlyphDescription; -import net.java.dev.typecast.ot.table.GlyfDescript; -import net.java.dev.typecast.ot.table.Charstring; -import net.java.dev.typecast.ot.table.CharstringType2; - -import net.java.dev.typecast.t2.T2Interpreter; - -/** - * An individual glyph within a font. - * @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $ - * @author David Schweinsberg - */ -public class Glyph { - - protected short _leftSideBearing; - protected int _advanceWidth; - private Point[] _points; - - /** - * Construct a Glyph from a TrueType outline described by - * a GlyphDescription. - * @param cs The Charstring describing the glyph. - * @param lsb The Left Side Bearing. - * @param advance The advance width. - */ - public Glyph(GlyphDescription gd, short lsb, int advance) { - _leftSideBearing = lsb; - _advanceWidth = advance; - describe(gd); - } - - /** - * Construct a Glyph from a PostScript outline described by a Charstring. - * @param cs The Charstring describing the glyph. - * @param lsb The Left Side Bearing. - * @param advance The advance width. - */ - public Glyph(Charstring cs, short lsb, int advance) { - _leftSideBearing = lsb; - _advanceWidth = advance; - if (cs instanceof CharstringType2) { - T2Interpreter t2i = new T2Interpreter(); - _points = t2i.execute((CharstringType2) cs); - } else { - //throw unsupported charstring type - } - } - - public int getAdvanceWidth() { - return _advanceWidth; - } - - public short getLeftSideBearing() { - return _leftSideBearing; - } - - public Point getPoint(int i) { - return _points[i]; - } - - public int getPointCount() { - return _points.length; - } - - /** - * Resets the glyph to the TrueType table settings - */ - public void reset() { - } - - /** - * @param factor a 16.16 fixed value - */ - public void scale(int factor) { - for (int i = 0; i < _points.length; i++) { - //points[i].x = ( points[i].x * factor ) >> 6; - //points[i].y = ( points[i].y * factor ) >> 6; - _points[i].x = ((_points[i].x<<10) * factor) >> 26; - _points[i].y = ((_points[i].y<<10) * factor) >> 26; - } - _leftSideBearing = (short)(( _leftSideBearing * factor) >> 6); - _advanceWidth = (_advanceWidth * factor) >> 6; - } - - /** - * Set the points of a glyph from the GlyphDescription - */ - private void describe(GlyphDescription gd) { - int endPtIndex = 0; - _points = new Point[gd.getPointCount() + 2]; - for (int i = 0; i < gd.getPointCount(); i++) { - boolean endPt = gd.getEndPtOfContours(endPtIndex) == i; - if (endPt) { - endPtIndex++; - } - _points[i] = new Point( - gd.getXCoordinate(i), - gd.getYCoordinate(i), - (gd.getFlags(i) & GlyfDescript.onCurve) != 0, - endPt); - } - - // Append the origin and advanceWidth points (n & n+1) - _points[gd.getPointCount()] = new Point(0, 0, true, true); - _points[gd.getPointCount()+1] = new Point(_advanceWidth, 0, true, true); - } -} diff --git a/src/net/java/dev/typecast/ot/OTFont.java b/src/net/java/dev/typecast/ot/OTFont.java index d23228483..e58fc3794 100644 --- a/src/net/java/dev/typecast/ot/OTFont.java +++ b/src/net/java/dev/typecast/ot/OTFont.java @@ -54,7 +54,8 @@ import java.io.DataInputStream; import java.io.IOException; import net.java.dev.typecast.ot.table.DirectoryEntry; -import net.java.dev.typecast.ot.table.TTCHeader; +import net.java.dev.typecast.ot.table.GlyfDescript; +import net.java.dev.typecast.ot.table.HdmxTable; import net.java.dev.typecast.ot.table.TableDirectory; import net.java.dev.typecast.ot.table.Table; import net.java.dev.typecast.ot.table.Os2Table; @@ -73,7 +74,7 @@ import net.java.dev.typecast.ot.table.TableFactory; /** * The TrueType font. * @version $Id: OTFont.java,v 1.6 2007-01-31 01:49:18 davidsch Exp $ - * @author David Schweinsberg + * @author David Schweinsberg, Sven Gothel */ public class OTFont { @@ -85,6 +86,7 @@ public class OTFont { private GlyfTable _glyf; private HeadTable _head; private HheaTable _hhea; + private HdmxTable _hdmx; private HmtxTable _hmtx; private LocaTable _loca; private MaxpTable _maxp; @@ -124,6 +126,10 @@ public class OTFont { return _hhea; } + public HdmxTable getHdmxTable() { + return _hdmx; + } + public HmtxTable getHmtxTable() { return _hmtx; } @@ -160,15 +166,17 @@ public class OTFont { return _maxp.getNumGlyphs(); } - public Glyph getGlyph(int i) { - return (_glyf.getDescription(i) != null) - ? new Glyph( - _glyf.getDescription(i), + public OTGlyph getGlyph(int i) { + + final GlyfDescript _glyfDescr = _glyf.getDescription(i); + return (null != _glyfDescr) + ? new OTGlyph( + _glyfDescr, _hmtx.getLeftSideBearing(i), _hmtx.getAdvanceWidth(i)) : null; } - + public TableDirectory getTableDirectory() { return _tableDirectory; } @@ -245,6 +253,7 @@ public class OTFont { // Get references to commonly used tables (these happen to be all the // required tables) _cmap = (CmapTable) getTable(Table.cmap); + _hdmx = (HdmxTable) getTable(Table.hdmx); _hmtx = (HmtxTable) getTable(Table.hmtx); _name = (NameTable) getTable(Table.name); _os2 = (Os2Table) getTable(Table.OS_2); diff --git a/src/net/java/dev/typecast/ot/OTGlyph.java b/src/net/java/dev/typecast/ot/OTGlyph.java new file mode 100644 index 000000000..958dd2280 --- /dev/null +++ b/src/net/java/dev/typecast/ot/OTGlyph.java @@ -0,0 +1,168 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Batik" and "Apache Software Foundation" must not be + used to endorse or promote products derived from this software without + prior written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation. For more information on the + Apache Software Foundation, please see . + +*/ + +package net.java.dev.typecast.ot; + +import com.jogamp.graph.geom.AABBox; + +import net.java.dev.typecast.ot.table.GlyphDescription; +import net.java.dev.typecast.ot.table.GlyfDescript; +import net.java.dev.typecast.ot.table.Charstring; +import net.java.dev.typecast.ot.table.CharstringType2; + +import net.java.dev.typecast.t2.T2Interpreter; + +/** + * An individual glyph within a font. + * @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $ + * @author David Schweinsberg, Sven Gothel + */ +public class OTGlyph { + + protected short _leftSideBearing; + protected int _advanceWidth; + private Point[] _points; + AABBox _bbox; + + /** + * Construct a Glyph from a TrueType outline described by + * a GlyphDescription. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public OTGlyph(GlyphDescription gd, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + describe(gd); + } + + /** + * Construct a Glyph from a PostScript outline described by a Charstring. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public OTGlyph(Charstring cs, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + if (cs instanceof CharstringType2) { + T2Interpreter t2i = new T2Interpreter(); + _points = t2i.execute((CharstringType2) cs); + } else { + //throw unsupported charstring type + } + } + + public AABBox getBBox() { + return _bbox; + } + + public int getAdvanceWidth() { + return _advanceWidth; + } + + public short getLeftSideBearing() { + return _leftSideBearing; + } + + public Point getPoint(int i) { + return _points[i]; + } + + public int getPointCount() { + return _points.length; + } + + /** + * Resets the glyph to the TrueType table settings + */ + public void reset() { + } + + /** + * @param factor a 16.16 fixed value + */ + public void scale(int factor) { + for (int i = 0; i < _points.length; i++) { + //points[i].x = ( points[i].x * factor ) >> 6; + //points[i].y = ( points[i].y * factor ) >> 6; + _points[i].x = ((_points[i].x<<10) * factor) >> 26; + _points[i].y = ((_points[i].y<<10) * factor) >> 26; + } + _leftSideBearing = (short)(( _leftSideBearing * factor) >> 6); + _advanceWidth = (_advanceWidth * factor) >> 6; + } + + /** + * Set the points of a glyph from the GlyphDescription + */ + private void describe(GlyphDescription gd) { + int endPtIndex = 0; + _points = new Point[gd.getPointCount() /* + 2 */ ]; + for (int i = 0; i < gd.getPointCount(); i++) { + boolean endPt = gd.getEndPtOfContours(endPtIndex) == i; + if (endPt) { + endPtIndex++; + } + _points[i] = new Point( + gd.getXCoordinate(i), + gd.getYCoordinate(i), + (gd.getFlags(i) & GlyfDescript.onCurve) != 0, + endPt); + } + + // Append the origin and advanceWidth points (n & n+1) + // _points[gd.getPointCount()] = new Point(0, 0, true, true); + // _points[gd.getPointCount()+1] = new Point(_advanceWidth, 0, true, true); + + _bbox = new AABBox(gd.getXMinimum(), gd.getYMinimum(), 0, gd.getXMaximum(), gd.getYMaximum(), 0); + } +} -- cgit v1.2.3 From 89d1a2d2ecb414d62f44cbb2e3b9bd75746943cf Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 03:30:21 +0100 Subject: Imported part of Harmony's awt.geom impl. 6.0-r991881, http://harmony.apache.org/ - Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 --- .../jogamp/graph/geom/plane/AffineTransform.java | 637 +++++++++++++++ src/com/jogamp/graph/geom/plane/GeneralPath.java | 433 ++++++++++ .../geom/plane/IllegalPathStateException.java | 34 + .../plane/NoninvertibleTransformException.java | 31 + src/com/jogamp/graph/geom/plane/PathIterator.java | 44 + src/jogamp/graph/math/plane/Crossing.java | 895 +++++++++++++++++++++ src/org/apache/harmony/misc/HashCode.java | 203 +++++ 7 files changed, 2277 insertions(+) create mode 100644 src/com/jogamp/graph/geom/plane/AffineTransform.java create mode 100644 src/com/jogamp/graph/geom/plane/GeneralPath.java create mode 100644 src/com/jogamp/graph/geom/plane/IllegalPathStateException.java create mode 100644 src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java create mode 100644 src/com/jogamp/graph/geom/plane/PathIterator.java create mode 100644 src/jogamp/graph/math/plane/Crossing.java create mode 100644 src/org/apache/harmony/misc/HashCode.java diff --git a/src/com/jogamp/graph/geom/plane/AffineTransform.java b/src/com/jogamp/graph/geom/plane/AffineTransform.java new file mode 100644 index 000000000..065ad94b2 --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/AffineTransform.java @@ -0,0 +1,637 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package java.awt.geom; + +import java.awt.Shape; +import java.io.IOException; +import java.io.Serializable; + +import org.apache.harmony.awt.internal.nls.Messages; +import org.apache.harmony.misc.HashCode; + +public class AffineTransform implements Cloneable, Serializable { + + private static final long serialVersionUID = 1330973210523860834L; + + public static final int TYPE_IDENTITY = 0; + public static final int TYPE_TRANSLATION = 1; + public static final int TYPE_UNIFORM_SCALE = 2; + public static final int TYPE_GENERAL_SCALE = 4; + public static final int TYPE_QUADRANT_ROTATION = 8; + public static final int TYPE_GENERAL_ROTATION = 16; + public static final int TYPE_GENERAL_TRANSFORM = 32; + public static final int TYPE_FLIP = 64; + public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; + public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION; + + /** + * The TYPE_UNKNOWN is an initial type value + */ + static final int TYPE_UNKNOWN = -1; + + /** + * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. + */ + static final double ZERO = 1E-10; + + /** + * The values of transformation matrix + */ + double m00; + double m10; + double m01; + double m11; + double m02; + double m12; + + /** + * The transformation type + */ + transient int type; + + public AffineTransform() { + type = TYPE_IDENTITY; + m00 = m11 = 1.0; + m10 = m01 = m02 = m12 = 0.0; + } + + public AffineTransform(AffineTransform t) { + this.type = t.type; + this.m00 = t.m00; + this.m10 = t.m10; + this.m01 = t.m01; + this.m11 = t.m11; + this.m02 = t.m02; + this.m12 = t.m12; + } + + public AffineTransform(float m00, float m10, float m01, float m11, float m02, float m12) { + this.type = TYPE_UNKNOWN; + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + } + + public AffineTransform(double m00, double m10, double m01, double m11, double m02, double m12) { + this.type = TYPE_UNKNOWN; + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + } + + public AffineTransform(float[] matrix) { + this.type = TYPE_UNKNOWN; + m00 = matrix[0]; + m10 = matrix[1]; + m01 = matrix[2]; + m11 = matrix[3]; + if (matrix.length > 4) { + m02 = matrix[4]; + m12 = matrix[5]; + } + } + + public AffineTransform(double[] matrix) { + this.type = TYPE_UNKNOWN; + m00 = matrix[0]; + m10 = matrix[1]; + m01 = matrix[2]; + m11 = matrix[3]; + if (matrix.length > 4) { + m02 = matrix[4]; + m12 = matrix[5]; + } + } + + /* + * Method returns type of affine transformation. + * + * Transform matrix is + * m00 m01 m02 + * m10 m11 m12 + * + * According analytic geometry new basis vectors are (m00, m01) and (m10, m11), + * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1). + * Type transformations classification: + * TYPE_IDENTITY - new basis equals original one and zero translation + * TYPE_TRANSLATION - translation vector isn't zero + * TYPE_UNIFORM_SCALE - vectors length of new basis equals + * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal + * TYPE_FLIP - new basis vector orientation differ from original one + * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees + * TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle + * TYPE_GENERAL_TRANSFORM - transformation can't be inversed + */ + public int getType() { + if (type != TYPE_UNKNOWN) { + return type; + } + + int type = 0; + + if (m00 * m01 + m10 * m11 != 0.0) { + type |= TYPE_GENERAL_TRANSFORM; + return type; + } + + if (m02 != 0.0 || m12 != 0.0) { + type |= TYPE_TRANSLATION; + } else + if (m00 == 1.0 && m11 == 1.0 && m01 == 0.0 && m10 == 0.0) { + type = TYPE_IDENTITY; + return type; + } + + if (m00 * m11 - m01 * m10 < 0.0) { + type |= TYPE_FLIP; + } + + double dx = m00 * m00 + m10 * m10; + double dy = m01 * m01 + m11 * m11; + if (dx != dy) { + type |= TYPE_GENERAL_SCALE; + } else + if (dx != 1.0) { + type |= TYPE_UNIFORM_SCALE; + } + + if ((m00 == 0.0 && m11 == 0.0) || + (m10 == 0.0 && m01 == 0.0 && (m00 < 0.0 || m11 < 0.0))) + { + type |= TYPE_QUADRANT_ROTATION; + } else + if (m01 != 0.0 || m10 != 0.0) { + type |= TYPE_GENERAL_ROTATION; + } + + return type; + } + + public double getScaleX() { + return m00; + } + + public double getScaleY() { + return m11; + } + + public double getShearX() { + return m01; + } + + public double getShearY() { + return m10; + } + + public double getTranslateX() { + return m02; + } + + public double getTranslateY() { + return m12; + } + + public boolean isIdentity() { + return getType() == TYPE_IDENTITY; + } + + public void getMatrix(double[] matrix) { + matrix[0] = m00; + matrix[1] = m10; + matrix[2] = m01; + matrix[3] = m11; + if (matrix.length > 4) { + matrix[4] = m02; + matrix[5] = m12; + } + } + + public double getDeterminant() { + return m00 * m11 - m01 * m10; + } + + public void setTransform(double m00, double m10, double m01, double m11, double m02, double m12) { + this.type = TYPE_UNKNOWN; + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + } + + public void setTransform(AffineTransform t) { + type = t.type; + setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12); + } + + public void setToIdentity() { + type = TYPE_IDENTITY; + m00 = m11 = 1.0; + m10 = m01 = m02 = m12 = 0.0; + } + + public void setToTranslation(double mx, double my) { + m00 = m11 = 1.0; + m01 = m10 = 0.0; + m02 = mx; + m12 = my; + if (mx == 0.0 && my == 0.0) { + type = TYPE_IDENTITY; + } else { + type = TYPE_TRANSLATION; + } + } + + public void setToScale(double scx, double scy) { + m00 = scx; + m11 = scy; + m10 = m01 = m02 = m12 = 0.0; + if (scx != 1.0 || scy != 1.0) { + type = TYPE_UNKNOWN; + } else { + type = TYPE_IDENTITY; + } + } + + public void setToShear(double shx, double shy) { + m00 = m11 = 1.0; + m02 = m12 = 0.0; + m01 = shx; + m10 = shy; + if (shx != 0.0 || shy != 0.0) { + type = TYPE_UNKNOWN; + } else { + type = TYPE_IDENTITY; + } + } + + public void setToRotation(double angle) { + double sin = Math.sin(angle); + double cos = Math.cos(angle); + if (Math.abs(cos) < ZERO) { + cos = 0.0; + sin = sin > 0.0 ? 1.0 : -1.0; + } else + if (Math.abs(sin) < ZERO) { + sin = 0.0; + cos = cos > 0.0 ? 1.0 : -1.0; + } + m00 = m11 = cos; + m01 = -sin; + m10 = sin; + m02 = m12 = 0.0; + type = TYPE_UNKNOWN; + } + + public void setToRotation(double angle, double px, double py) { + setToRotation(angle); + m02 = px * (1.0 - m00) + py * m10; + m12 = py * (1.0 - m00) - px * m10; + type = TYPE_UNKNOWN; + } + + public static AffineTransform getTranslateInstance(double mx, double my) { + AffineTransform t = new AffineTransform(); + t.setToTranslation(mx, my); + return t; + } + + public static AffineTransform getScaleInstance(double scx, double scY) { + AffineTransform t = new AffineTransform(); + t.setToScale(scx, scY); + return t; + } + + public static AffineTransform getShearInstance(double shx, double shy) { + AffineTransform m = new AffineTransform(); + m.setToShear(shx, shy); + return m; + } + + public static AffineTransform getRotateInstance(double angle) { + AffineTransform t = new AffineTransform(); + t.setToRotation(angle); + return t; + } + + public static AffineTransform getRotateInstance(double angle, double x, double y) { + AffineTransform t = new AffineTransform(); + t.setToRotation(angle, x, y); + return t; + } + + public void translate(double mx, double my) { + concatenate(AffineTransform.getTranslateInstance(mx, my)); + } + + public void scale(double scx, double scy) { + concatenate(AffineTransform.getScaleInstance(scx, scy)); + } + + public void shear(double shx, double shy) { + concatenate(AffineTransform.getShearInstance(shx, shy)); + } + + public void rotate(double angle) { + concatenate(AffineTransform.getRotateInstance(angle)); + } + + public void rotate(double angle, double px, double py) { + concatenate(AffineTransform.getRotateInstance(angle, px, py)); + } + + /** + * Multiply matrix of two AffineTransform objects + * @param t1 - the AffineTransform object is a multiplicand + * @param t2 - the AffineTransform object is a multiplier + * @return an AffineTransform object that is a result of t1 multiplied by matrix t2. + */ + AffineTransform multiply(AffineTransform t1, AffineTransform t2) { + return new AffineTransform( + t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00 + t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01 + t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10 + t1.m01 * t2.m10 + t1.m11 * t2.m11, // m11 + t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02 + t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12 + } + + public void concatenate(AffineTransform t) { + setTransform(multiply(t, this)); + } + + public void preConcatenate(AffineTransform t) { + setTransform(multiply(this, t)); + } + + public AffineTransform createInverse() throws NoninvertibleTransformException { + double det = getDeterminant(); + if (Math.abs(det) < ZERO) { + // awt.204=Determinant is zero + throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + } + return new AffineTransform( + m11 / det, // m00 + -m10 / det, // m10 + -m01 / det, // m01 + m00 / det, // m11 + (m01 * m12 - m11 * m02) / det, // m02 + (m10 * m02 - m00 * m12) / det // m12 + ); + } + + public Point2D transform(Point2D src, Point2D dst) { + if (dst == null) { + if (src instanceof Point2D.Double) { + dst = new Point2D.Double(); + } else { + dst = new Point2D.Float(); + } + } + + double x = src.getX(); + double y = src.getY(); + + dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + return dst; + } + + public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int length) { + while (--length >= 0) { + Point2D srcPoint = src[srcOff++]; + double x = srcPoint.getX(); + double y = srcPoint.getY(); + Point2D dstPoint = dst[dstOff]; + if (dstPoint == null) { + if (srcPoint instanceof Point2D.Double) { + dstPoint = new Point2D.Double(); + } else { + dstPoint = new Point2D.Float(); + } + } + dstPoint.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dst[dstOff++] = dstPoint; + } + } + + public void transform(double[] src, int srcOff, double[] dst, int dstOff, int length) { + int step = 2; + if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { + srcOff = srcOff + length * 2 - 2; + dstOff = dstOff + length * 2 - 2; + step = -2; + } + while (--length >= 0) { + double x = src[srcOff + 0]; + double y = src[srcOff + 1]; + dst[dstOff + 0] = x * m00 + y * m01 + m02; + dst[dstOff + 1] = x * m10 + y * m11 + m12; + srcOff += step; + dstOff += step; + } + } + + public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) { + int step = 2; + if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { + srcOff = srcOff + length * 2 - 2; + dstOff = dstOff + length * 2 - 2; + step = -2; + } + while (--length >= 0) { + float x = src[srcOff + 0]; + float y = src[srcOff + 1]; + dst[dstOff + 0] = (float)(x * m00 + y * m01 + m02); + dst[dstOff + 1] = (float)(x * m10 + y * m11 + m12); + srcOff += step; + dstOff += step; + } + } + + public void transform(float[] src, int srcOff, double[] dst, int dstOff, int length) { + while (--length >= 0) { + float x = src[srcOff++]; + float y = src[srcOff++]; + dst[dstOff++] = x * m00 + y * m01 + m02; + dst[dstOff++] = x * m10 + y * m11 + m12; + } + } + + public void transform(double[] src, int srcOff, float[] dst, int dstOff, int length) { + while (--length >= 0) { + double x = src[srcOff++]; + double y = src[srcOff++]; + dst[dstOff++] = (float)(x * m00 + y * m01 + m02); + dst[dstOff++] = (float)(x * m10 + y * m11 + m12); + } + } + + public Point2D deltaTransform(Point2D src, Point2D dst) { + if (dst == null) { + if (src instanceof Point2D.Double) { + dst = new Point2D.Double(); + } else { + dst = new Point2D.Float(); + } + } + + double x = src.getX(); + double y = src.getY(); + + dst.setLocation(x * m00 + y * m01, x * m10 + y * m11); + return dst; + } + + public void deltaTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) { + while (--length >= 0) { + double x = src[srcOff++]; + double y = src[srcOff++]; + dst[dstOff++] = x * m00 + y * m01; + dst[dstOff++] = x * m10 + y * m11; + } + } + + public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException { + double det = getDeterminant(); + if (Math.abs(det) < ZERO) { + // awt.204=Determinant is zero + throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + } + + if (dst == null) { + if (src instanceof Point2D.Double) { + dst = new Point2D.Double(); + } else { + dst = new Point2D.Float(); + } + } + + double x = src.getX() - m02; + double y = src.getY() - m12; + + dst.setLocation((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); + return dst; + } + + public void inverseTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) + throws NoninvertibleTransformException + { + double det = getDeterminant(); + if (Math.abs(det) < ZERO) { + // awt.204=Determinant is zero + throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + } + + while (--length >= 0) { + double x = src[srcOff++] - m02; + double y = src[srcOff++] - m12; + dst[dstOff++] = (x * m11 - y * m01) / det; + dst[dstOff++] = (y * m00 - x * m10) / det; + } + } + + public Shape createTransformedShape(Shape src) { + if (src == null) { + return null; + } + if (src instanceof GeneralPath) { + return ((GeneralPath)src).createTransformedShape(this); + } + PathIterator path = src.getPathIterator(this); + GeneralPath dst = new GeneralPath(path.getWindingRule()); + dst.append(path, false); + return dst; + } + + @Override + public String toString() { + return + getClass().getName() + + "[[" + m00 + ", " + m01 + ", " + m02 + "], [" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + m10 + ", " + m11 + ", " + m12 + "]]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + @Override + public int hashCode() { + HashCode hash = new HashCode(); + hash.append(m00); + hash.append(m01); + hash.append(m02); + hash.append(m10); + hash.append(m11); + hash.append(m12); + return hash.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof AffineTransform) { + AffineTransform t = (AffineTransform)obj; + return + m00 == t.m00 && m01 == t.m01 && + m02 == t.m02 && m10 == t.m10 && + m11 == t.m11 && m12 == t.m12; + } + return false; + } + + + /** + * Write AffineTrasform object to the output steam. + * @param stream - the output stream + * @throws IOException - if there are I/O errors while writing to the output strem + */ + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + } + + + /** + * Read AffineTransform object from the input stream + * @param stream - the input steam + * @throws IOException - if there are I/O errors while reading from the input strem + * @throws ClassNotFoundException - if class could not be found + */ + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + type = TYPE_UNKNOWN; + } + +} + diff --git a/src/com/jogamp/graph/geom/plane/GeneralPath.java b/src/com/jogamp/graph/geom/plane/GeneralPath.java new file mode 100644 index 000000000..6d6282ef1 --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/GeneralPath.java @@ -0,0 +1,433 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package java.awt.geom; + +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.NoSuchElementException; + +import org.apache.harmony.awt.gl.Crossing; +import org.apache.harmony.awt.internal.nls.Messages; + +public final class GeneralPath implements Shape, Cloneable { + + public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; + public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; + + /** + * The buffers size + */ + private static final int BUFFER_SIZE = 10; + + /** + * The buffers capacity + */ + private static final int BUFFER_CAPACITY = 10; + + /** + * The point's types buffer + */ + byte[] types; + + /** + * The points buffer + */ + float[] points; + + /** + * The point's type buffer size + */ + int typeSize; + + /** + * The points buffer size + */ + int pointSize; + + /** + * The path rule + */ + int rule; + + /** + * The space amount in points buffer for different segmenet's types + */ + static int pointShift[] = { + 2, // MOVETO + 2, // LINETO + 4, // QUADTO + 6, // CUBICTO + 0}; // CLOSE + + /* + * GeneralPath path iterator + */ + class Iterator implements PathIterator { + + /** + * The current cursor position in types buffer + */ + int typeIndex; + + /** + * The current cursor position in points buffer + */ + int pointIndex; + + /** + * The source GeneralPath object + */ + GeneralPath p; + + /** + * The path iterator transformation + */ + AffineTransform t; + + /** + * Constructs a new GeneralPath.Iterator for given general path + * @param path - the source GeneralPath object + */ + Iterator(GeneralPath path) { + this(path, null); + } + + /** + * Constructs a new GeneralPath.Iterator for given general path and transformation + * @param path - the source GeneralPath object + * @param at - the AffineTransform object to apply rectangle path + */ + Iterator(GeneralPath path, AffineTransform at) { + this.p = path; + this.t = at; + } + + public int getWindingRule() { + return p.getWindingRule(); + } + + public boolean isDone() { + return typeIndex >= p.typeSize; + } + + public void next() { + typeIndex++; + } + + public int currentSegment(double[] coords) { + if (isDone()) { + // awt.4B=Iterator out of bounds + throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ + } + int type = p.types[typeIndex]; + int count = GeneralPath.pointShift[type]; + for (int i = 0; i < count; i++) { + coords[i] = p.points[pointIndex + i]; + } + if (t != null) { + t.transform(coords, 0, coords, 0, count / 2); + } + pointIndex += count; + return type; + } + + public int currentSegment(float[] coords) { + if (isDone()) { + // awt.4B=Iterator out of bounds + throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ + } + int type = p.types[typeIndex]; + int count = GeneralPath.pointShift[type]; + System.arraycopy(p.points, pointIndex, coords, 0, count); + if (t != null) { + t.transform(coords, 0, coords, 0, count / 2); + } + pointIndex += count; + return type; + } + + } + + public GeneralPath() { + this(WIND_NON_ZERO, BUFFER_SIZE); + } + + public GeneralPath(int rule) { + this(rule, BUFFER_SIZE); + } + + public GeneralPath(int rule, int initialCapacity) { + setWindingRule(rule); + types = new byte[initialCapacity]; + points = new float[initialCapacity * 2]; + } + + public GeneralPath(Shape shape) { + this(WIND_NON_ZERO, BUFFER_SIZE); + PathIterator p = shape.getPathIterator(null); + setWindingRule(p.getWindingRule()); + append(p, false); + } + + public void setWindingRule(int rule) { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { + // awt.209=Invalid winding rule value + throw new java.lang.IllegalArgumentException(Messages.getString("awt.209")); //$NON-NLS-1$ + } + this.rule = rule; + } + + public int getWindingRule() { + return rule; + } + + /** + * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. + * @param pointCount - the point count to be added in buffer + */ + void checkBuf(int pointCount, boolean checkMove) { + if (checkMove && typeSize == 0) { + // awt.20A=First segment should be SEG_MOVETO type + throw new IllegalPathStateException(Messages.getString("awt.20A")); //$NON-NLS-1$ + } + if (typeSize == types.length) { + byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; + System.arraycopy(types, 0, tmp, 0, typeSize); + types = tmp; + } + if (pointSize + pointCount > points.length) { + float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; + System.arraycopy(points, 0, tmp, 0, pointSize); + points = tmp; + } + } + + public void moveTo(float x, float y) { + if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { + points[pointSize - 2] = x; + points[pointSize - 1] = y; + } else { + checkBuf(2, false); + types[typeSize++] = PathIterator.SEG_MOVETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + } + + public void lineTo(float x, float y) { + checkBuf(2, true); + types[typeSize++] = PathIterator.SEG_LINETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + + public void quadTo(float x1, float y1, float x2, float y2) { + checkBuf(4, true); + types[typeSize++] = PathIterator.SEG_QUADTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + } + + public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { + checkBuf(6, true); + types[typeSize++] = PathIterator.SEG_CUBICTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + points[pointSize++] = x3; + points[pointSize++] = y3; + } + + public void closePath() { + if (typeSize == 0 || types[typeSize - 1] != PathIterator.SEG_CLOSE) { + checkBuf(0, true); + types[typeSize++] = PathIterator.SEG_CLOSE; + } + } + + public void append(Shape shape, boolean connect) { + PathIterator p = shape.getPathIterator(null); + append(p, connect); + } + + public void append(PathIterator path, boolean connect) { + while (!path.isDone()) { + float coords[] = new float[6]; + switch (path.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (!connect || typeSize == 0) { + moveTo(coords[0], coords[1]); + break; + } + if (types[typeSize - 1] != PathIterator.SEG_CLOSE && + points[pointSize - 2] == coords[0] && + points[pointSize - 1] == coords[1]) + { + break; + } + // NO BREAK; + case PathIterator.SEG_LINETO: + lineTo(coords[0], coords[1]); + break; + case PathIterator.SEG_QUADTO: + quadTo(coords[0], coords[1], coords[2], coords[3]); + break; + case PathIterator.SEG_CUBICTO: + curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); + break; + case PathIterator.SEG_CLOSE: + closePath(); + break; + } + path.next(); + connect = false; + } + } + + public Point2D getCurrentPoint() { + if (typeSize == 0) { + return null; + } + int j = pointSize - 2; + if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { + + for (int i = typeSize - 2; i > 0; i--) { + int type = types[i]; + if (type == PathIterator.SEG_MOVETO) { + break; + } + j -= pointShift[type]; + } + } + return new Point2D.Float(points[j], points[j + 1]); + } + + public void reset() { + typeSize = 0; + pointSize = 0; + } + + public void transform(AffineTransform t) { + t.transform(points, 0, points, 0, pointSize / 2); + } + + public Shape createTransformedShape(AffineTransform t) { + GeneralPath p = (GeneralPath)clone(); + if (t != null) { + p.transform(t); + } + return p; + } + + public Rectangle2D getBounds2D() { + float rx1, ry1, rx2, ry2; + if (pointSize == 0) { + rx1 = ry1 = rx2 = ry2 = 0.0f; + } else { + int i = pointSize - 1; + ry1 = ry2 = points[i--]; + rx1 = rx2 = points[i--]; + while (i > 0) { + float y = points[i--]; + float x = points[i--]; + if (x < rx1) { + rx1 = x; + } else + if (x > rx2) { + rx2 = x; + } + if (y < ry1) { + ry1 = y; + } else + if (y > ry2) { + ry2 = y; + } + } + } + return new Rectangle2D.Float(rx1, ry1, rx2 - rx1, ry2 - ry1); + } + + public Rectangle getBounds() { + return getBounds2D().getBounds(); + } + + /** + * Checks cross count according to path rule to define is it point inside shape or not. + * @param cross - the point cross count + * @return true if point is inside path, or false otherwise + */ + boolean isInside(int cross) { + if (rule == WIND_NON_ZERO) { + return Crossing.isInsideNonZero(cross); + } + return Crossing.isInsideEvenOdd(cross); + } + + public boolean contains(double px, double py) { + return isInside(Crossing.crossShape(this, px, py)); + } + + public boolean contains(double rx, double ry, double rw, double rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross != Crossing.CROSSING && isInside(cross); + } + + public boolean intersects(double rx, double ry, double rw, double rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross == Crossing.CROSSING || isInside(cross); + } + + public boolean contains(Point2D p) { + return contains(p.getX(), p.getY()); + } + + public boolean contains(Rectangle2D r) { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public boolean intersects(Rectangle2D r) { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public PathIterator getPathIterator(AffineTransform t) { + return new Iterator(this, t); + } + + public PathIterator getPathIterator(AffineTransform t, double flatness) { + return new FlatteningPathIterator(getPathIterator(t), flatness); + } + + @Override + public Object clone() { + try { + GeneralPath p = (GeneralPath) super.clone(); + p.types = types.clone(); + p.points = points.clone(); + return p; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + +} + diff --git a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java new file mode 100644 index 000000000..9d667e510 --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java @@ -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. + */ +/** + * @author Denis M. Kishenko + */ +package java.awt.geom; + +public class IllegalPathStateException extends RuntimeException { + + private static final long serialVersionUID = -5158084205220481094L; + + public IllegalPathStateException() { + } + + public IllegalPathStateException(String s) { + super(s); + } + +} + diff --git a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java new file mode 100644 index 000000000..eee170ec1 --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package java.awt.geom; + +public class NoninvertibleTransformException extends java.lang.Exception { + + private static final long serialVersionUID = 6137225240503990466L; + + public NoninvertibleTransformException(String s) { + super(s); + } + +} + diff --git a/src/com/jogamp/graph/geom/plane/PathIterator.java b/src/com/jogamp/graph/geom/plane/PathIterator.java new file mode 100644 index 000000000..22b897841 --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/PathIterator.java @@ -0,0 +1,44 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package java.awt.geom; + +public interface PathIterator { + + public static final int WIND_EVEN_ODD = 0; + public static final int WIND_NON_ZERO = 1; + + public static final int SEG_MOVETO = 0; + public static final int SEG_LINETO = 1; + public static final int SEG_QUADTO = 2; + public static final int SEG_CUBICTO = 3; + public static final int SEG_CLOSE = 4; + + public int getWindingRule(); + + public boolean isDone(); + + public void next(); + + public int currentSegment(float[] coords); + + public int currentSegment(double[] coords); + +} + diff --git a/src/jogamp/graph/math/plane/Crossing.java b/src/jogamp/graph/math/plane/Crossing.java new file mode 100644 index 000000000..7da1c466e --- /dev/null +++ b/src/jogamp/graph/math/plane/Crossing.java @@ -0,0 +1,895 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package org.apache.harmony.awt.gl; + +import java.awt.Shape; +import java.awt.geom.PathIterator; + +public class Crossing { + + /** + * Allowable tolerance for bounds comparison + */ + static final double DELTA = 1E-5; + + /** + * If roots have distance less then ROOT_DELTA they are double + */ + static final double ROOT_DELTA = 1E-10; + + /** + * Rectangle cross segment + */ + public static final int CROSSING = 255; + + /** + * Unknown crossing result + */ + static final int UNKNOWN = 254; + + /** + * Solves quadratic equation + * @param eqn - the coefficients of the equation + * @param res - the roots of the equation + * @return a number of roots + */ + public static int solveQuad(double eqn[], double res[]) { + double a = eqn[2]; + double b = eqn[1]; + double c = eqn[0]; + int rc = 0; + if (a == 0.0) { + if (b == 0.0) { + return -1; + } + res[rc++] = -c / b; + } else { + double d = b * b - 4.0 * a * c; + // d < 0.0 + if (d < 0.0) { + return 0; + } + d = Math.sqrt(d); + res[rc++] = (- b + d) / (a * 2.0); + // d != 0.0 + if (d != 0.0) { + res[rc++] = (- b - d) / (a * 2.0); + } + } + return fixRoots(res, rc); + } + + /** + * Solves cubic equation + * @param eqn - the coefficients of the equation + * @param res - the roots of the equation + * @return a number of roots + */ + public static int solveCubic(double eqn[], double res[]) { + double d = eqn[3]; + if (d == 0) { + return solveQuad(eqn, res); + } + double a = eqn[2] / d; + double b = eqn[1] / d; + double c = eqn[0] / d; + int rc = 0; + + double Q = (a * a - 3.0 * b) / 9.0; + double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0; + double Q3 = Q * Q * Q; + double R2 = R * R; + double n = - a / 3.0; + + if (R2 < Q3) { + double t = Math.acos(R / Math.sqrt(Q3)) / 3.0; + double p = 2.0 * Math.PI / 3.0; + double m = -2.0 * Math.sqrt(Q); + res[rc++] = m * Math.cos(t) + n; + res[rc++] = m * Math.cos(t + p) + n; + res[rc++] = m * Math.cos(t - p) + n; + } else { +// Debug.println("R2 >= Q3 (" + R2 + "/" + Q3 + ")"); + double A = Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0); + if (R > 0.0) { + A = -A; + } +// if (A == 0.0) { + if (-ROOT_DELTA < A && A < ROOT_DELTA) { + res[rc++] = n; + } else { + double B = Q / A; + res[rc++] = A + B + n; +// if (R2 == Q3) { + double delta = R2 - Q3; + if (-ROOT_DELTA < delta && delta < ROOT_DELTA) { + res[rc++] = - (A + B) / 2.0 + n; + } + } + + } + return fixRoots(res, rc); + } + + /** + * Excludes double roots. Roots are double if they lies enough close with each other. + * @param res - the roots + * @param rc - the roots count + * @return new roots count + */ + static int fixRoots(double res[], int rc) { + int tc = 0; + for(int i = 0; i < rc; i++) { + out: { + for(int j = i + 1; j < rc; j++) { + if (isZero(res[i] - res[j])) { + break out; + } + } + res[tc++] = res[i]; + } + } + return tc; + } + + /** + * QuadCurve class provides basic functionality to find curve crossing and calculating bounds + */ + public static class QuadCurve { + + double ax, ay, bx, by; + double Ax, Ay, Bx, By; + + public QuadCurve(double x1, double y1, double cx, double cy, double x2, double y2) { + ax = x2 - x1; + ay = y2 - y1; + bx = cx - x1; + by = cy - y1; + + Bx = bx + bx; // Bx = 2.0 * bx + Ax = ax - Bx; // Ax = ax - 2.0 * bx + + By = by + by; // By = 2.0 * by + Ay = ay - By; // Ay = ay - 2.0 * by + } + + int cross(double res[], int rc, double py1, double py2) { + int cross = 0; + + for (int i = 0; i < rc; i++) { + double t = res[i]; + + // CURVE-OUTSIDE + if (t < -DELTA || t > 1 + DELTA) { + continue; + } + // CURVE-START + if (t < DELTA) { + if (py1 < 0.0 && (bx != 0.0 ? bx : ax - bx) < 0.0) { + cross--; + } + continue; + } + // CURVE-END + if (t > 1 - DELTA) { + if (py1 < ay && (ax != bx ? ax - bx : bx) > 0.0) { + cross++; + } + continue; + } + // CURVE-INSIDE + double ry = t * (t * Ay + By); + // ry = t * t * Ay + t * By + if (ry > py2) { + double rxt = t * Ax + bx; + // rxt = 2.0 * t * Ax + Bx = 2.0 * t * Ax + 2.0 * bx + if (rxt > -DELTA && rxt < DELTA) { + continue; + } + cross += rxt > 0.0 ? 1 : -1; + } + } // for + + return cross; + } + + int solvePoint(double res[], double px) { + double eqn[] = {-px, Bx, Ax}; + return solveQuad(eqn, res); + } + + int solveExtrem(double res[]) { + int rc = 0; + if (Ax != 0.0) { + res[rc++] = - Bx / (Ax + Ax); + } + if (Ay != 0.0) { + res[rc++] = - By / (Ay + Ay); + } + return rc; + } + + int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) { + for(int i = 0; i < rc; i++) { + double t = res[i]; + if (t > -DELTA && t < 1 + DELTA) { + double rx = t * (t * Ax + Bx); + if (minX <= rx && rx <= maxX) { + bound[bc++] = t; + bound[bc++] = rx; + bound[bc++] = t * (t * Ay + By); + bound[bc++] = id; + if (changeId) { + id++; + } + } + } + } + return bc; + } + + } + + /** + * CubicCurve class provides basic functionality to find curve crossing and calculating bounds + */ + public static class CubicCurve { + + double ax, ay, bx, by, cx, cy; + double Ax, Ay, Bx, By, Cx, Cy; + double Ax3, Bx2; + + public CubicCurve(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2) { + ax = x2 - x1; + ay = y2 - y1; + bx = cx1 - x1; + by = cy1 - y1; + cx = cx2 - x1; + cy = cy2 - y1; + + Cx = bx + bx + bx; // Cx = 3.0 * bx + Bx = cx + cx + cx - Cx - Cx; // Bx = 3.0 * cx - 6.0 * bx + Ax = ax - Bx - Cx; // Ax = ax - 3.0 * cx + 3.0 * bx + + Cy = by + by + by; // Cy = 3.0 * by + By = cy + cy + cy - Cy - Cy; // By = 3.0 * cy - 6.0 * by + Ay = ay - By - Cy; // Ay = ay - 3.0 * cy + 3.0 * by + + Ax3 = Ax + Ax + Ax; + Bx2 = Bx + Bx; + } + + int cross(double res[], int rc, double py1, double py2) { + int cross = 0; + for (int i = 0; i < rc; i++) { + double t = res[i]; + + // CURVE-OUTSIDE + if (t < -DELTA || t > 1 + DELTA) { + continue; + } + // CURVE-START + if (t < DELTA) { + if (py1 < 0.0 && (bx != 0.0 ? bx : (cx != bx ? cx - bx : ax - cx)) < 0.0) { + cross--; + } + continue; + } + // CURVE-END + if (t > 1 - DELTA) { + if (py1 < ay && (ax != cx ? ax - cx : (cx != bx ? cx - bx : bx)) > 0.0) { + cross++; + } + continue; + } + // CURVE-INSIDE + double ry = t * (t * (t * Ay + By) + Cy); + // ry = t * t * t * Ay + t * t * By + t * Cy + if (ry > py2) { + double rxt = t * (t * Ax3 + Bx2) + Cx; + // rxt = 3.0 * t * t * Ax + 2.0 * t * Bx + Cx + if (rxt > -DELTA && rxt < DELTA) { + rxt = t * (Ax3 + Ax3) + Bx2; + // rxt = 6.0 * t * Ax + 2.0 * Bx + if (rxt < -DELTA || rxt > DELTA) { + // Inflection point + continue; + } + rxt = ax; + } + cross += rxt > 0.0 ? 1 : -1; + } + } //for + + return cross; + } + + int solvePoint(double res[], double px) { + double eqn[] = {-px, Cx, Bx, Ax}; + return solveCubic(eqn, res); + } + + int solveExtremX(double res[]) { + double eqn[] = {Cx, Bx2, Ax3}; + return solveQuad(eqn, res); + } + + int solveExtremY(double res[]) { + double eqn[] = {Cy, By + By, Ay + Ay + Ay}; + return solveQuad(eqn, res); + } + + int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) { + for(int i = 0; i < rc; i++) { + double t = res[i]; + if (t > -DELTA && t < 1 + DELTA) { + double rx = t * (t * (t * Ax + Bx) + Cx); + if (minX <= rx && rx <= maxX) { + bound[bc++] = t; + bound[bc++] = rx; + bound[bc++] = t * (t * (t * Ay + By) + Cy); + bound[bc++] = id; + if (changeId) { + id++; + } + } + } + } + return bc; + } + + } + + /** + * Returns how many times ray from point (x,y) cross line. + */ + public static int crossLine(double x1, double y1, double x2, double y2, double x, double y) { + + // LEFT/RIGHT/UP/EMPTY + if ((x < x1 && x < x2) || + (x > x1 && x > x2) || + (y > y1 && y > y2) || + (x1 == x2)) + { + return 0; + } + + // DOWN + if (y < y1 && y < y2) { + } else { + // INSIDE + if ((y2 - y1) * (x - x1) / (x2 - x1) <= y - y1) { + // INSIDE-UP + return 0; + } + } + + // START + if (x == x1) { + return x1 < x2 ? 0 : -1; + } + + // END + if (x == x2) { + return x1 < x2 ? 1 : 0; + } + + // INSIDE-DOWN + return x1 < x2 ? 1 : -1; + } + + /** + * Returns how many times ray from point (x,y) cross quard curve + */ + public static int crossQuad(double x1, double y1, double cx, double cy, double x2, double y2, double x, double y) { + + // LEFT/RIGHT/UP/EMPTY + if ((x < x1 && x < cx && x < x2) || + (x > x1 && x > cx && x > x2) || + (y > y1 && y > cy && y > y2) || + (x1 == cx && cx == x2)) + { + return 0; + } + + // DOWN + if (y < y1 && y < cy && y < y2 && x != x1 && x != x2) { + if (x1 < x2) { + return x1 < x && x < x2 ? 1 : 0; + } + return x2 < x && x < x1 ? -1 : 0; + } + + // INSIDE + QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2); + double px = x - x1; + double py = y - y1; + double res[] = new double[3]; + int rc = c.solvePoint(res, px); + + return c.cross(res, rc, py, py); + } + + /** + * Returns how many times ray from point (x,y) cross cubic curve + */ + public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y) { + + // LEFT/RIGHT/UP/EMPTY + if ((x < x1 && x < cx1 && x < cx2 && x < x2) || + (x > x1 && x > cx1 && x > cx2 && x > x2) || + (y > y1 && y > cy1 && y > cy2 && y > y2) || + (x1 == cx1 && cx1 == cx2 && cx2 == x2)) + { + return 0; + } + + // DOWN + if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2) { + if (x1 < x2) { + return x1 < x && x < x2 ? 1 : 0; + } + return x2 < x && x < x1 ? -1 : 0; + } + + // INSIDE + CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); + double px = x - x1; + double py = y - y1; + double res[] = new double[3]; + int rc = c.solvePoint(res, px); + return c.cross(res, rc, py, py); + } + + /** + * Returns how many times ray from point (x,y) cross path + */ + public static int crossPath(PathIterator p, double x, double y) { + int cross = 0; + double mx, my, cx, cy; + mx = my = cx = cy = 0.0; + double coords[] = new double[6]; + + while (!p.isDone()) { + switch (p.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (cx != mx || cy != my) { + cross += crossLine(cx, cy, mx, my, x, y); + } + mx = cx = coords[0]; + my = cy = coords[1]; + break; + case PathIterator.SEG_LINETO: + cross += crossLine(cx, cy, cx = coords[0], cy = coords[1], x, y); + break; + case PathIterator.SEG_QUADTO: + cross += crossQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3], x, y); + break; + case PathIterator.SEG_CUBICTO: + cross += crossCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5], x, y); + break; + case PathIterator.SEG_CLOSE: + if (cy != my || cx != mx) { + cross += crossLine(cx, cy, cx = mx, cy = my, x, y); + } + break; + } + + // checks if the point (x,y) is the vertex of shape with PathIterator p + if (x == cx && y == cy) { + cross = 0; + cy = my; + break; + } + p.next(); + } + if (cy != my) { + cross += crossLine(cx, cy, mx, my, x, y); + } + return cross; + } + + /** + * Returns how many times ray from point (x,y) cross shape + */ + public static int crossShape(Shape s, double x, double y) { + if (!s.getBounds2D().contains(x, y)) { + return 0; + } + return crossPath(s.getPathIterator(null), x, y); + } + + /** + * Returns true if value enough small + */ + public static boolean isZero(double val) { + return -DELTA < val && val < DELTA; + } + + /** + * Sort bound array + */ + static void sortBound(double bound[], int bc) { + for(int i = 0; i < bc - 4; i += 4) { + int k = i; + for(int j = i + 4; j < bc; j += 4) { + if (bound[k] > bound[j]) { + k = j; + } + } + if (k != i) { + double tmp = bound[i]; + bound[i] = bound[k]; + bound[k] = tmp; + tmp = bound[i + 1]; + bound[i + 1] = bound[k + 1]; + bound[k + 1] = tmp; + tmp = bound[i + 2]; + bound[i + 2] = bound[k + 2]; + bound[k + 2] = tmp; + tmp = bound[i + 3]; + bound[i + 3] = bound[k + 3]; + bound[k + 3] = tmp; + } + } + } + + /** + * Returns are bounds intersect or not intersect rectangle + */ + static int crossBound(double bound[], int bc, double py1, double py2) { + + // LEFT/RIGHT + if (bc == 0) { + return 0; + } + + // Check Y coordinate + int up = 0; + int down = 0; + for(int i = 2; i < bc; i += 4) { + if (bound[i] < py1) { + up++; + continue; + } + if (bound[i] > py2) { + down++; + continue; + } + return CROSSING; + } + + // UP + if (down == 0) { + return 0; + } + + if (up != 0) { + // bc >= 2 + sortBound(bound, bc); + boolean sign = bound[2] > py2; + for(int i = 6; i < bc; i += 4) { + boolean sign2 = bound[i] > py2; + if (sign != sign2 && bound[i + 1] != bound[i - 3]) { + return CROSSING; + } + sign = sign2; + } + } + return UNKNOWN; + } + + /** + * Returns how many times rectangle stripe cross line or the are intersect + */ + public static int intersectLine(double x1, double y1, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + + // LEFT/RIGHT/UP + if ((rx2 < x1 && rx2 < x2) || + (rx1 > x1 && rx1 > x2) || + (ry1 > y1 && ry1 > y2)) + { + return 0; + } + + // DOWN + if (ry2 < y1 && ry2 < y2) { + } else { + + // INSIDE + if (x1 == x2) { + return CROSSING; + } + + // Build bound + double bx1, bx2; + if (x1 < x2) { + bx1 = x1 < rx1 ? rx1 : x1; + bx2 = x2 < rx2 ? x2 : rx2; + } else { + bx1 = x2 < rx1 ? rx1 : x2; + bx2 = x1 < rx2 ? x1 : rx2; + } + double k = (y2 - y1) / (x2 - x1); + double by1 = k * (bx1 - x1) + y1; + double by2 = k * (bx2 - x1) + y1; + + // BOUND-UP + if (by1 < ry1 && by2 < ry1) { + return 0; + } + + // BOUND-DOWN + if (by1 > ry2 && by2 > ry2) { + } else { + return CROSSING; + } + } + + // EMPTY + if (x1 == x2) { + return 0; + } + + // CURVE-START + if (rx1 == x1) { + return x1 < x2 ? 0 : -1; + } + + // CURVE-END + if (rx1 == x2) { + return x1 < x2 ? 1 : 0; + } + + if (x1 < x2) { + return x1 < rx1 && rx1 < x2 ? 1 : 0; + } + return x2 < rx1 && rx1 < x1 ? -1 : 0; + + } + + /** + * Returns how many times rectangle stripe cross quad curve or the are intersect + */ + public static int intersectQuad(double x1, double y1, double cx, double cy, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + + // LEFT/RIGHT/UP ------------------------------------------------------ + if ((rx2 < x1 && rx2 < cx && rx2 < x2) || + (rx1 > x1 && rx1 > cx && rx1 > x2) || + (ry1 > y1 && ry1 > cy && ry1 > y2)) + { + return 0; + } + + // DOWN --------------------------------------------------------------- + if (ry2 < y1 && ry2 < cy && ry2 < y2 && rx1 != x1 && rx1 != x2) { + if (x1 < x2) { + return x1 < rx1 && rx1 < x2 ? 1 : 0; + } + return x2 < rx1 && rx1 < x1 ? -1 : 0; + } + + // INSIDE ------------------------------------------------------------- + QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2); + double px1 = rx1 - x1; + double py1 = ry1 - y1; + double px2 = rx2 - x1; + double py2 = ry2 - y1; + + double res1[] = new double[3]; + double res2[] = new double[3]; + int rc1 = c.solvePoint(res1, px1); + int rc2 = c.solvePoint(res2, px2); + + // INSIDE-LEFT/RIGHT + if (rc1 == 0 && rc2 == 0) { + return 0; + } + + // Build bound -------------------------------------------------------- + double minX = px1 - DELTA; + double maxX = px2 + DELTA; + double bound[] = new double[28]; + int bc = 0; + // Add roots + bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); + bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1); + // Add extremal points` + rc2 = c.solveExtrem(res2); + bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2); + // Add start and end + if (rx1 < x1 && x1 < rx2) { + bound[bc++] = 0.0; + bound[bc++] = 0.0; + bound[bc++] = 0.0; + bound[bc++] = 4; + } + if (rx1 < x2 && x2 < rx2) { + bound[bc++] = 1.0; + bound[bc++] = c.ax; + bound[bc++] = c.ay; + bound[bc++] = 5; + } + // End build bound ---------------------------------------------------- + + int cross = crossBound(bound, bc, py1, py2); + if (cross != UNKNOWN) { + return cross; + } + return c.cross(res1, rc1, py1, py2); + } + + /** + * Returns how many times rectangle stripe cross cubic curve or the are intersect + */ + public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + + // LEFT/RIGHT/UP + if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) || + (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) || + (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2)) + { + return 0; + } + + // DOWN + if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2) { + if (x1 < x2) { + return x1 < rx1 && rx1 < x2 ? 1 : 0; + } + return x2 < rx1 && rx1 < x1 ? -1 : 0; + } + + // INSIDE + CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); + double px1 = rx1 - x1; + double py1 = ry1 - y1; + double px2 = rx2 - x1; + double py2 = ry2 - y1; + + double res1[] = new double[3]; + double res2[] = new double[3]; + int rc1 = c.solvePoint(res1, px1); + int rc2 = c.solvePoint(res2, px2); + + // LEFT/RIGHT + if (rc1 == 0 && rc2 == 0) { + return 0; + } + + double minX = px1 - DELTA; + double maxX = px2 + DELTA; + + // Build bound -------------------------------------------------------- + double bound[] = new double[40]; + int bc = 0; + // Add roots + bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); + bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1); + // Add extrimal points + rc2 = c.solveExtremX(res2); + bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2); + rc2 = c.solveExtremY(res2); + bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4); + // Add start and end + if (rx1 < x1 && x1 < rx2) { + bound[bc++] = 0.0; + bound[bc++] = 0.0; + bound[bc++] = 0.0; + bound[bc++] = 6; + } + if (rx1 < x2 && x2 < rx2) { + bound[bc++] = 1.0; + bound[bc++] = c.ax; + bound[bc++] = c.ay; + bound[bc++] = 7; + } + // End build bound ---------------------------------------------------- + + int cross = crossBound(bound, bc, py1, py2); + if (cross != UNKNOWN) { + return cross; + } + return c.cross(res1, rc1, py1, py2); + } + + /** + * Returns how many times rectangle stripe cross path or the are intersect + */ + public static int intersectPath(PathIterator p, double x, double y, double w, double h) { + + int cross = 0; + int count; + double mx, my, cx, cy; + mx = my = cx = cy = 0.0; + double coords[] = new double[6]; + + double rx1 = x; + double ry1 = y; + double rx2 = x + w; + double ry2 = y + h; + + while (!p.isDone()) { + count = 0; + switch (p.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (cx != mx || cy != my) { + count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2); + } + mx = cx = coords[0]; + my = cy = coords[1]; + break; + case PathIterator.SEG_LINETO: + count = intersectLine(cx, cy, cx = coords[0], cy = coords[1], rx1, ry1, rx2, ry2); + break; + case PathIterator.SEG_QUADTO: + count = intersectQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3], rx1, ry1, rx2, ry2); + break; + case PathIterator.SEG_CUBICTO: + count = intersectCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5], rx1, ry1, rx2, ry2); + break; + case PathIterator.SEG_CLOSE: + if (cy != my || cx != mx) { + count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2); + } + cx = mx; + cy = my; + break; + } + if (count == CROSSING) { + return CROSSING; + } + cross += count; + p.next(); + } + if (cy != my) { + count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2); + if (count == CROSSING) { + return CROSSING; + } + cross += count; + } + return cross; + } + + /** + * Returns how many times rectangle stripe cross shape or the are intersect + */ + public static int intersectShape(Shape s, double x, double y, double w, double h) { + if (!s.getBounds2D().intersects(x, y, w, h)) { + return 0; + } + return intersectPath(s.getPathIterator(null), x, y, w, h); + } + + /** + * Returns true if cross count correspond inside location for non zero path rule + */ + public static boolean isInsideNonZero(int cross) { + return cross != 0; + } + + /** + * Returns true if cross count correspond inside location for even-odd path rule + */ + public static boolean isInsideEvenOdd(int cross) { + return (cross & 1) != 0; + } +} \ No newline at end of file diff --git a/src/org/apache/harmony/misc/HashCode.java b/src/org/apache/harmony/misc/HashCode.java new file mode 100644 index 000000000..e8ce8f620 --- /dev/null +++ b/src/org/apache/harmony/misc/HashCode.java @@ -0,0 +1,203 @@ +/* + * 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.harmony.misc; + +/** + * This class is a convenience method to sequentially calculate hash code of the + * object based on the field values. The result depends on the order of elements + * appended. The exact formula is the same as for + * java.util.List.hashCode. + * + * If you need order independent hash code just summate, multiply or XOR all + * elements. + * + *

+ * Suppose we have class: + * + *


+ * class Thing {
+ *     long id;
+ *     String name;
+ *     float weight;
+ * }
+ * 
+ * + * The hash code calculation can be expressed in 2 forms. + * + *

+ * For maximum performance: + * + *


+ * public int hashCode() {
+ *     int hashCode = HashCode.EMPTY_HASH_CODE;
+ *     hashCode = HashCode.combine(hashCode, id);
+ *     hashCode = HashCode.combine(hashCode, name);
+ *     hashCode = HashCode.combine(hashCode, weight);
+ *     return hashCode;
+ * }
+ * 
+ * + *

+ * For convenience:

+ * public int hashCode() {
+ *     return new HashCode().append(id).append(name).append(weight).hashCode();
+ * }
+ * 
+ * + * @see java.util.List#hashCode() + */ +public final class HashCode { + /** + * The hashCode value before any data is appended, equals to 1. + * @see java.util.List#hashCode() + */ + public static final int EMPTY_HASH_CODE = 1; + + private int hashCode = EMPTY_HASH_CODE; + + /** + * Returns accumulated hashCode + */ + public final int hashCode() { + return hashCode; + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, boolean value) { + int v = value ? 1231 : 1237; + return combine(hashCode, v); + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, long value) { + int v = (int) (value ^ (value >>> 32)); + return combine(hashCode, v); + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, float value) { + int v = Float.floatToIntBits(value); + return combine(hashCode, v); + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, double value) { + long v = Double.doubleToLongBits(value); + return combine(hashCode, v); + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, Object value) { + return combine(hashCode, value.hashCode()); + } + + /** + * Combines hashCode of previous elements sequence and value's hashCode. + * @param hashCode previous hashCode value + * @param value new element + * @return combined hashCode + */ + public static int combine(int hashCode, int value) { + return 31 * hashCode + value; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(int value) { + hashCode = combine(hashCode, value); + return this; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(long value) { + hashCode = combine(hashCode, value); + return this; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(float value) { + hashCode = combine(hashCode, value); + return this; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(double value) { + hashCode = combine(hashCode, value); + return this; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(boolean value) { + hashCode = combine(hashCode, value); + return this; + } + + /** + * Appends value's hashCode to the current hashCode. + * @param value new element + * @return this + */ + public final HashCode append(Object value) { + hashCode = combine(hashCode, value); + return this; + } +} -- cgit v1.2.3 From 524a7d61a4fc4a4d38aeb543b9887e787555bb71 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 03:45:53 +0100 Subject: Fitting of jogamp.graph.geom.plane: double -> float, package location, use PointFactory, GeneralPath -> Path2D, .. --- .../jogamp/graph/geom/plane/AffineTransform.java | 330 +++++++--------- src/com/jogamp/graph/geom/plane/GeneralPath.java | 433 --------------------- .../geom/plane/IllegalPathStateException.java | 2 +- .../plane/NoninvertibleTransformException.java | 2 +- src/com/jogamp/graph/geom/plane/Path2D.java | 430 ++++++++++++++++++++ src/com/jogamp/graph/geom/plane/PathIterator.java | 4 +- src/jogamp/graph/math/plane/Crossing.java | 258 ++++++------ 7 files changed, 696 insertions(+), 763 deletions(-) delete mode 100644 src/com/jogamp/graph/geom/plane/GeneralPath.java create mode 100644 src/com/jogamp/graph/geom/plane/Path2D.java diff --git a/src/com/jogamp/graph/geom/plane/AffineTransform.java b/src/com/jogamp/graph/geom/plane/AffineTransform.java index 065ad94b2..321551edc 100644 --- a/src/com/jogamp/graph/geom/plane/AffineTransform.java +++ b/src/com/jogamp/graph/geom/plane/AffineTransform.java @@ -17,19 +17,23 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; -import java.awt.Shape; import java.io.IOException; import java.io.Serializable; -import org.apache.harmony.awt.internal.nls.Messages; +import jogamp.graph.math.MathFloat; import org.apache.harmony.misc.HashCode; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Point.Factory; + public class AffineTransform implements Cloneable, Serializable { private static final long serialVersionUID = 1330973210523860834L; + static final String determinantIsZero = "Determinant is zero"; + public static final int TYPE_IDENTITY = 0; public static final int TYPE_TRANSLATION = 1; public static final int TYPE_UNIFORM_SCALE = 2; @@ -49,30 +53,34 @@ public class AffineTransform implements Cloneable, Serializable { /** * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. */ - static final double ZERO = 1E-10; + static final float ZERO = (float) 1E-10; + private final Point.Factory pointFactory; + /** * The values of transformation matrix */ - double m00; - double m10; - double m01; - double m11; - double m02; - double m12; + float m00; + float m10; + float m01; + float m11; + float m02; + float m12; /** * The transformation type */ transient int type; - public AffineTransform() { + public AffineTransform(Factory factory) { + pointFactory = factory; type = TYPE_IDENTITY; - m00 = m11 = 1.0; - m10 = m01 = m02 = m12 = 0.0; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; } public AffineTransform(AffineTransform t) { + this.pointFactory = t.pointFactory; this.type = t.type; this.m00 = t.m00; this.m10 = t.m10; @@ -82,7 +90,8 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = t.m12; } - public AffineTransform(float m00, float m10, float m01, float m11, float m02, float m12) { + public AffineTransform(Point.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { + pointFactory = factory; this.type = TYPE_UNKNOWN; this.m00 = m00; this.m10 = m10; @@ -92,29 +101,8 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = m12; } - public AffineTransform(double m00, double m10, double m01, double m11, double m02, double m12) { - this.type = TYPE_UNKNOWN; - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - } - - public AffineTransform(float[] matrix) { - this.type = TYPE_UNKNOWN; - m00 = matrix[0]; - m10 = matrix[1]; - m01 = matrix[2]; - m11 = matrix[3]; - if (matrix.length > 4) { - m02 = matrix[4]; - m12 = matrix[5]; - } - } - - public AffineTransform(double[] matrix) { + public AffineTransform(Point.Factory factory, float[] matrix) { + pointFactory = factory; this.type = TYPE_UNKNOWN; m00 = matrix[0]; m10 = matrix[1]; @@ -169,8 +157,8 @@ public class AffineTransform implements Cloneable, Serializable { type |= TYPE_FLIP; } - double dx = m00 * m00 + m10 * m10; - double dy = m01 * m01 + m11 * m11; + float dx = m00 * m00 + m10 * m10; + float dy = m01 * m01 + m11 * m11; if (dx != dy) { type |= TYPE_GENERAL_SCALE; } else @@ -190,27 +178,27 @@ public class AffineTransform implements Cloneable, Serializable { return type; } - public double getScaleX() { + public float getScaleX() { return m00; } - public double getScaleY() { + public float getScaleY() { return m11; } - public double getShearX() { + public float getShearX() { return m01; } - public double getShearY() { + public float getShearY() { return m10; } - public double getTranslateX() { + public float getTranslateX() { return m02; } - public double getTranslateY() { + public float getTranslateY() { return m12; } @@ -218,7 +206,7 @@ public class AffineTransform implements Cloneable, Serializable { return getType() == TYPE_IDENTITY; } - public void getMatrix(double[] matrix) { + public void getMatrix(float[] matrix) { matrix[0] = m00; matrix[1] = m10; matrix[2] = m01; @@ -229,11 +217,11 @@ public class AffineTransform implements Cloneable, Serializable { } } - public double getDeterminant() { + public float getDeterminant() { return m00 * m11 - m01 * m10; } - public void setTransform(double m00, double m10, double m01, double m11, double m02, double m12) { + public void setTransform(float m00, float m10, float m01, float m11, float m02, float m12) { this.type = TYPE_UNKNOWN; this.m00 = m00; this.m10 = m10; @@ -250,128 +238,130 @@ public class AffineTransform implements Cloneable, Serializable { public void setToIdentity() { type = TYPE_IDENTITY; - m00 = m11 = 1.0; - m10 = m01 = m02 = m12 = 0.0; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; } - public void setToTranslation(double mx, double my) { - m00 = m11 = 1.0; - m01 = m10 = 0.0; + public void setToTranslation(float mx, float my) { + m00 = m11 = 1.0f; + m01 = m10 = 0.0f; m02 = mx; m12 = my; - if (mx == 0.0 && my == 0.0) { + if (mx == 0.0f && my == 0.0f) { type = TYPE_IDENTITY; } else { type = TYPE_TRANSLATION; } } - public void setToScale(double scx, double scy) { + public void setToScale(float scx, float scy) { m00 = scx; m11 = scy; - m10 = m01 = m02 = m12 = 0.0; - if (scx != 1.0 || scy != 1.0) { + m10 = m01 = m02 = m12 = 0.0f; + if (scx != 1.0f || scy != 1.0f) { type = TYPE_UNKNOWN; } else { type = TYPE_IDENTITY; } } - public void setToShear(double shx, double shy) { - m00 = m11 = 1.0; - m02 = m12 = 0.0; + public void setToShear(float shx, float shy) { + m00 = m11 = 1.0f; + m02 = m12 = 0.0f; m01 = shx; m10 = shy; - if (shx != 0.0 || shy != 0.0) { + if (shx != 0.0f || shy != 0.0f) { type = TYPE_UNKNOWN; } else { type = TYPE_IDENTITY; } } - public void setToRotation(double angle) { - double sin = Math.sin(angle); - double cos = Math.cos(angle); - if (Math.abs(cos) < ZERO) { - cos = 0.0; - sin = sin > 0.0 ? 1.0 : -1.0; + public void setToRotation(float angle) { + float sin = MathFloat.sin(angle); + float cos = MathFloat.cos(angle); + if (MathFloat.abs(cos) < ZERO) { + cos = 0.0f; + sin = sin > 0.0f ? 1.0f : -1.0f; } else - if (Math.abs(sin) < ZERO) { - sin = 0.0; - cos = cos > 0.0 ? 1.0 : -1.0; + if (MathFloat.abs(sin) < ZERO) { + sin = 0.0f; + cos = cos > 0.0f ? 1.0f : -1.0f; } m00 = m11 = cos; m01 = -sin; m10 = sin; - m02 = m12 = 0.0; + m02 = m12 = 0.0f; type = TYPE_UNKNOWN; } - public void setToRotation(double angle, double px, double py) { + public void setToRotation(float angle, float px, float py) { setToRotation(angle); - m02 = px * (1.0 - m00) + py * m10; - m12 = py * (1.0 - m00) - px * m10; + m02 = px * (1.0f - m00) + py * m10; + m12 = py * (1.0f - m00) - px * m10; type = TYPE_UNKNOWN; } - public static AffineTransform getTranslateInstance(double mx, double my) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getTranslateInstance(Point.Factory factory, float mx, float my) { + AffineTransform t = new AffineTransform(factory); t.setToTranslation(mx, my); return t; } - public static AffineTransform getScaleInstance(double scx, double scY) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getScaleInstance(Point.Factory factory, float scx, float scY) { + AffineTransform t = new AffineTransform(factory); t.setToScale(scx, scY); return t; } - public static AffineTransform getShearInstance(double shx, double shy) { - AffineTransform m = new AffineTransform(); - m.setToShear(shx, shy); - return m; + public static AffineTransform getShearInstance(Point.Factory factory, float shx, float shy) { + AffineTransform t = new AffineTransform(factory); + t.setToShear(shx, shy); + return t; } - public static AffineTransform getRotateInstance(double angle) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getRotateInstance(Point.Factory factory, float angle) { + AffineTransform t = new AffineTransform(factory); t.setToRotation(angle); return t; } - public static AffineTransform getRotateInstance(double angle, double x, double y) { - AffineTransform t = new AffineTransform(); + public static AffineTransform getRotateInstance(Point.Factory factory, float angle, float x, float y) { + AffineTransform t = new AffineTransform(factory); t.setToRotation(angle, x, y); return t; } - public void translate(double mx, double my) { - concatenate(AffineTransform.getTranslateInstance(mx, my)); + public void translate(float mx, float my) { + concatenate(AffineTransform.getTranslateInstance(pointFactory, mx, my)); } - public void scale(double scx, double scy) { - concatenate(AffineTransform.getScaleInstance(scx, scy)); + public void scale(float scx, float scy) { + concatenate(AffineTransform.getScaleInstance(pointFactory, scx, scy)); } - public void shear(double shx, double shy) { - concatenate(AffineTransform.getShearInstance(shx, shy)); + public void shear(float shx, float shy) { + concatenate(AffineTransform.getShearInstance(pointFactory, shx, shy)); } - public void rotate(double angle) { - concatenate(AffineTransform.getRotateInstance(angle)); + public void rotate(float angle) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle)); } - public void rotate(double angle, double px, double py) { - concatenate(AffineTransform.getRotateInstance(angle, px, py)); + public void rotate(float angle, float px, float py) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle, px, py)); } /** - * Multiply matrix of two AffineTransform objects + * Multiply matrix of two AffineTransform objects. + * The first argument's {@link Point.Factory} is being used. + * * @param t1 - the AffineTransform object is a multiplicand * @param t2 - the AffineTransform object is a multiplier * @return an AffineTransform object that is a result of t1 multiplied by matrix t2. */ AffineTransform multiply(AffineTransform t1, AffineTransform t2) { - return new AffineTransform( + return new AffineTransform(t1.pointFactory, t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00 t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01 t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10 @@ -389,12 +379,12 @@ public class AffineTransform implements Cloneable, Serializable { } public AffineTransform createInverse() throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } return new AffineTransform( + this.pointFactory, m11 / det, // m00 -m10 / det, // m10 -m01 / det, // m01 @@ -404,57 +394,32 @@ public class AffineTransform implements Cloneable, Serializable { ); } - public Point2D transform(Point2D src, Point2D dst) { + public Point transform(Point src, Point dst) { if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX(); - double y = src.getY(); + float x = src.getX(); + float y = src.getY(); - dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); return dst; } - public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int length) { + public void transform(Point[] src, int srcOff, Point[] dst, int dstOff, int length) { while (--length >= 0) { - Point2D srcPoint = src[srcOff++]; - double x = srcPoint.getX(); - double y = srcPoint.getY(); - Point2D dstPoint = dst[dstOff]; + Point srcPoint = src[srcOff++]; + float x = srcPoint.getX(); + float y = srcPoint.getY(); + Point dstPoint = dst[dstOff]; if (dstPoint == null) { - if (srcPoint instanceof Point2D.Double) { - dstPoint = new Point2D.Double(); - } else { - dstPoint = new Point2D.Float(); - } + throw new IllegalArgumentException("dst["+dstOff+"] is null"); } - dstPoint.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); dst[dstOff++] = dstPoint; } } - public void transform(double[] src, int srcOff, double[] dst, int dstOff, int length) { - int step = 2; - if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { - srcOff = srcOff + length * 2 - 2; - dstOff = dstOff + length * 2 - 2; - step = -2; - } - while (--length >= 0) { - double x = src[srcOff + 0]; - double y = src[srcOff + 1]; - dst[dstOff + 0] = x * m00 + y * m01 + m02; - dst[dstOff + 1] = x * m10 + y * m11 + m12; - srcOff += step; - dstOff += step; - } - } - public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) { int step = 2; if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { @@ -465,104 +430,75 @@ public class AffineTransform implements Cloneable, Serializable { while (--length >= 0) { float x = src[srcOff + 0]; float y = src[srcOff + 1]; - dst[dstOff + 0] = (float)(x * m00 + y * m01 + m02); - dst[dstOff + 1] = (float)(x * m10 + y * m11 + m12); + dst[dstOff + 0] = x * m00 + y * m01 + m02; + dst[dstOff + 1] = x * m10 + y * m11 + m12; srcOff += step; dstOff += step; } } - public void transform(float[] src, int srcOff, double[] dst, int dstOff, int length) { - while (--length >= 0) { - float x = src[srcOff++]; - float y = src[srcOff++]; - dst[dstOff++] = x * m00 + y * m01 + m02; - dst[dstOff++] = x * m10 + y * m11 + m12; - } - } - - public void transform(double[] src, int srcOff, float[] dst, int dstOff, int length) { - while (--length >= 0) { - double x = src[srcOff++]; - double y = src[srcOff++]; - dst[dstOff++] = (float)(x * m00 + y * m01 + m02); - dst[dstOff++] = (float)(x * m10 + y * m11 + m12); - } - } - - public Point2D deltaTransform(Point2D src, Point2D dst) { + public Point deltaTransform(Point src, Point dst) { if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX(); - double y = src.getY(); + float x = src.getX(); + float y = src.getY(); - dst.setLocation(x * m00 + y * m01, x * m10 + y * m11); + dst.setCoord(x * m00 + y * m01, x * m10 + y * m11); return dst; } - public void deltaTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) { + public void deltaTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) { while (--length >= 0) { - double x = src[srcOff++]; - double y = src[srcOff++]; + float x = src[srcOff++]; + float y = src[srcOff++]; dst[dstOff++] = x * m00 + y * m01; dst[dstOff++] = x * m10 + y * m11; } } - public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + public Point inverseTransform(Point src, Point dst) throws NoninvertibleTransformException { + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } - if (dst == null) { - if (src instanceof Point2D.Double) { - dst = new Point2D.Double(); - } else { - dst = new Point2D.Float(); - } + dst = pointFactory.create(); } - double x = src.getX() - m02; - double y = src.getY() - m12; + float x = src.getX() - m02; + float y = src.getY() - m12; - dst.setLocation((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); + dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); return dst; } - public void inverseTransform(double[] src, int srcOff, double[] dst, int dstOff, int length) + public void inverseTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) throws NoninvertibleTransformException { - double det = getDeterminant(); - if (Math.abs(det) < ZERO) { - // awt.204=Determinant is zero - throw new NoninvertibleTransformException(Messages.getString("awt.204")); //$NON-NLS-1$ + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); } while (--length >= 0) { - double x = src[srcOff++] - m02; - double y = src[srcOff++] - m12; + float x = src[srcOff++] - m02; + float y = src[srcOff++] - m12; dst[dstOff++] = (x * m11 - y * m01) / det; dst[dstOff++] = (y * m00 - x * m10) / det; } } - public Shape createTransformedShape(Shape src) { + public Path2D createTransformedShape(Path2D src) { if (src == null) { return null; } - if (src instanceof GeneralPath) { - return ((GeneralPath)src).createTransformedShape(this); + if (src instanceof Path2D) { + return ((Path2D)src).createTransformedShape(this); } - PathIterator path = src.getPathIterator(this); - GeneralPath dst = new GeneralPath(path.getWindingRule()); + PathIterator path = src.iterator(this); + Path2D dst = new Path2D(path.getWindingRule()); dst.append(path, false); return dst; } diff --git a/src/com/jogamp/graph/geom/plane/GeneralPath.java b/src/com/jogamp/graph/geom/plane/GeneralPath.java deleted file mode 100644 index 6d6282ef1..000000000 --- a/src/com/jogamp/graph/geom/plane/GeneralPath.java +++ /dev/null @@ -1,433 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.NoSuchElementException; - -import org.apache.harmony.awt.gl.Crossing; -import org.apache.harmony.awt.internal.nls.Messages; - -public final class GeneralPath implements Shape, Cloneable { - - public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; - public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; - - /** - * The buffers size - */ - private static final int BUFFER_SIZE = 10; - - /** - * The buffers capacity - */ - private static final int BUFFER_CAPACITY = 10; - - /** - * The point's types buffer - */ - byte[] types; - - /** - * The points buffer - */ - float[] points; - - /** - * The point's type buffer size - */ - int typeSize; - - /** - * The points buffer size - */ - int pointSize; - - /** - * The path rule - */ - int rule; - - /** - * The space amount in points buffer for different segmenet's types - */ - static int pointShift[] = { - 2, // MOVETO - 2, // LINETO - 4, // QUADTO - 6, // CUBICTO - 0}; // CLOSE - - /* - * GeneralPath path iterator - */ - class Iterator implements PathIterator { - - /** - * The current cursor position in types buffer - */ - int typeIndex; - - /** - * The current cursor position in points buffer - */ - int pointIndex; - - /** - * The source GeneralPath object - */ - GeneralPath p; - - /** - * The path iterator transformation - */ - AffineTransform t; - - /** - * Constructs a new GeneralPath.Iterator for given general path - * @param path - the source GeneralPath object - */ - Iterator(GeneralPath path) { - this(path, null); - } - - /** - * Constructs a new GeneralPath.Iterator for given general path and transformation - * @param path - the source GeneralPath object - * @param at - the AffineTransform object to apply rectangle path - */ - Iterator(GeneralPath path, AffineTransform at) { - this.p = path; - this.t = at; - } - - public int getWindingRule() { - return p.getWindingRule(); - } - - public boolean isDone() { - return typeIndex >= p.typeSize; - } - - public void next() { - typeIndex++; - } - - public int currentSegment(double[] coords) { - if (isDone()) { - // awt.4B=Iterator out of bounds - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ - } - int type = p.types[typeIndex]; - int count = GeneralPath.pointShift[type]; - for (int i = 0; i < count; i++) { - coords[i] = p.points[pointIndex + i]; - } - if (t != null) { - t.transform(coords, 0, coords, 0, count / 2); - } - pointIndex += count; - return type; - } - - public int currentSegment(float[] coords) { - if (isDone()) { - // awt.4B=Iterator out of bounds - throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$ - } - int type = p.types[typeIndex]; - int count = GeneralPath.pointShift[type]; - System.arraycopy(p.points, pointIndex, coords, 0, count); - if (t != null) { - t.transform(coords, 0, coords, 0, count / 2); - } - pointIndex += count; - return type; - } - - } - - public GeneralPath() { - this(WIND_NON_ZERO, BUFFER_SIZE); - } - - public GeneralPath(int rule) { - this(rule, BUFFER_SIZE); - } - - public GeneralPath(int rule, int initialCapacity) { - setWindingRule(rule); - types = new byte[initialCapacity]; - points = new float[initialCapacity * 2]; - } - - public GeneralPath(Shape shape) { - this(WIND_NON_ZERO, BUFFER_SIZE); - PathIterator p = shape.getPathIterator(null); - setWindingRule(p.getWindingRule()); - append(p, false); - } - - public void setWindingRule(int rule) { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { - // awt.209=Invalid winding rule value - throw new java.lang.IllegalArgumentException(Messages.getString("awt.209")); //$NON-NLS-1$ - } - this.rule = rule; - } - - public int getWindingRule() { - return rule; - } - - /** - * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. - * @param pointCount - the point count to be added in buffer - */ - void checkBuf(int pointCount, boolean checkMove) { - if (checkMove && typeSize == 0) { - // awt.20A=First segment should be SEG_MOVETO type - throw new IllegalPathStateException(Messages.getString("awt.20A")); //$NON-NLS-1$ - } - if (typeSize == types.length) { - byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; - System.arraycopy(types, 0, tmp, 0, typeSize); - types = tmp; - } - if (pointSize + pointCount > points.length) { - float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; - System.arraycopy(points, 0, tmp, 0, pointSize); - points = tmp; - } - } - - public void moveTo(float x, float y) { - if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { - points[pointSize - 2] = x; - points[pointSize - 1] = y; - } else { - checkBuf(2, false); - types[typeSize++] = PathIterator.SEG_MOVETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - } - - public void lineTo(float x, float y) { - checkBuf(2, true); - types[typeSize++] = PathIterator.SEG_LINETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - - public void quadTo(float x1, float y1, float x2, float y2) { - checkBuf(4, true); - types[typeSize++] = PathIterator.SEG_QUADTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - } - - public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - checkBuf(6, true); - types[typeSize++] = PathIterator.SEG_CUBICTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - points[pointSize++] = x3; - points[pointSize++] = y3; - } - - public void closePath() { - if (typeSize == 0 || types[typeSize - 1] != PathIterator.SEG_CLOSE) { - checkBuf(0, true); - types[typeSize++] = PathIterator.SEG_CLOSE; - } - } - - public void append(Shape shape, boolean connect) { - PathIterator p = shape.getPathIterator(null); - append(p, connect); - } - - public void append(PathIterator path, boolean connect) { - while (!path.isDone()) { - float coords[] = new float[6]; - switch (path.currentSegment(coords)) { - case PathIterator.SEG_MOVETO: - if (!connect || typeSize == 0) { - moveTo(coords[0], coords[1]); - break; - } - if (types[typeSize - 1] != PathIterator.SEG_CLOSE && - points[pointSize - 2] == coords[0] && - points[pointSize - 1] == coords[1]) - { - break; - } - // NO BREAK; - case PathIterator.SEG_LINETO: - lineTo(coords[0], coords[1]); - break; - case PathIterator.SEG_QUADTO: - quadTo(coords[0], coords[1], coords[2], coords[3]); - break; - case PathIterator.SEG_CUBICTO: - curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); - break; - case PathIterator.SEG_CLOSE: - closePath(); - break; - } - path.next(); - connect = false; - } - } - - public Point2D getCurrentPoint() { - if (typeSize == 0) { - return null; - } - int j = pointSize - 2; - if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { - - for (int i = typeSize - 2; i > 0; i--) { - int type = types[i]; - if (type == PathIterator.SEG_MOVETO) { - break; - } - j -= pointShift[type]; - } - } - return new Point2D.Float(points[j], points[j + 1]); - } - - public void reset() { - typeSize = 0; - pointSize = 0; - } - - public void transform(AffineTransform t) { - t.transform(points, 0, points, 0, pointSize / 2); - } - - public Shape createTransformedShape(AffineTransform t) { - GeneralPath p = (GeneralPath)clone(); - if (t != null) { - p.transform(t); - } - return p; - } - - public Rectangle2D getBounds2D() { - float rx1, ry1, rx2, ry2; - if (pointSize == 0) { - rx1 = ry1 = rx2 = ry2 = 0.0f; - } else { - int i = pointSize - 1; - ry1 = ry2 = points[i--]; - rx1 = rx2 = points[i--]; - while (i > 0) { - float y = points[i--]; - float x = points[i--]; - if (x < rx1) { - rx1 = x; - } else - if (x > rx2) { - rx2 = x; - } - if (y < ry1) { - ry1 = y; - } else - if (y > ry2) { - ry2 = y; - } - } - } - return new Rectangle2D.Float(rx1, ry1, rx2 - rx1, ry2 - ry1); - } - - public Rectangle getBounds() { - return getBounds2D().getBounds(); - } - - /** - * Checks cross count according to path rule to define is it point inside shape or not. - * @param cross - the point cross count - * @return true if point is inside path, or false otherwise - */ - boolean isInside(int cross) { - if (rule == WIND_NON_ZERO) { - return Crossing.isInsideNonZero(cross); - } - return Crossing.isInsideEvenOdd(cross); - } - - public boolean contains(double px, double py) { - return isInside(Crossing.crossShape(this, px, py)); - } - - public boolean contains(double rx, double ry, double rw, double rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross != Crossing.CROSSING && isInside(cross); - } - - public boolean intersects(double rx, double ry, double rw, double rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross == Crossing.CROSSING || isInside(cross); - } - - public boolean contains(Point2D p) { - return contains(p.getX(), p.getY()); - } - - public boolean contains(Rectangle2D r) { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - public boolean intersects(Rectangle2D r) { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - public PathIterator getPathIterator(AffineTransform t) { - return new Iterator(this, t); - } - - public PathIterator getPathIterator(AffineTransform t, double flatness) { - return new FlatteningPathIterator(getPathIterator(t), flatness); - } - - @Override - public Object clone() { - try { - GeneralPath p = (GeneralPath) super.clone(); - p.types = types.clone(); - p.points = points.clone(); - return p; - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - -} - diff --git a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java index 9d667e510..15f629b88 100644 --- a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java +++ b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public class IllegalPathStateException extends RuntimeException { diff --git a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java index eee170ec1..cd1ec8d16 100644 --- a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java +++ b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public class NoninvertibleTransformException extends java.lang.Exception { diff --git a/src/com/jogamp/graph/geom/plane/Path2D.java b/src/com/jogamp/graph/geom/plane/Path2D.java new file mode 100644 index 000000000..031450c8e --- /dev/null +++ b/src/com/jogamp/graph/geom/plane/Path2D.java @@ -0,0 +1,430 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package com.jogamp.graph.geom.plane; + +import java.util.NoSuchElementException; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.opengl.Vertex; + +import jogamp.graph.math.plane.Crossing; + +public final class Path2D implements Cloneable { + + public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; + public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; + + static final String invalidWindingRuleValue = "Invalid winding rule value"; + static final String iteratorOutOfBounds = "Iterator out of bounds"; + + /** + * The buffers size + */ + private static final int BUFFER_SIZE = 10; + + /** + * The buffers capacity + */ + private static final int BUFFER_CAPACITY = 10; + + /** + * The point's types buffer + */ + byte[] types; + + /** + * The points buffer + */ + float[] points; + + /** + * The point's type buffer size + */ + int typeSize; + + /** + * The points buffer size + */ + int pointSize; + + /** + * The path rule + */ + int rule; + + /** + * The space amount in points buffer for different segmenet's types + */ + static int pointShift[] = { + 2, // MOVETO + 2, // LINETO + 4, // QUADTO + 6, // CUBICTO + 0}; // CLOSE + + /* + * GeneralPath path iterator + */ + class Iterator implements PathIterator { + + /** + * The current cursor position in types buffer + */ + int typeIndex; + + /** + * The current cursor position in points buffer + */ + int pointIndex; + + /** + * The source GeneralPath object + */ + Path2D p; + + /** + * The path iterator transformation + */ + AffineTransform t; + + /** + * Constructs a new GeneralPath.Iterator for given general path + * @param path - the source GeneralPath object + */ + Iterator(Path2D path) { + this(path, null); + } + + /** + * Constructs a new GeneralPath.Iterator for given general path and transformation + * @param path - the source GeneralPath object + * @param at - the AffineTransform object to apply rectangle path + */ + Iterator(Path2D path, AffineTransform at) { + this.p = path; + this.t = at; + } + + public int getWindingRule() { + return p.getWindingRule(); + } + + public boolean isDone() { + return typeIndex >= p.typeSize; + } + + public void next() { + typeIndex++; + } + + public int currentSegment(float[] coords) { + if (isDone()) { + throw new NoSuchElementException(iteratorOutOfBounds); + } + int type = p.types[typeIndex]; + int count = Path2D.pointShift[type]; + System.arraycopy(p.points, pointIndex, coords, 0, count); + if (t != null) { + t.transform(coords, 0, coords, 0, count / 2); + } + pointIndex += count; + return type; + } + + } + + public Path2D() { + this(WIND_NON_ZERO, BUFFER_SIZE); + } + + public Path2D(int rule) { + this(rule, BUFFER_SIZE); + } + + public Path2D(int rule, int initialCapacity) { + setWindingRule(rule); + types = new byte[initialCapacity]; + points = new float[initialCapacity * 2]; + } + + public Path2D(Path2D path) { + this(WIND_NON_ZERO, BUFFER_SIZE); + PathIterator p = path.iterator(null); + setWindingRule(p.getWindingRule()); + append(p, false); + } + + public void setWindingRule(int rule) { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { + throw new NoSuchElementException(invalidWindingRuleValue); + } + this.rule = rule; + } + + public int getWindingRule() { + return rule; + } + + /** + * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. + * @param pointCount - the point count to be added in buffer + */ + void checkBuf(int pointCount, boolean checkMove) { + if (checkMove && typeSize == 0) { + throw new IllegalPathStateException("First segment should be SEG_MOVETO type"); + } + if (typeSize == types.length) { + byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; + System.arraycopy(types, 0, tmp, 0, typeSize); + types = tmp; + } + if (pointSize + pointCount > points.length) { + float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; + System.arraycopy(points, 0, tmp, 0, pointSize); + points = tmp; + } + } + + public void moveTo(float x, float y) { + if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { + points[pointSize - 2] = x; + points[pointSize - 1] = y; + } else { + checkBuf(2, false); + types[typeSize++] = PathIterator.SEG_MOVETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + } + + public void lineTo(float x, float y) { + checkBuf(2, true); + types[typeSize++] = PathIterator.SEG_LINETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + + public void quadTo(float x1, float y1, float x2, float y2) { + checkBuf(4, true); + types[typeSize++] = PathIterator.SEG_QUADTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + } + + public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { + checkBuf(6, true); + types[typeSize++] = PathIterator.SEG_CUBICTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + points[pointSize++] = x3; + points[pointSize++] = y3; + } + + final public int size() { + return typeSize; + } + + final public boolean isClosed() { + return typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_CLOSE ; + } + + public void closePath() { + if (!isClosed()) { + checkBuf(0, true); + types[typeSize++] = PathIterator.SEG_CLOSE; + } + } + + public String toString() { + return "[size "+size()+", closed "+isClosed()+"]"; + } + + public void append(Path2D path, boolean connect) { + PathIterator p = path.iterator(null); + append(p, connect); + } + + public void append(PathIterator path, boolean connect) { + while (!path.isDone()) { + float coords[] = new float[6]; + switch (path.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (!connect || typeSize == 0) { + moveTo(coords[0], coords[1]); + break; + } + if (types[typeSize - 1] != PathIterator.SEG_CLOSE && + points[pointSize - 2] == coords[0] && + points[pointSize - 1] == coords[1]) + { + break; + } + // NO BREAK; + case PathIterator.SEG_LINETO: + lineTo(coords[0], coords[1]); + break; + case PathIterator.SEG_QUADTO: + quadTo(coords[0], coords[1], coords[2], coords[3]); + break; + case PathIterator.SEG_CUBICTO: + curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); + break; + case PathIterator.SEG_CLOSE: + closePath(); + break; + } + path.next(); + connect = false; + } + } + + public Vertex getCurrentPoint() { + if (typeSize == 0) { + return null; + } + int j = pointSize - 2; + if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { + + for (int i = typeSize - 2; i > 0; i--) { + int type = types[i]; + if (type == PathIterator.SEG_MOVETO) { + break; + } + j -= pointShift[type]; + } + } + return new Vertex(points[j], points[j + 1]); + } + + public void reset() { + typeSize = 0; + pointSize = 0; + } + + public void transform(AffineTransform t) { + t.transform(points, 0, points, 0, pointSize / 2); + } + + public Path2D createTransformedShape(AffineTransform t) { + Path2D p = (Path2D)clone(); + if (t != null) { + p.transform(t); + } + return p; + } + + public final synchronized AABBox getBounds2D() { + float rx1, ry1, rx2, ry2; + if (pointSize == 0) { + rx1 = ry1 = rx2 = ry2 = 0.0f; + } else { + int i = pointSize - 1; + ry1 = ry2 = points[i--]; + rx1 = rx2 = points[i--]; + while (i > 0) { + float y = points[i--]; + float x = points[i--]; + if (x < rx1) { + rx1 = x; + } else + if (x > rx2) { + rx2 = x; + } + if (y < ry1) { + ry1 = y; + } else + if (y > ry2) { + ry2 = y; + } + } + } + // FIXME: Rami's code had this in, but AABBox uses upper left - lower right - right ? + // return new AABBox(rx1, ry1, 0f, rx2 - rx1, ry2 - ry1, 0f); + return new AABBox(rx1, ry1, 0f, rx2, ry2, 0f); + } + + /** + * Checks cross count according to path rule to define is it point inside shape or not. + * @param cross - the point cross count + * @return true if point is inside path, or false otherwise + */ + boolean isInside(int cross) { + if (rule == WIND_NON_ZERO) { + return Crossing.isInsideNonZero(cross); + } + return Crossing.isInsideEvenOdd(cross); + } + + public boolean contains(float px, float py) { + return isInside(Crossing.crossShape(this, px, py)); + } + + public boolean contains(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross != Crossing.CROSSING && isInside(cross); + } + + public boolean intersects(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross == Crossing.CROSSING || isInside(cross); + } + + public boolean contains(Point p) { + return contains(p.getX(), p.getY()); + } + + public boolean contains(AABBox r) { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public boolean intersects(AABBox r) { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public PathIterator iterator() { + return new Iterator(this); + } + + public PathIterator iterator(AffineTransform t) { + return new Iterator(this, t); + } + + /* public PathIterator getPathIterator(AffineTransform t, float flatness) { + return new FlatteningPathIterator(getPathIterator(t), flatness); + } */ + + @Override + public Object clone() { + try { + Path2D p = (Path2D) super.clone(); + p.types = types.clone(); + p.points = points.clone(); + return p; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } +} + diff --git a/src/com/jogamp/graph/geom/plane/PathIterator.java b/src/com/jogamp/graph/geom/plane/PathIterator.java index 22b897841..b4681df0a 100644 --- a/src/com/jogamp/graph/geom/plane/PathIterator.java +++ b/src/com/jogamp/graph/geom/plane/PathIterator.java @@ -17,7 +17,7 @@ /** * @author Denis M. Kishenko */ -package java.awt.geom; +package com.jogamp.graph.geom.plane; public interface PathIterator { @@ -38,7 +38,5 @@ public interface PathIterator { public int currentSegment(float[] coords); - public int currentSegment(double[] coords); - } diff --git a/src/jogamp/graph/math/plane/Crossing.java b/src/jogamp/graph/math/plane/Crossing.java index 7da1c466e..5620da73a 100644 --- a/src/jogamp/graph/math/plane/Crossing.java +++ b/src/jogamp/graph/math/plane/Crossing.java @@ -17,22 +17,24 @@ /** * @author Denis M. Kishenko */ -package org.apache.harmony.awt.gl; +package jogamp.graph.math.plane; -import java.awt.Shape; -import java.awt.geom.PathIterator; +import jogamp.graph.math.MathFloat; + +import com.jogamp.graph.geom.plane.Path2D; +import com.jogamp.graph.geom.plane.PathIterator; public class Crossing { /** * Allowable tolerance for bounds comparison */ - static final double DELTA = 1E-5; + static final float DELTA = (float) 1E-5; /** * If roots have distance less then ROOT_DELTA they are double */ - static final double ROOT_DELTA = 1E-10; + static final float ROOT_DELTA = (float) 1E-10; /** * Rectangle cross segment @@ -50,10 +52,10 @@ public class Crossing { * @param res - the roots of the equation * @return a number of roots */ - public static int solveQuad(double eqn[], double res[]) { - double a = eqn[2]; - double b = eqn[1]; - double c = eqn[0]; + public static int solveQuad(float eqn[], float res[]) { + float a = eqn[2]; + float b = eqn[1]; + float c = eqn[0]; int rc = 0; if (a == 0.0) { if (b == 0.0) { @@ -61,16 +63,16 @@ public class Crossing { } res[rc++] = -c / b; } else { - double d = b * b - 4.0 * a * c; + float d = b * b - 4.0f * a * c; // d < 0.0 if (d < 0.0) { return 0; } - d = Math.sqrt(d); - res[rc++] = (- b + d) / (a * 2.0); + d = MathFloat.sqrt(d); + res[rc++] = (- b + d) / (a * 2.0f); // d != 0.0 if (d != 0.0) { - res[rc++] = (- b - d) / (a * 2.0); + res[rc++] = (- b - d) / (a * 2.0f); } } return fixRoots(res, rc); @@ -82,32 +84,32 @@ public class Crossing { * @param res - the roots of the equation * @return a number of roots */ - public static int solveCubic(double eqn[], double res[]) { - double d = eqn[3]; + public static int solveCubic(float eqn[], float res[]) { + float d = eqn[3]; if (d == 0) { return solveQuad(eqn, res); } - double a = eqn[2] / d; - double b = eqn[1] / d; - double c = eqn[0] / d; + float a = eqn[2] / d; + float b = eqn[1] / d; + float c = eqn[0] / d; int rc = 0; - double Q = (a * a - 3.0 * b) / 9.0; - double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0; - double Q3 = Q * Q * Q; - double R2 = R * R; - double n = - a / 3.0; + float Q = (a * a - 3.0f * b) / 9.0f; + float R = (2.0f * a * a * a - 9.0f * a * b + 27.0f * c) / 54.0f; + float Q3 = Q * Q * Q; + float R2 = R * R; + float n = - a / 3.0f; if (R2 < Q3) { - double t = Math.acos(R / Math.sqrt(Q3)) / 3.0; - double p = 2.0 * Math.PI / 3.0; - double m = -2.0 * Math.sqrt(Q); - res[rc++] = m * Math.cos(t) + n; - res[rc++] = m * Math.cos(t + p) + n; - res[rc++] = m * Math.cos(t - p) + n; + float t = MathFloat.acos(R / MathFloat.sqrt(Q3)) / 3.0f; + float p = 2.0f * MathFloat.PI / 3.0f; + float m = -2.0f * MathFloat.sqrt(Q); + res[rc++] = m * MathFloat.cos(t) + n; + res[rc++] = m * MathFloat.cos(t + p) + n; + res[rc++] = m * MathFloat.cos(t - p) + n; } else { // Debug.println("R2 >= Q3 (" + R2 + "/" + Q3 + ")"); - double A = Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0); + float A = MathFloat.pow(MathFloat.abs(R) + MathFloat.sqrt(R2 - Q3), 1.0f / 3.0f); if (R > 0.0) { A = -A; } @@ -115,12 +117,12 @@ public class Crossing { if (-ROOT_DELTA < A && A < ROOT_DELTA) { res[rc++] = n; } else { - double B = Q / A; + float B = Q / A; res[rc++] = A + B + n; // if (R2 == Q3) { - double delta = R2 - Q3; + float delta = R2 - Q3; if (-ROOT_DELTA < delta && delta < ROOT_DELTA) { - res[rc++] = - (A + B) / 2.0 + n; + res[rc++] = - (A + B) / 2.0f + n; } } @@ -129,12 +131,12 @@ public class Crossing { } /** - * Excludes double roots. Roots are double if they lies enough close with each other. + * Excludes float roots. Roots are float if they lies enough close with each other. * @param res - the roots * @param rc - the roots count * @return new roots count */ - static int fixRoots(double res[], int rc) { + static int fixRoots(float res[], int rc) { int tc = 0; for(int i = 0; i < rc; i++) { out: { @@ -154,10 +156,10 @@ public class Crossing { */ public static class QuadCurve { - double ax, ay, bx, by; - double Ax, Ay, Bx, By; + float ax, ay, bx, by; + float Ax, Ay, Bx, By; - public QuadCurve(double x1, double y1, double cx, double cy, double x2, double y2) { + public QuadCurve(float x1, float y1, float cx, float cy, float x2, float y2) { ax = x2 - x1; ay = y2 - y1; bx = cx - x1; @@ -170,11 +172,11 @@ public class Crossing { Ay = ay - By; // Ay = ay - 2.0 * by } - int cross(double res[], int rc, double py1, double py2) { + int cross(float res[], int rc, float py1, float py2) { int cross = 0; for (int i = 0; i < rc; i++) { - double t = res[i]; + float t = res[i]; // CURVE-OUTSIDE if (t < -DELTA || t > 1 + DELTA) { @@ -195,10 +197,10 @@ public class Crossing { continue; } // CURVE-INSIDE - double ry = t * (t * Ay + By); + float ry = t * (t * Ay + By); // ry = t * t * Ay + t * By if (ry > py2) { - double rxt = t * Ax + bx; + float rxt = t * Ax + bx; // rxt = 2.0 * t * Ax + Bx = 2.0 * t * Ax + 2.0 * bx if (rxt > -DELTA && rxt < DELTA) { continue; @@ -210,12 +212,12 @@ public class Crossing { return cross; } - int solvePoint(double res[], double px) { - double eqn[] = {-px, Bx, Ax}; + int solvePoint(float res[], float px) { + float eqn[] = {-px, Bx, Ax}; return solveQuad(eqn, res); } - int solveExtrem(double res[]) { + int solveExtrem(float res[]) { int rc = 0; if (Ax != 0.0) { res[rc++] = - Bx / (Ax + Ax); @@ -226,11 +228,11 @@ public class Crossing { return rc; } - int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) { + int addBound(float bound[], int bc, float res[], int rc, float minX, float maxX, boolean changeId, int id) { for(int i = 0; i < rc; i++) { - double t = res[i]; + float t = res[i]; if (t > -DELTA && t < 1 + DELTA) { - double rx = t * (t * Ax + Bx); + float rx = t * (t * Ax + Bx); if (minX <= rx && rx <= maxX) { bound[bc++] = t; bound[bc++] = rx; @@ -252,11 +254,11 @@ public class Crossing { */ public static class CubicCurve { - double ax, ay, bx, by, cx, cy; - double Ax, Ay, Bx, By, Cx, Cy; - double Ax3, Bx2; + float ax, ay, bx, by, cx, cy; + float Ax, Ay, Bx, By, Cx, Cy; + float Ax3, Bx2; - public CubicCurve(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2) { + public CubicCurve(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2) { ax = x2 - x1; ay = y2 - y1; bx = cx1 - x1; @@ -276,10 +278,10 @@ public class Crossing { Bx2 = Bx + Bx; } - int cross(double res[], int rc, double py1, double py2) { + int cross(float res[], int rc, float py1, float py2) { int cross = 0; for (int i = 0; i < rc; i++) { - double t = res[i]; + float t = res[i]; // CURVE-OUTSIDE if (t < -DELTA || t > 1 + DELTA) { @@ -300,10 +302,10 @@ public class Crossing { continue; } // CURVE-INSIDE - double ry = t * (t * (t * Ay + By) + Cy); + float ry = t * (t * (t * Ay + By) + Cy); // ry = t * t * t * Ay + t * t * By + t * Cy if (ry > py2) { - double rxt = t * (t * Ax3 + Bx2) + Cx; + float rxt = t * (t * Ax3 + Bx2) + Cx; // rxt = 3.0 * t * t * Ax + 2.0 * t * Bx + Cx if (rxt > -DELTA && rxt < DELTA) { rxt = t * (Ax3 + Ax3) + Bx2; @@ -321,26 +323,26 @@ public class Crossing { return cross; } - int solvePoint(double res[], double px) { - double eqn[] = {-px, Cx, Bx, Ax}; + int solvePoint(float res[], float px) { + float eqn[] = {-px, Cx, Bx, Ax}; return solveCubic(eqn, res); } - int solveExtremX(double res[]) { - double eqn[] = {Cx, Bx2, Ax3}; + int solveExtremX(float res[]) { + float eqn[] = {Cx, Bx2, Ax3}; return solveQuad(eqn, res); } - int solveExtremY(double res[]) { - double eqn[] = {Cy, By + By, Ay + Ay + Ay}; + int solveExtremY(float res[]) { + float eqn[] = {Cy, By + By, Ay + Ay + Ay}; return solveQuad(eqn, res); } - int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) { + int addBound(float bound[], int bc, float res[], int rc, float minX, float maxX, boolean changeId, int id) { for(int i = 0; i < rc; i++) { - double t = res[i]; + float t = res[i]; if (t > -DELTA && t < 1 + DELTA) { - double rx = t * (t * (t * Ax + Bx) + Cx); + float rx = t * (t * (t * Ax + Bx) + Cx); if (minX <= rx && rx <= maxX) { bound[bc++] = t; bound[bc++] = rx; @@ -360,7 +362,7 @@ public class Crossing { /** * Returns how many times ray from point (x,y) cross line. */ - public static int crossLine(double x1, double y1, double x2, double y2, double x, double y) { + public static int crossLine(float x1, float y1, float x2, float y2, float x, float y) { // LEFT/RIGHT/UP/EMPTY if ((x < x1 && x < x2) || @@ -398,7 +400,7 @@ public class Crossing { /** * Returns how many times ray from point (x,y) cross quard curve */ - public static int crossQuad(double x1, double y1, double cx, double cy, double x2, double y2, double x, double y) { + public static int crossQuad(float x1, float y1, float cx, float cy, float x2, float y2, float x, float y) { // LEFT/RIGHT/UP/EMPTY if ((x < x1 && x < cx && x < x2) || @@ -419,9 +421,9 @@ public class Crossing { // INSIDE QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2); - double px = x - x1; - double py = y - y1; - double res[] = new double[3]; + float px = x - x1; + float py = y - y1; + float res[] = new float[3]; int rc = c.solvePoint(res, px); return c.cross(res, rc, py, py); @@ -430,7 +432,7 @@ public class Crossing { /** * Returns how many times ray from point (x,y) cross cubic curve */ - public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y) { + public static int crossCubic(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, float x, float y) { // LEFT/RIGHT/UP/EMPTY if ((x < x1 && x < cx1 && x < cx2 && x < x2) || @@ -451,9 +453,9 @@ public class Crossing { // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); - double px = x - x1; - double py = y - y1; - double res[] = new double[3]; + float px = x - x1; + float py = y - y1; + float res[] = new float[3]; int rc = c.solvePoint(res, px); return c.cross(res, rc, py, py); } @@ -461,11 +463,11 @@ public class Crossing { /** * Returns how many times ray from point (x,y) cross path */ - public static int crossPath(PathIterator p, double x, double y) { + public static int crossPath(PathIterator p, float x, float y) { int cross = 0; - double mx, my, cx, cy; - mx = my = cx = cy = 0.0; - double coords[] = new double[6]; + float mx, my, cx, cy; + mx = my = cx = cy = 0.0f; + float coords[] = new float[6]; while (!p.isDone()) { switch (p.currentSegment(coords)) { @@ -509,24 +511,24 @@ public class Crossing { /** * Returns how many times ray from point (x,y) cross shape */ - public static int crossShape(Shape s, double x, double y) { + public static int crossShape(Path2D s, float x, float y) { if (!s.getBounds2D().contains(x, y)) { return 0; } - return crossPath(s.getPathIterator(null), x, y); + return crossPath(s.iterator(null), x, y); } /** * Returns true if value enough small */ - public static boolean isZero(double val) { + public static boolean isZero(float val) { return -DELTA < val && val < DELTA; } /** * Sort bound array */ - static void sortBound(double bound[], int bc) { + static void sortBound(float bound[], int bc) { for(int i = 0; i < bc - 4; i += 4) { int k = i; for(int j = i + 4; j < bc; j += 4) { @@ -535,7 +537,7 @@ public class Crossing { } } if (k != i) { - double tmp = bound[i]; + float tmp = bound[i]; bound[i] = bound[k]; bound[k] = tmp; tmp = bound[i + 1]; @@ -554,7 +556,7 @@ public class Crossing { /** * Returns are bounds intersect or not intersect rectangle */ - static int crossBound(double bound[], int bc, double py1, double py2) { + static int crossBound(float bound[], int bc, float py1, float py2) { // LEFT/RIGHT if (bc == 0) { @@ -599,7 +601,7 @@ public class Crossing { /** * Returns how many times rectangle stripe cross line or the are intersect */ - public static int intersectLine(double x1, double y1, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + public static int intersectLine(float x1, float y1, float x2, float y2, float rx1, float ry1, float rx2, float ry2) { // LEFT/RIGHT/UP if ((rx2 < x1 && rx2 < x2) || @@ -619,7 +621,7 @@ public class Crossing { } // Build bound - double bx1, bx2; + float bx1, bx2; if (x1 < x2) { bx1 = x1 < rx1 ? rx1 : x1; bx2 = x2 < rx2 ? x2 : rx2; @@ -627,9 +629,9 @@ public class Crossing { bx1 = x2 < rx1 ? rx1 : x2; bx2 = x1 < rx2 ? x1 : rx2; } - double k = (y2 - y1) / (x2 - x1); - double by1 = k * (bx1 - x1) + y1; - double by2 = k * (bx2 - x1) + y1; + float k = (y2 - y1) / (x2 - x1); + float by1 = k * (bx1 - x1) + y1; + float by2 = k * (bx2 - x1) + y1; // BOUND-UP if (by1 < ry1 && by2 < ry1) { @@ -668,7 +670,7 @@ public class Crossing { /** * Returns how many times rectangle stripe cross quad curve or the are intersect */ - public static int intersectQuad(double x1, double y1, double cx, double cy, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + public static int intersectQuad(float x1, float y1, float cx, float cy, float x2, float y2, float rx1, float ry1, float rx2, float ry2) { // LEFT/RIGHT/UP ------------------------------------------------------ if ((rx2 < x1 && rx2 < cx && rx2 < x2) || @@ -688,13 +690,13 @@ public class Crossing { // INSIDE ------------------------------------------------------------- QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2); - double px1 = rx1 - x1; - double py1 = ry1 - y1; - double px2 = rx2 - x1; - double py2 = ry2 - y1; + float px1 = rx1 - x1; + float py1 = ry1 - y1; + float px2 = rx2 - x1; + float py2 = ry2 - y1; - double res1[] = new double[3]; - double res2[] = new double[3]; + float res1[] = new float[3]; + float res2[] = new float[3]; int rc1 = c.solvePoint(res1, px1); int rc2 = c.solvePoint(res2, px2); @@ -704,9 +706,9 @@ public class Crossing { } // Build bound -------------------------------------------------------- - double minX = px1 - DELTA; - double maxX = px2 + DELTA; - double bound[] = new double[28]; + float minX = px1 - DELTA; + float maxX = px2 + DELTA; + float bound[] = new float[28]; int bc = 0; // Add roots bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); @@ -716,13 +718,13 @@ public class Crossing { bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2); // Add start and end if (rx1 < x1 && x1 < rx2) { - bound[bc++] = 0.0; - bound[bc++] = 0.0; - bound[bc++] = 0.0; + bound[bc++] = 0.0f; + bound[bc++] = 0.0f; + bound[bc++] = 0.0f; bound[bc++] = 4; } if (rx1 < x2 && x2 < rx2) { - bound[bc++] = 1.0; + bound[bc++] = 1.0f; bound[bc++] = c.ax; bound[bc++] = c.ay; bound[bc++] = 5; @@ -739,7 +741,7 @@ public class Crossing { /** * Returns how many times rectangle stripe cross cubic curve or the are intersect */ - public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2) { + public static int intersectCubic(float x1, float y1, float cx1, float cy1, float cx2, float cy2, float x2, float y2, float rx1, float ry1, float rx2, float ry2) { // LEFT/RIGHT/UP if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) || @@ -759,13 +761,13 @@ public class Crossing { // INSIDE CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2); - double px1 = rx1 - x1; - double py1 = ry1 - y1; - double px2 = rx2 - x1; - double py2 = ry2 - y1; + float px1 = rx1 - x1; + float py1 = ry1 - y1; + float px2 = rx2 - x1; + float py2 = ry2 - y1; - double res1[] = new double[3]; - double res2[] = new double[3]; + float res1[] = new float[3]; + float res2[] = new float[3]; int rc1 = c.solvePoint(res1, px1); int rc2 = c.solvePoint(res2, px2); @@ -774,11 +776,11 @@ public class Crossing { return 0; } - double minX = px1 - DELTA; - double maxX = px2 + DELTA; + float minX = px1 - DELTA; + float maxX = px2 + DELTA; // Build bound -------------------------------------------------------- - double bound[] = new double[40]; + float bound[] = new float[40]; int bc = 0; // Add roots bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0); @@ -790,13 +792,13 @@ public class Crossing { bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4); // Add start and end if (rx1 < x1 && x1 < rx2) { - bound[bc++] = 0.0; - bound[bc++] = 0.0; - bound[bc++] = 0.0; + bound[bc++] = 0.0f; + bound[bc++] = 0.0f; + bound[bc++] = 0.0f; bound[bc++] = 6; } if (rx1 < x2 && x2 < rx2) { - bound[bc++] = 1.0; + bound[bc++] = 1.0f; bound[bc++] = c.ax; bound[bc++] = c.ay; bound[bc++] = 7; @@ -813,18 +815,18 @@ public class Crossing { /** * Returns how many times rectangle stripe cross path or the are intersect */ - public static int intersectPath(PathIterator p, double x, double y, double w, double h) { + public static int intersectPath(PathIterator p, float x, float y, float w, float h) { int cross = 0; int count; - double mx, my, cx, cy; - mx = my = cx = cy = 0.0; - double coords[] = new double[6]; + float mx, my, cx, cy; + mx = my = cx = cy = 0.0f; + float coords[] = new float[6]; - double rx1 = x; - double ry1 = y; - double rx2 = x + w; - double ry2 = y + h; + float rx1 = x; + float ry1 = y; + float rx2 = x + w; + float ry2 = y + h; while (!p.isDone()) { count = 0; @@ -872,11 +874,11 @@ public class Crossing { /** * Returns how many times rectangle stripe cross shape or the are intersect */ - public static int intersectShape(Shape s, double x, double y, double w, double h) { + public static int intersectShape(Path2D s, float x, float y, float w, float h) { if (!s.getBounds2D().intersects(x, y, w, h)) { return 0; } - return intersectPath(s.getPathIterator(null), x, y, w, h); + return intersectPath(s.iterator(null), x, y, w, h); } /** @@ -892,4 +894,4 @@ public class Crossing { public static boolean isInsideEvenOdd(int cross) { return (cross & 1) != 0; } -} \ No newline at end of file +} -- cgit v1.2.3 From 49379f06ceefeaa795af05b1c890047176fe19ef Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 03:48:01 +0100 Subject: Add generic Font and impl TypecastFont. --- src/com/jogamp/graph/font/Font.java | 82 +++++++ src/com/jogamp/graph/font/FontFactory.java | 45 ++++ src/jogamp/graph/font/JavaFontLoader.java | 111 +++++++++ src/jogamp/graph/font/typecast/TypecastFont.java | 178 ++++++++++++++ .../graph/font/typecast/TypecastFontFactory.java | 65 +++++ src/jogamp/graph/font/typecast/TypecastGlyph.java | 269 +++++++++++++++++++++ .../graph/font/typecast/TypecastMetrics.java | 87 +++++++ .../graph/font/typecast/TypecastRenderer.java | 162 +++++++++++++ 8 files changed, 999 insertions(+) create mode 100644 src/com/jogamp/graph/font/Font.java create mode 100644 src/com/jogamp/graph/font/FontFactory.java create mode 100644 src/jogamp/graph/font/JavaFontLoader.java create mode 100644 src/jogamp/graph/font/typecast/TypecastFont.java create mode 100644 src/jogamp/graph/font/typecast/TypecastFontFactory.java create mode 100644 src/jogamp/graph/font/typecast/TypecastGlyph.java create mode 100644 src/jogamp/graph/font/typecast/TypecastMetrics.java create mode 100644 src/jogamp/graph/font/typecast/TypecastRenderer.java diff --git a/src/com/jogamp/graph/font/Font.java b/src/com/jogamp/graph/font/Font.java new file mode 100644 index 000000000..5c26e8626 --- /dev/null +++ b/src/com/jogamp/graph/font/Font.java @@ -0,0 +1,82 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.font; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.geom.plane.Path2D; + +public interface Font { + + /** + * Metrics for font based on pixel size ! + * + * If no pixelSize is given, this font's static pixelSize is being used. + * + * value = Table.value * fontSize * 1.0f / HeadTable.UnitsPerEm + */ + public interface Metrics { + public float getAscent(); + public float getDescent(); + public float getLineGap(); + public float getScale(); + public float getScaleForPixelSize(float pixelSize); + public AABBox getBBox(); + } + + /** + * Glyph for font symbols based on pixel size ! + * + * If no pixelSize is given, this font's static pixelSize is being used. + */ + public interface Glyph { + public Font getFont(); + public char getSymbol(); + public AABBox getBBox(); + public float getAdvance(); + public float getAdvanceForPixelSize(float pixelSize, boolean useFrationalMetrics); + public Path2D getPath(); + public Path2D getPathForPixelSize(float pixelSize); + } + + + public String getName(); + public float getSize(); + public Metrics getMetrics(); + public Glyph getGlyph(char symbol); + + public float getStringWidth(String string); + public float getStringHeight(String string); + public AABBox getStringBounds(CharSequence string); + + public void getOutline(String string, + AffineTransform transform, + Path2D[] result); + + public int getNumGlyphs(); +} \ No newline at end of file diff --git a/src/com/jogamp/graph/font/FontFactory.java b/src/com/jogamp/graph/font/FontFactory.java new file mode 100644 index 000000000..d10e1c38b --- /dev/null +++ b/src/com/jogamp/graph/font/FontFactory.java @@ -0,0 +1,45 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.font; + +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; + +public interface FontFactory { + + Font createFont(Point.Factory factory, + String[] families, + String style, + String variant, + String weight, + String size); + + Font createFont(Point.Factory factory, + String name, + int size); +} \ No newline at end of file diff --git a/src/jogamp/graph/font/JavaFontLoader.java b/src/jogamp/graph/font/JavaFontLoader.java new file mode 100644 index 000000000..f6954944d --- /dev/null +++ b/src/jogamp/graph/font/JavaFontLoader.java @@ -0,0 +1,111 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font; + +public class JavaFontLoader { + + static String javaFontPath; + static + { + javaFontPath = System.getProperty("java.home") + "/lib/fonts/"; + } + + public static final int MAX_BITMAP_FONT_SIZE = 120; + + public static final int MONOSPACED = 1; + public static final int SERIF = 2; + public static final int SANSERIF = 3; + public static final int CURSIVE = 4; + public static final int FANTASY = 5; + + final static String availableJavaFontNames[] = + { + "Lucida Bright Regular", + "Lucida Bright Italic", + "Lucida Bright Demibold", + "Lucida Bright Demibold Italic", + "Lucida Sans Regular", + "Lucida Sans Demibold", + "Lucida Sans Typewriter Regular", + "Lucida Sans Typewriter Bold", + }; + static public String[] getAvailableNames() + { + return availableJavaFontNames; + } + + final static String availableJavaFontFileNames[] = + { + "LucidaBrightRegular.ttf", + "LucidaBrightItalic.ttf", + "LucidaBrightDemiBold.ttf", + "LucidaBrightDemiItalic.ttf", + "LucidaSansRegular.ttf", + "LucidaSansDemiBold.ttf", + "LucidaTypewriterRegular.ttf", + "LucidaTypewriterBold.ttf", + }; + + static public String get(int type) + { + String font = null; + + switch (type) + { + case MONOSPACED: + font = getByName("Lucida Sans Typewriter Regular"); + break; + case SERIF: + font = getByName("Lucida Bright Regular"); + break; + case SANSERIF: + font = getByName("Lucida Sans Regular"); + break; + case CURSIVE: + font = getByName("Lucida Bright Regular"); + break; + case FANTASY: + font = getByName("Lucida Sans Regular"); + break; + } + + return font; + } + + static public String getByName(String name) + { + for (int i=0; i pointFactory; + final OTFontCollection fontset; + final OTFont font; + final int size; + Metrics metrics; + final CmapFormat cmapFormat; + int cmapentries; + // final IntIntHashMap char2Code; + IntObjectHashMap char2Glyph; + + public static TypecastFont create(Point.Factory factory, String name, int size) { + String path = JavaFontLoader.getByName(name); + OTFontCollection fontset; + try { + fontset = OTFontCollection.create(new File(path)); + return new TypecastFont(factory, fontset, size); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public TypecastFont(Point.Factory factory, OTFontCollection fontset, int size) { + this.pointFactory = factory; + this.fontset = fontset; + this.font = fontset.getFont(0); + this.size = size; + + CmapTable cmapTable = font.getCmapTable(); + CmapFormat _cmapFormat = null; + /* + if(null == _cmapFormat) { + _cmapFormat = cmapTable.getCmapFormat(ID.platformMacintosh, ID.encodingASCII); + } */ + if(null == _cmapFormat) { + // default unicode + _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingUnicode); + } + if(null == _cmapFormat) { + // maybe a symbol font ? + _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingSymbol); + } + if(null == _cmapFormat) { + throw new RuntimeException("Cannot find a suitable cmap table for font "+font); + } + cmapFormat = _cmapFormat; + + cmapentries = 0; + for (int i = 0; i < cmapFormat.getRangeCount(); ++i) { + CmapFormat.Range range = cmapFormat.getRange(i); + cmapentries += range.getEndCode() - range.getStartCode() + 1; // end included + } + if(DEBUG) { + System.err.println("num glyphs: "+font.getNumGlyphs()); + System.err.println("num cmap entries: "+cmapentries); + } + + /* + char2Code = new IntIntHashMap(cmapentries + cmapentries/4); + for (int i = 0; i < cmapFormat.getRangeCount(); ++i) { + CmapFormat.Range range = cmapFormat.getRange(i); + for (int j = range.getStartCode(); j <= range.getEndCode(); ++j) { + final int code = cmapFormat.mapCharCode(j); + char2Code.put(j, code); + if(code < 50) { + System.err.println(" char: " + (int)j + " ( " + (char)j +" ) -> " + code); + } + } + } + */ + char2Glyph = new IntObjectHashMap(cmapentries + cmapentries/4); + } + + public String getName() { + return fontset.getFileName(); + } + + public float getSize() { + return size; + } + + public Metrics getMetrics() { + if (metrics == null) { + metrics = new TypecastMetrics(this); + } + return metrics; + } + + public Glyph getGlyph(char symbol) { + TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol); + if (null == result) { + // final short code = (short) char2Code.get(symbol); + final short code = (short) cmapFormat.mapCharCode(symbol); + net.java.dev.typecast.ot.OTGlyph glyph = font.getGlyph(code); + final Path2D path = TypecastRenderer.buildPath(glyph); + result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), path); + if(DEBUG) { + System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path); + } + char2Glyph.put(symbol, result); + } + return result; + } + + public void getOutline(String string, AffineTransform transform, Path2D[] result) { + TypecastRenderer.getOutline(pointFactory, this, string, transform, result); + } + + public float getStringWidth(String string) { + // return 0f; // FIXME font.getStringWidthForPixelSize(string, size); + throw new RuntimeException("n/a"); + } + + public float getStringHeight(String string) { + // return 0f; // FIXME font.getStringHeightForPixelSize(string, size); + throw new RuntimeException("n/a"); + } + + public AABBox getStringBounds(CharSequence string) { + // return null; // FIXME font.getStringBoundsForPixelSize(string, size); + throw new RuntimeException("n/a"); + } + + final public int getNumGlyphs() { + return font.getNumGlyphs(); + } +} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java new file mode 100644 index 000000000..f66772029 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastFontFactory.java @@ -0,0 +1,65 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import java.util.HashMap; +import java.util.Map; + +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.Point.Factory; +import com.jogamp.graph.geom.PointTex; + + +public class TypecastFontFactory implements FontFactory { + + Map fonts = new HashMap(); + + public Font createFont(Factory factory, String name, int size) { + Font result = fonts.get(name + ":"+size); + if (result == null) { + result = TypecastFont.create(factory, name, size); + if(result != null) { + fonts.put(name+":"+size, result); + } + } + return result; + } + + + public Font createFont(Factory factory, + String[] families, + String style, + String variant, + String weight, + String size) { + throw new Error("not implemented"); + } + + +} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogamp/graph/font/typecast/TypecastGlyph.java new file mode 100644 index 000000000..faca8c779 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastGlyph.java @@ -0,0 +1,269 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.geom.plane.Path2D; + +public class TypecastGlyph implements Font.Glyph { + public class Advance + { + Font font; + float advance; + float advances[]; // in pixels + float sizes[]; + float advanceCached = -1; // in pixels + float sizeCached = -1; + + public Advance(Font font, float advance) + { + this.font = font; + this.advance = advance; + + this.advances = new float[0]; + this.sizes = new float[0]; + } + + public float getScaleForPixelSize(float pixelSize) + { + return this.font.getMetrics().getScaleForPixelSize(pixelSize); + } + + public void add(float advance, float size) + { + float advancesNew[] = new float[this.advances.length+1]; + float sizesNew[] = new float[this.sizes.length+1]; + + for (int i=0; i 0) { + string = "\n advances: \n"+string; + } + return "\nAdvance:"+ + "\n advance: "+this.advance+ + string; + } + } + + public class Metrics + { + AABBox bbox; + AABBox bbox_sized; + Advance advance; + + public Metrics(Font font, AABBox bbox, float advance) + { + this.bbox = bbox; + this.advance = new Advance(font, advance); + } + + public float getScaleForPixelSize(float pixelSize) + { + return this.advance.getScaleForPixelSize(pixelSize); + } + + public AABBox getBBox() + { + return this.bbox; + } + + public void addAdvance(float advance, float size) + { + this.advance.add(advance, size); + } + + public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) + { + return this.advance.get(size, useFrationalMetrics); + } + + public String toString() + { + return "\nMetrics:"+ + "\n bbox: "+this.bbox+ + this.advance; + } + } + + public static final short INVALID_ID = (short)((1 << 16) - 1); + public static final short MAX_ID = (short)((1 << 16) - 2); + + private final Font font; + + char symbol; + short id; + int advance; + Metrics metrics; + + protected Path2D path; // in EM units + protected Path2D pathSized; + protected float numberSized; + + protected TypecastGlyph(Font font, char symbol) { + this.font = font; + this.symbol = symbol; + } + + protected TypecastGlyph(Font font, + char symbol, short id, AABBox bbox, int advance, Path2D path) { + this.font = font; + this.symbol = symbol; + this.advance = advance; + + init(id, bbox, advance); + + this.path = path; + this.pathSized = null; + this.numberSized = 0.0f; + } + + void init(short id, AABBox bbox, int advance) { + this.id = id; + this.advance = advance; + this.metrics = new Metrics(this.font, bbox, this.advance); + } + + public Font getFont() { + return this.font; + } + + public char getSymbol() { + return this.symbol; + } + + AABBox getBBoxUnsized() { + return this.metrics.getBBox(); + } + + public AABBox getBBox() { + return this.metrics.getBBox(); + } + + public Metrics getMetrics() { + return this.metrics; + } + + public short getID() { + return this.id; + } + + public float getScaleForPixelSize(float pixelSize) { + return this.metrics.getScaleForPixelSize(pixelSize); + } + + public AABBox getBBox(float size) { + AABBox newBox = getBBox().clone(); + newBox.scale(size); + return newBox; + } + + public AABBox getBBoxForPixelSize(float pixelSize) { + return getBBox(getScaleForPixelSize(pixelSize)); + } + + protected void addAdvance(float advance, float size) { + this.metrics.addAdvance(advance, size); + } + + public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) { + return this.metrics.getAdvanceForPixelSize(size, useFrationalMetrics); + } + + public float getAdvance() { + return getAdvanceForPixelSize(font.getSize(), false); + } + + public Path2D getPath() { + return getPath(getScaleForPixelSize(font.getSize())); + } + + private Path2D getPath(float size) + { + if (this.numberSized != size) { + this.numberSized = size; + this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath()); + } + return this.pathSized; + } + + public Path2D getPathForPixelSize(float pixelSize) { + return getPath(getScaleForPixelSize(pixelSize)); + } + + public Path2D getNormalPath() { + return this.path; + } + +} diff --git a/src/jogamp/graph/font/typecast/TypecastMetrics.java b/src/jogamp/graph/font/typecast/TypecastMetrics.java new file mode 100644 index 000000000..541ed90d8 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastMetrics.java @@ -0,0 +1,87 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import net.java.dev.typecast.ot.table.HeadTable; +import net.java.dev.typecast.ot.table.HheaTable; + +import com.jogamp.graph.font.Font.Metrics; +import com.jogamp.graph.geom.AABBox; + +class TypecastMetrics implements Metrics { + private final TypecastFont fontImpl; + + // HeadTable + private final float unitsPerEM_Inv; + private final float unitsPerEM_Inv_sized; + private final AABBox bbox_sized; + + // HheaTable + private final float ascend_sized; + private final float descent_sized; + private final float linegap_sized; + + public TypecastMetrics(TypecastFont fontImpl) { + this.fontImpl = fontImpl; + final HeadTable headTable = this.fontImpl.font.getHeadTable(); + unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() ); + unitsPerEM_Inv_sized = this.fontImpl.size * unitsPerEM_Inv; + int maxWidth = headTable.getXMax() - headTable.getXMin(); + int maxHeight = headTable.getYMax() - headTable.getYMin(); + float lowx= headTable.getXMin(); + float lowy = -(headTable.getYMin()+maxHeight); + float highx = lowx + maxWidth; + float highy = lowy + maxHeight; + bbox_sized = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert + bbox_sized.scale(unitsPerEM_Inv_sized); + + final HheaTable hheaTable = this.fontImpl.font.getHheaTable(); + ascend_sized = unitsPerEM_Inv_sized * -hheaTable.getAscender(); // invert + descent_sized = unitsPerEM_Inv_sized * -hheaTable.getDescender(); // invert + linegap_sized = unitsPerEM_Inv_sized * -hheaTable.getLineGap(); // invert + } + + public final float getAscent() { + return ascend_sized; + } + public final float getDescent() { + return descent_sized; + } + public final float getLineGap() { + return linegap_sized; + } + public final float getScale() { + return unitsPerEM_Inv_sized; + } + public float getScaleForPixelSize(float pixelSize) { + return pixelSize * unitsPerEM_Inv; + } + public final AABBox getBBox() { + return bbox_sized; + } +} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java new file mode 100644 index 000000000..7b36d22b5 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java @@ -0,0 +1,162 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.geom.plane.Path2D; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Point.Factory; + +import net.java.dev.typecast.ot.Point; +import net.java.dev.typecast.ot.OTGlyph; + +/** + * Factory to build a {@link com.jogamp.graph.geom.Path2D Path2D} from + * {@link net.java.dev.typecast.ot.OTGlyph Glyph}s. + */ +public class TypecastRenderer { + + public static void getOutline(Factory factory, TypecastFont font, + String string, AffineTransform transform, Path2D[] p) + { + if (string == null) { + return; + } + Font.Metrics metrics = font.getMetrics(); + float advanceTotal = 0; + float lineGap = metrics.getLineGap() ; + float ascent = metrics.getAscent() ; + float descent = metrics.getDescent() ; + if (transform == null) { + transform = new AffineTransform(factory); + } + AffineTransform t = new AffineTransform(factory); + + float advanceY = lineGap - descent + ascent; + float y = 0; + for (int i=0; i Date: Fri, 25 Mar 2011 03:55:20 +0100 Subject: Add com.jogamp.graph.geom types --- src/com/jogamp/graph/geom/AABBox.java | 244 +++++++++++++++++++++++++++ src/com/jogamp/graph/geom/Line.java | 61 +++++++ src/com/jogamp/graph/geom/Outline.java | 150 ++++++++++++++++ src/com/jogamp/graph/geom/Point.java | 78 +++++++++ src/com/jogamp/graph/geom/PointTex.java | 37 ++++ src/com/jogamp/graph/geom/Triangle.java | 79 +++++++++ src/com/jogamp/graph/geom/opengl/Vertex.java | 180 ++++++++++++++++++++ src/jogamp/graph/math/MathFloat.java | 45 +++++ 8 files changed, 874 insertions(+) create mode 100644 src/com/jogamp/graph/geom/AABBox.java create mode 100644 src/com/jogamp/graph/geom/Line.java create mode 100644 src/com/jogamp/graph/geom/Outline.java create mode 100644 src/com/jogamp/graph/geom/Point.java create mode 100644 src/com/jogamp/graph/geom/PointTex.java create mode 100644 src/com/jogamp/graph/geom/Triangle.java create mode 100644 src/com/jogamp/graph/geom/opengl/Vertex.java create mode 100644 src/jogamp/graph/math/MathFloat.java diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java new file mode 100644 index 000000000..9199e5253 --- /dev/null +++ b/src/com/jogamp/graph/geom/AABBox.java @@ -0,0 +1,244 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +import jogamp.graph.math.VectorFloatUtil; + +/** + * Axis Aligned Bounding Box. + */ +public class AABBox { + private float[] low = {Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE}; + private float[] high = {-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE}; + private float[] center = new float[3]; + + public AABBox() {} + + public AABBox(float lx, float ly, float lz, + float hx, float hy, float hz) + { + setLow(lx, ly, lz); + setHigh(hx, hy, hz); + + computeCenter(); + } + + + public AABBox(float[] low, float[] high) + { + this.low = low; + this.high = high; + + computeCenter(); + } + + public float[] getHigh() + { + return high; + } + public void setHigh(float hx, float hy, float hz) + { + this.high[0] = hx; + this.high[1] = hy; + this.high[2] = hz; + } + public float[] getLow() + { + return low; + } + public void setLow(float lx, float ly, float lz) + { + this.low[0] = lx; + this.low[1] = ly; + this.low[2] = lz; + } + + public void resize(AABBox newBox) + { + float[] newLow = newBox.getLow(); + float[] newHigh = newBox.getHigh(); + + /** test low */ + if (newLow[0] < low[0]) + low[0] = newLow[0]; + if (newLow[1] < low[1]) + low[1] = newLow[1]; + if (newLow[2] < low[2]) + low[2] = newLow[2]; + + /** test high */ + if (newHigh[0] > high[0]) + high[0] = newHigh[0]; + if (newHigh[1] > high[1]) + high[1] = newHigh[1]; + if (newHigh[2] > high[2]) + high[2] = newHigh[2]; + + computeCenter(); + } + + private void computeCenter() + { + center[0] = (high[0] + low[0])/2; + center[1] = (high[1] + low[1])/2; + center[2] = (high[2] + low[2])/2; + } + + public void resize(float x, float y, float z) + { + /** test low */ + if (x < low[0]) + low[0] = x; + if (y < low[1]) + low[1] = y; + if (z < low[2]) + low[2] = z; + + /** test high */ + if (x > high[0]) + high[0] = x; + if (y > high[1]) + high[1] = y; + if (z > high[2]) + high[2] = z; + + computeCenter(); + } + + public boolean contains(float x, float y){ + if(xhigh[0]){ + return false; + } + if(yhigh[1]){ + return false; + } + return true; + } + + public boolean contains(float x, float y, float z){ + if(xhigh[0]){ + return false; + } + if(yhigh[1]){ + return false; + } + if(zhigh[2]){ + return false; + } + return true; + } + + /** + * @return true if area is empty + */ + boolean isEmpty() { + return getWidth() <=0 || getHeight() <= 0 ; + } + + public boolean intersects(double x, double y, double w, double h) { + if (w <= 0 || h <= 0) { + return false; + } + + final float _w = getWidth(); + final float _h = getHeight(); + if (_w <= 0 || _h <= 0) { + return false; + } + + final float x0 = getX(); + final float y0 = getY(); + return (x + w > x0 && + y + h > y0 && + x < x0 + _w && + y < y0 + _h); + } + + + public float getSize(){ + return VectorFloatUtil.computeLength(low, high); + } + + public float[] getCenter() { + return center; + } + + public void setCenter(float[] center) { + this.center = center; + } + + public void setHigh(float[] high) { + this.high = high; + } + + public void setLow(float[] low) { + this.low = low; + } + + public void scale(float size) { + float[] diffH = new float[3]; + diffH[0] = high[0] - center[0]; + diffH[1] = high[1] - center[1]; + diffH[2] = high[2] - center[2]; + + diffH = VectorFloatUtil.scale(diffH, size); + + float[] diffL = new float[3]; + diffL[0] = low[0] - center[0]; + diffL[1] = low[1] - center[1]; + diffL[2] = low[2] - center[2]; + + diffL = VectorFloatUtil.scale(diffL, size); + + high = VectorFloatUtil.vectorAdd(center, diffH); + low = VectorFloatUtil.vectorAdd(center, diffL); + } + + public float getX() { + return low[0]; + } + + public float getY() { + return low[1]; + } + + public float getWidth(){ + return high[0] - low[0]; + } + + public float getHeight() { + return high[1] - low[1]; + } + + public float getDepth() { + return high[2] - low[2]; + } + public AABBox clone(){ + return new AABBox(this.low, this.high); + } +} diff --git a/src/com/jogamp/graph/geom/Line.java b/src/com/jogamp/graph/geom/Line.java new file mode 100644 index 000000000..dbdee569c --- /dev/null +++ b/src/com/jogamp/graph/geom/Line.java @@ -0,0 +1,61 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +public class Line { + private T v1; + private T v2; + + public Line(T v1, T v2) { + this.v1 = v1; + this.v2 = v2; + } + + public T getV1() { + return v1; + } + + public void setV1(T v1) { + this.v1 = v1; + } + + public T getV2() { + return v2; + } + + public void setV2(T v2) { + this.v2 = v2; + } + public boolean isEqual(T t1, T t2){ + if((t1 == v1 || t1 == v2) + &&(t2 == v2 || t2 == v1)){ + return true; + } + return false; + } +} diff --git a/src/com/jogamp/graph/geom/Outline.java b/src/com/jogamp/graph/geom/Outline.java new file mode 100644 index 000000000..b8b824a1c --- /dev/null +++ b/src/com/jogamp/graph/geom/Outline.java @@ -0,0 +1,150 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.Point; + +import jogamp.graph.math.VectorFloatUtil; + + +/** Define a single continuous stroke by control vertices. + * The vertices define the shape of the region defined by this + * outline. The Outline can contain a list of off-curve and on-curve + * vertices which define curved regions. + * + * Note: An outline should be closed to be rendered as a region. + * + * + * @see OutlineShape, Region + * + */ +public class Outline implements Comparable>{ + + private ArrayList vertices = new ArrayList(3); + private boolean closed = false; + private AABBox box = new AABBox(); + + /**Create an outline defined by control vertices. + * An outline can contain off Curve vertices which define curved + * regions in the outline. + */ + public Outline(){ + + } + + /** Add a vertex to the outline. The vertex is added at the + * end of the outline loop/strip. + * @param vertex Vertex to be added + */ + public final void addVertex(T vertex) { + vertices.add(vertex); + box.resize(vertex.getX(), vertex.getY(), vertex.getZ()); + } + + public final void addVertex(Point.Factory factory, float x, float y, boolean onCurve) { + addVertex(factory, x, y, 0f, onCurve); + } + + @SuppressWarnings("unchecked") + public final void addVertex(Point.Factory factory, float x, float y, float z, boolean onCurve) { + Point v = factory.create(x, y, z); + v.setOnCurve(onCurve); + addVertex((T)v); + } + + @SuppressWarnings("unchecked") + public final void addVertex(Point.Factory factory, float[] coordsBuffer, int offset, int length, boolean onCurve) { + Point v = factory.create(coordsBuffer, offset, length); + v.setOnCurve(onCurve); + addVertex((T)v); + } + + public T getVertex(int index){ + return vertices.get(index); + } + + public boolean isEmpty(){ + return (vertices.size() == 0); + } + public T getLastVertex(){ + if(isEmpty()){ + return null; + } + return vertices.get(vertices.size()-1); + } + + public ArrayList getVertices() { + return vertices; + } + public void setVertices(ArrayList vertices) { + this.vertices = vertices; + } + public AABBox getBox() { + return box; + } + public boolean isClosed() { + return closed; + } + + /** define if this outline is closed or not. + * if set to closed, checks if the last vertex is + * equal to the first vertex. If not Equal adds a + * vertex at the end to the list. + * @param closed + */ + public void setClosed(boolean closed) { + this.closed = closed; + if(closed){ + T first = vertices.get(0); + T last = getLastVertex(); + if(!VectorFloatUtil.checkEquality(first.getCoord(), last.getCoord())){ + @SuppressWarnings("unchecked") + T v = (T) first.clone(); + vertices.add(v); + } + } + } + + /** Compare two outlines with Bounding Box area + * as criteria. + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + public int compareTo(Outline outline) { + float size = box.getSize(); + float newSize = outline.getBox().getSize(); + if(size < newSize){ + return -1; + } + else if(size > newSize){ + return 1; + } + return 0; + } +} diff --git a/src/com/jogamp/graph/geom/Point.java b/src/com/jogamp/graph/geom/Point.java new file mode 100644 index 000000000..5f85801f8 --- /dev/null +++ b/src/com/jogamp/graph/geom/Point.java @@ -0,0 +1,78 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +/** + * A point with custom memory layout using custom factory. + */ +public interface Point extends Comparable, Cloneable { + + public static interface Factory { + T create(); + + T create(float x, float y); + + T create(float x, float y, float z); + + T create(float[] coordsBuffer, int offset, int length); + + // T[] create(T ... v); + } + + void setCoord(float x, float y); + + void setCoord(float x, float y, float z); + + void setCoord(float[] coordsBuffer, int offset, int length); + + float[] getCoord(); + + void setX(float x); + + void setY(float y); + + void setZ(float z); + + float getX(); + + float getY(); + + float getZ(); + + boolean isOnCurve(); + + void setOnCurve(boolean onCurve); + + int getId(); + + void setId(int id); + + int compareTo(Point p); + + Point clone(); +} diff --git a/src/com/jogamp/graph/geom/PointTex.java b/src/com/jogamp/graph/geom/PointTex.java new file mode 100644 index 000000000..59f7ee0c6 --- /dev/null +++ b/src/com/jogamp/graph/geom/PointTex.java @@ -0,0 +1,37 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +/** + * A Point with texture coordinates + */ +public interface PointTex extends Point { + float[] getTexCoord(); + + void setTexCoord(float s, float t); +} diff --git a/src/com/jogamp/graph/geom/Triangle.java b/src/com/jogamp/graph/geom/Triangle.java new file mode 100644 index 000000000..341a4483b --- /dev/null +++ b/src/com/jogamp/graph/geom/Triangle.java @@ -0,0 +1,79 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +public class Triangle { + private int id = Integer.MAX_VALUE; + final private T[] vertices; + private boolean[] boundaryEdges = new boolean[3]; + private boolean[] boundaryVertices = null; + + public Triangle(T ... v123){ + vertices = v123; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public T[] getVertices() { + return vertices; + } + + public boolean isEdgesBoundary() { + return boundaryEdges[0] || boundaryEdges[1] || boundaryEdges[2]; + } + + public boolean isVerticesBoundary() { + return boundaryVertices[0] || boundaryVertices[1] || boundaryVertices[2]; + } + + public void setEdgesBoundary(boolean[] boundary) { + this.boundaryEdges = boundary; + } + + public boolean[] getEdgeBoundary() { + return boundaryEdges; + } + + public boolean[] getVerticesBoundary() { + return boundaryVertices; + } + + public void setVerticesBoundary(boolean[] boundaryVertices) { + this.boundaryVertices = boundaryVertices; + } + + public String toString() { + return "Tri ID: " + id + "\n" + vertices[0] + "\n" + vertices[1] + "\n" + vertices[2]; + } +} diff --git a/src/com/jogamp/graph/geom/opengl/Vertex.java b/src/com/jogamp/graph/geom/opengl/Vertex.java new file mode 100644 index 000000000..77d18d7f5 --- /dev/null +++ b/src/com/jogamp/graph/geom/opengl/Vertex.java @@ -0,0 +1,180 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom.opengl; + +import jogamp.graph.math.VectorFloatUtil; + +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; + +public class Vertex implements PointTex { + private int id = Integer.MAX_VALUE; + protected float[] coord = new float[3]; + protected boolean onCurve = true; + private float[] texCoord = new float[2]; + + static final Factory factory = new Factory(); + + public static Factory factory() { return factory; } + + public static class Factory implements Point.Factory { + @Override + public Vertex create() { + return new Vertex(); + } + + @Override + public Vertex create(float x, float y) { + return new Vertex(x, y); + } + + @Override + public Vertex create(float x, float y, float z) { + return new Vertex(x, y, z); + } + + @Override + public Vertex create(float[] coordsBuffer, int offset, int length) { + return new Vertex(coordsBuffer, offset, length); + } + + /* @Override + public Vertex[] create(Vertex ... v) { + return v; + } */ + } + + public Vertex() { + } + + public Vertex(float x, float y) { + setCoord(x, y); + } + public Vertex(float x, float y, float z) { + setCoord(x, y, z); + } + public Vertex(float[] coordsBuffer, int offset, int length) { + setCoord(coordsBuffer, offset, length); + } + + public void setCoord(float x, float y) { + this.coord[0] = x; + this.coord[1] = y; + this.coord[2] = 0f; + } + + public void setCoord(float x, float y, float z) { + this.coord[0] = x; + this.coord[1] = y; + this.coord[2] = z; + } + + public void setCoord(float[] coordsBuffer, int offset, int length) { + if(length > coordsBuffer.length - offset) { + throw new IndexOutOfBoundsException("coordsBuffer too small: "+coordsBuffer.length+" - "+offset+" < "+length); + } + if(length > 3) { + throw new IndexOutOfBoundsException("length too bug: "+length+" > "+3); + } + int i=0; + while(i Date: Fri, 25 Mar 2011 03:58:05 +0100 Subject: Add initial GPU based curve rendering implementation, utilizing TTF fonts and manual shapes --- doc/alt-algorithm-rsantina-01.pdf | Bin 0 -> 52435 bytes src/com/jogamp/graph/curve/HwRegionRenderer.java | 385 +++++++++++++++++++++ src/com/jogamp/graph/curve/OutlineShape.java | 244 +++++++++++++ src/com/jogamp/graph/curve/Region.java | 125 +++++++ src/com/jogamp/graph/curve/RegionFactory.java | 58 ++++ src/com/jogamp/graph/curve/shader/curverenderer.fp | 99 ++++++ src/com/jogamp/graph/curve/shader/curverenderer.vp | 13 + .../jogamp/graph/curve/tess/CDTriangulator2D.java | 213 ++++++++++++ .../jogamp/graph/curve/text/HwTextRenderer.java | 367 ++++++++++++++++++++ src/com/jogamp/graph/math/Quaternion.java | 382 ++++++++++++++++++++ src/demo/GPURegionNewtDemo01.java | 230 ++++++++++++ src/demo/GPURegionNewtDemo02.java | 227 ++++++++++++ src/demo/GPUTextNewtDemo01.java | 198 +++++++++++ src/demo/GPUTextNewtDemo02.java | 215 ++++++++++++ src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 363 +++++++++++++++++++ src/jogamp/graph/curve/opengl/VBORegionSPES2.java | 185 ++++++++++ src/jogamp/graph/curve/tess/GraphOutline.java | 81 +++++ src/jogamp/graph/curve/tess/GraphPoint.java | 120 +++++++ src/jogamp/graph/curve/tess/HEdge.java | 131 +++++++ src/jogamp/graph/curve/tess/Loop.java | 376 ++++++++++++++++++++ src/jogamp/graph/curve/text/GlyphShape.java | 169 +++++++++ src/jogamp/graph/curve/text/GlyphString.java | 163 +++++++++ src/jogamp/graph/math/VectorFloatUtil.java | 293 ++++++++++++++++ 23 files changed, 4637 insertions(+) create mode 100644 doc/alt-algorithm-rsantina-01.pdf create mode 100755 src/com/jogamp/graph/curve/HwRegionRenderer.java create mode 100755 src/com/jogamp/graph/curve/OutlineShape.java create mode 100755 src/com/jogamp/graph/curve/Region.java create mode 100755 src/com/jogamp/graph/curve/RegionFactory.java create mode 100644 src/com/jogamp/graph/curve/shader/curverenderer.fp create mode 100644 src/com/jogamp/graph/curve/shader/curverenderer.vp create mode 100644 src/com/jogamp/graph/curve/tess/CDTriangulator2D.java create mode 100644 src/com/jogamp/graph/curve/text/HwTextRenderer.java create mode 100755 src/com/jogamp/graph/math/Quaternion.java create mode 100755 src/demo/GPURegionNewtDemo01.java create mode 100755 src/demo/GPURegionNewtDemo02.java create mode 100644 src/demo/GPUTextNewtDemo01.java create mode 100644 src/demo/GPUTextNewtDemo02.java create mode 100644 src/jogamp/graph/curve/opengl/VBORegion2PGL3.java create mode 100644 src/jogamp/graph/curve/opengl/VBORegionSPES2.java create mode 100644 src/jogamp/graph/curve/tess/GraphOutline.java create mode 100644 src/jogamp/graph/curve/tess/GraphPoint.java create mode 100644 src/jogamp/graph/curve/tess/HEdge.java create mode 100644 src/jogamp/graph/curve/tess/Loop.java create mode 100644 src/jogamp/graph/curve/text/GlyphShape.java create mode 100644 src/jogamp/graph/curve/text/GlyphString.java create mode 100755 src/jogamp/graph/math/VectorFloatUtil.java diff --git a/doc/alt-algorithm-rsantina-01.pdf b/doc/alt-algorithm-rsantina-01.pdf new file mode 100644 index 000000000..969b3a7ae Binary files /dev/null and b/doc/alt-algorithm-rsantina-01.pdf differ diff --git a/src/com/jogamp/graph/curve/HwRegionRenderer.java b/src/com/jogamp/graph/curve/HwRegionRenderer.java new file mode 100755 index 000000000..3c3142061 --- /dev/null +++ b/src/com/jogamp/graph/curve/HwRegionRenderer.java @@ -0,0 +1,385 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.PointTex; + +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class HwRegionRenderer { + protected static final boolean DEBUG = Debug.debug("RegionRenderer"); + + private ShaderState st; + private PMVMatrix pmvMatrix = new PMVMatrix(); + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private float sharpness = 0.5f; + private float alpha = 1.0f; + private float strength = 3.0f; + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private GLContext context; + private FloatBuffer color = FloatBuffer.allocate(3); + private HashMap regions = new HashMap(); + + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param factory optional Point.Factory for PointTex construction. Default is Vertex.Factory. + */ + public HwRegionRenderer(GLContext context) { + this.context = context; + init(context, 0.5f); + } + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param type region type (single or multipass) + */ + public HwRegionRenderer(GLContext context, int type) { + this.context = context; + this.regionType = type; + init(context, 0.5f); + } + + private boolean init(GLContext context, float sharpvalue){ + if(initialized){ + if(DEBUG) { + System.err.println("HWRegionRenderer: Already initialized!"); + } + return true; + } + sharpness = sharpvalue; + + GL2ES2 gl = context.getGL().getGL2ES2(); + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.setSwapInterval(1); + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + initShader(gl); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + st.glUseProgram(gl, false); + + if(DEBUG) { + System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public float getAlpha() { + return alpha; + } + public void setAlpha(float alpha_t) { + alpha = alpha_t; + } + + public void setColor(float r, float g, float b){ + color.put(r); + color.put(g); + color.put(b); + color.rewind(); + } + + public void rotate(float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + } + public void translate(float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + } + + public void resetMatrix(){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + } + + /** + * @param drawable + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null==st) { + if(DEBUG){ + System.err.println("HWRegionRenderer: Shader State is null, or not"); + } + return false; + } + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + st.glUseProgram(gl, false); + return true; + } + + private void initShader(GL2ES2 gl) { + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwRegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwRegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); + } + + st = new ShaderState(); + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + } + + private Region createRegion(OutlineShape outlineShape) { + Region region = RegionFactory.create(context, st, regionType); + + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList vertices = (ArrayList) outlineShape.getVertices(); + region.addVertices(vertices); + region.addTriangles(triangles); + + region.update(); + return region; + } + + private Region createRegion(OutlineShape[] outlineShapes) { + Region region = RegionFactory.create(context, st, regionType); + + int numVertices = region.getNumVertices(); + + for(OutlineShape outlineShape:outlineShapes){ + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = outlineShape.triangulate(sharpness); + region.addTriangles(triangles); + + ArrayList vertices = outlineShape.getVertices(); + for(PointTex vert:vertices){ + vert.setId(numVertices++); + } + region.addVertices(vertices); + } + + region.update(); + return region; + } + + + /** Render outline in 3D space at the position provided + * the triangles of the shapes will be generated, if not yet generated + * @param outlineShape the OutlineShape to Render. + * @param position the initial translation of the outlineShape. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + int hashCode = getHashCode(outlineShape); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShape); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + /** Render a list of Outline shapes combined in one region + * at the position provided the triangles of the + * shapes will be generated, if not yet generated + * @param outlineShapes the list of OutlineShapes to Render. + * @param position the initial translation of the outlineShapes. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + + int hashCode = getHashCode(outlineShapes); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShapes); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + private int getHashCode(OutlineShape outlineShape){ + return outlineShape.hashCode(); + } + + private int getHashCode(OutlineShape[] outlineShapes){ + int hashcode = 0; + for(OutlineShape outlineShape:outlineShapes){ + hashcode += getHashCode(outlineShape); + } + return hashcode; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void clearCached() { + Iterator iterator = regions.values().iterator(); + while(iterator.hasNext()){ + Region region = iterator.next(); + region.destroy(); + } + regions.clear(); + } +} diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java new file mode 100755 index 000000000..d939d7427 --- /dev/null +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -0,0 +1,244 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve; + +import java.util.ArrayList; +import java.util.Collections; + +import jogamp.graph.math.VectorFloatUtil; + +import com.jogamp.graph.geom.Outline; +import com.jogamp.graph.geom.Line; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; + +import com.jogamp.graph.curve.tess.CDTriangulator2D; + +/** A Generic shape objects which is defined by a list of Outlines. + * This Shape can be transformed to Triangulations. + * The list of triangles generated are render-able by a Region object. + * The triangulation produced by this Shape will define the + * closed region defined by the outlines. + * + * One or more OutlineShape Object can be associated to a region + * this is left high-level representation of the Objects. For + * possible Optimizations. + * + * @see Region + */ +public class OutlineShape { + public static final int QUADRATIC_NURBS = 10; + private final Point.Factory pointFactory; + private ArrayList> outlines = new ArrayList>(3); + + /** Create a new Outline based Shape + */ + public OutlineShape(Point.Factory factory) { + pointFactory = factory; + outlines.add(new Outline()); + } + + public final Point.Factory pointFactory() { return pointFactory; } + + /** Add a new empty outline + * to the shape, this new outline will + * be placed at the end of the outline list. + */ + public void addEmptyOutline(){ + outlines.add(new Outline()); + } + + /** Adds an outline to the OutlineShape object + * if last outline of the shape is empty, it will replace + * that last Outline with the new one. If outline is empty, + * it will do nothing. + * @param outline an Outline object + */ + public void addOutline(Outline outline){ + if(outline.isEmpty()){ + return; + } + if(getLastOutline().isEmpty()){ + outlines.remove(getLastOutline()); + } + outlines.add(outline); + } + + /** Adds a vertex to the last open outline in the + * shape + * @param point + */ + public final void addVertex(PointTex point){ + getLastOutline().addVertex(point); + } + + public final void addVertex(float x, float y, boolean onCurve) { + getLastOutline().addVertex(pointFactory, x, y, onCurve); + } + + public final void addVertex(float x, float y, float z, boolean onCurve) { + getLastOutline().addVertex(pointFactory, x, y, z, onCurve); + } + + public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) { + getLastOutline().addVertex(pointFactory, coordsBuffer, offset, length, onCurve); + } + + /** Closes the last outline in the shape + * if last vertex is not equal to first vertex. + * A new temp vertex is added at the end which + * is equal to the first. + */ + public void closeLastOutline(){ + getLastOutline().setClosed(true); + } + + /** Get the last added outline to the list + * of outlines that define the shape + * @return the last outline + */ + public final Outline getLastOutline(){ + return outlines.get(outlines.size()-1); + } + /** Make sure that the outlines represent + * the specified destinationType, if not + * transform outlines to destinationType. + * @param destinationType The curve type needed + */ + public void transformOutlines(int destinationType){ + if(destinationType == QUADRATIC_NURBS){ + transformOutlinesQuadratic(); + } + } + + private void transformOutlinesQuadratic(){ + ArrayList> newOutlines = new ArrayList>(3); + + /**loop over the outlines and make sure no + * adj off-curve vertices + */ + for(Outline outline:outlines){ + Outline newOutline = new Outline(); + + ArrayList vertices = outline.getVertices(); + int size =vertices.size()-1; + for(int i=0;i outline:outlines){ + ArrayList vertices = outline.getVertices(); + for(PointTex vert:vertices){ + vert.setId(maxVertexId); + maxVertexId++; + } + } + } + + /** @return the list of vertices associated with the + * {@code Outline} list of this object + */ + public ArrayList getVertices(){ + ArrayList vertices = new ArrayList(); + for(Outline polyline:outlines){ + vertices.addAll(polyline.getVertices()); + } + return vertices; + } + + + /** Generates the lines the define the noncurved + * parts of this graph + * @return arraylist of lines + */ + public ArrayList> getLines(){ + ArrayList> lines = new ArrayList>(); + for(Outline outline:outlines){ + ArrayList outVertices = outline.getVertices(); + int size = outVertices.size(); + for(int i=0; i < size; i++) { + PointTex currentVertex = outVertices.get(i); + if(currentVertex.isOnCurve()) { + PointTex v2 = outVertices.get((i+1)%size); + if(v2.isOnCurve()){ + lines.add(new Line(currentVertex, v2)); + } + } + } + } + return lines; + } + + /** Triangluate the graph object + * @param sharpness sharpness of the curved regions default = 0.5 + */ + public ArrayList> triangulate(float sharpness){ + if(outlines.size() == 0){ + return null; + } + sortOutlines(); + generateVertexIds(); + + CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); + + for(int index = 0; index< outlines.size();index++){ + Outline outline = outlines.get(index); + triangulator2d.addCurve(outline); + } + + ArrayList> triangles = triangulator2d.generateTriangulation(); + triangulator2d.reset(); + + return triangles; + } + + /** Sort the outlines from large + * to small depending on the AABox + */ + private void sortOutlines() { + Collections.sort(outlines); + Collections.reverse(outlines); + } +} diff --git a/src/com/jogamp/graph/curve/Region.java b/src/com/jogamp/graph/curve/Region.java new file mode 100755 index 000000000..44f426313 --- /dev/null +++ b/src/com/jogamp/graph/curve/Region.java @@ -0,0 +1,125 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.opengl.util.PMVMatrix; + +/** A Region is the OGL binding of one or more OutlineShapes + * Defined by its vertices and generated triangles. The Region + * defines the final shape of the OutlineShape(s), which shall produced a shaded + * region on the screen. + * + * Implementations of the Region shall take care of the OGL + * binding of the depending on its context, profile. + * + * @see RegionFactory, OutlineShape + */ +public interface Region { + /** The vertices index in an OGL object + */ + public static int VERTEX_POS_INDX = 0; + + /** The Texture Coord index in an OGL object + */ + public static int TEX_COORD = 1; + + public static int SINGLE_PASS = 10; + public static int TWO_PASS = 20; + + /** Updates a graph region by updating the ogl related + * objects for use in rendering. if called for the first time + * it initialize the objects. + */ + public void update(); + + /** Renders the associated OGL objects specifying + * current width/hight of window for multi pass rendering + * of the region. + * @param matrix current pmv matrix. + * @param vp_width current screen width + * @param vp_height current screen height + * @param width texture width for mp rendering + * + * @see update() + */ + public void render(PMVMatrix matrix, int vp_width, int vp_height, int width); + + /** Adds a list of {@code Triangle} objects to the Region + * These triangles are to be binded to OGL objects + * on the next call to {@code update} + * @param tris an arraylist of triangle objects + * + * @see update() + */ + public void addTriangles(ArrayList> tris); + + /** Get the current number of vertices associated + * with this region. This number is not necessary equal to + * the OGL binded number of vertices. + * @return vertices count + * + * @see isDirty() + */ + public int getNumVertices(); + + /** Adds a list of {@code Vertex} objects to the Region + * These vertices are to be binded to OGL objects + * on the next call to {@code update} + * @param verts an arraylist of vertex objects + * + * @see update() + */ + public void addVertices(ArrayList verts); + + /** Check if this region is dirty. A region is marked dirty + * when new Vertices, Triangles, and or Lines are added after a + * call to update() + * @return true if region is Dirty, false otherwise + * + * @see update(); + */ + public boolean isDirty(); + + /** Delete and clean the associated OGL + * objects + */ + public void destroy(); + + public boolean isFlipped(); + + /** Set if the y coordinate of the region should be flipped + * {@code y=-y} used mainly for fonts since they use opposite vertex + * as origion + * @param flipped flag if the coordinate is flipped defaults to false. + */ + public void setFlipped(boolean flipped); +} diff --git a/src/com/jogamp/graph/curve/RegionFactory.java b/src/com/jogamp/graph/curve/RegionFactory.java new file mode 100755 index 000000000..158f9db5b --- /dev/null +++ b/src/com/jogamp/graph/curve/RegionFactory.java @@ -0,0 +1,58 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve; + +import javax.media.opengl.GLContext; + +import com.jogamp.opengl.util.glsl.ShaderState; + +import jogamp.graph.curve.opengl.VBORegionSPES2; +import jogamp.graph.curve.opengl.VBORegion2PGL3; + + +/** RegionFactory to create a Context specific Region implementation. + * + * @see Region + */ +public class RegionFactory { + + /**Create a Region based on the GLContext attached + * @param context the current opengl context + * @param st the shader state object + * @param type can be one of Region.SINGLE_PASS or Region.TWO_PASS + * @return region + */ + public static Region create(GLContext context, ShaderState st, int type){ + if(Region.TWO_PASS == type && context.isGL3()){ + return new VBORegion2PGL3(context, st); + } + else{ + return new VBORegionSPES2(context); + } + } +} diff --git a/src/com/jogamp/graph/curve/shader/curverenderer.fp b/src/com/jogamp/graph/curve/shader/curverenderer.fp new file mode 100644 index 000000000..2b3a0ce1d --- /dev/null +++ b/src/com/jogamp/graph/curve/shader/curverenderer.fp @@ -0,0 +1,99 @@ +//#version 100 + +uniform float p1y; +uniform float g_alpha; +uniform vec3 g_color; +uniform float a_strength; + +varying vec2 v_texCoord; + +vec3 b_color = vec3(0.0, 0.0, 0.0); + +uniform sampler2D texture; +vec4 weights = vec4(0.075, 0.06, 0.045, 0.025); + +void main (void) +{ + vec2 rtex = vec2(abs(v_texCoord.x),abs(v_texCoord.y)); + vec3 c = g_color; + + float alpha = 0.0; + + if((v_texCoord.x == 0.0) && (v_texCoord.y == 0.0)){ + alpha = g_alpha; + } + else if((v_texCoord.x >= 5.0)){ + vec2 dfx = dFdx(v_texCoord); + vec2 dfy = dFdy(v_texCoord); + + vec2 size = 1.0/textureSize(texture,0); //version 130 + rtex -= 5.0; + vec4 t = texture2D(texture, rtex)* 0.18; + + t += texture2D(texture, rtex + size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex + size*(vec2(0, 1)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(0, 1)))*weights.x; + + t += texture2D(texture, rtex + 2.0*size*(vec2(1, 0))) *weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(1, 0)))*weights.y; + t += texture2D(texture, rtex + 2.0*size*(vec2(0, 1)))*weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(0, 1)))*weights.y; + + t += texture2D(texture, rtex + 3.0*size*(vec2(1, 0))) *weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(1, 0)))*weights.z; + t += texture2D(texture, rtex + 3.0*size*(vec2(0, 1)))*weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(0, 1)))*weights.z; + + t += texture2D(texture, rtex + 4.0*size*(vec2(1, 0))) *weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(1, 0)))*weights.w; + t += texture2D(texture, rtex + 4.0*size*(vec2(0, 1)))*weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(0, 1)))*weights.w; + + if(t.w == 0.0){ + discard; + } + + c = t.xyz; + alpha = g_alpha* t.w; + } + /////////////////////////////////////////////////////////// + else if ((v_texCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)){ + vec2 dtx = dFdx(rtex); + vec2 dty = dFdy(rtex); + + rtex.y -= 0.1; + if(rtex.y < 0.0) { + if(v_texCoord.y < 0.0) + discard; + else{ + rtex.y = 0.0; + } + } + + vec2 f = vec2((dtx.y - 2.0*p1y*dtx.x + 4.0*p1y*rtex.x*dtx.x), (dty.y - 2.0*p1y*dty.x + 4.0*p1y*rtex.x*dty.x)); + + float position = rtex.y - ((2.0 * rtex.x * p1y) * (1.0 - rtex.x)); + float d = position/(length(f)); + + float a = (0.5 - d * sign(v_texCoord.y)); + + + if (a >= 1.0) { + alpha = g_alpha; + // c = vec3(1.0,1.0,1.0); + } + else if (a <= 0.0) { + alpha = 0.0;//discard; + // c = vec3(0.0,0.0,0.0); + + } + else { + alpha = g_alpha*a; + // c = vec3(a,a,a); + mix(b_color,g_color, a); + } + } + + gl_FragColor = vec4(c, alpha); +} diff --git a/src/com/jogamp/graph/curve/shader/curverenderer.vp b/src/com/jogamp/graph/curve/shader/curverenderer.vp new file mode 100644 index 000000000..bc9ecb41e --- /dev/null +++ b/src/com/jogamp/graph/curve/shader/curverenderer.vp @@ -0,0 +1,13 @@ +//#version 100 + +uniform mat4 mgl_PMVMatrix[2]; +attribute vec4 v_position; +attribute vec2 texCoord; + +varying vec2 v_texCoord; + +void main(void) +{ + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * v_position; + v_texCoord = texCoord.st; +} \ No newline at end of file diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java new file mode 100644 index 000000000..936965f0c --- /dev/null +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -0,0 +1,213 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.graph.curve.tess; + +import java.util.ArrayList; + +import jogamp.graph.curve.tess.GraphOutline; +import jogamp.graph.curve.tess.GraphPoint; +import jogamp.graph.curve.tess.Loop; +import jogamp.graph.math.VectorFloatUtil; + +import com.jogamp.graph.geom.Outline; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.PointTex; +import jogamp.opengl.Debug; + +/** Constrained Delaunay Triangulation + * implementation of a list of Outlines that define a set of + * Closed Regions with optional n holes. + * + */ +public class CDTriangulator2D { + + protected static final boolean DEBUG = Debug.debug("Triangulation"); + + private float sharpness = 0.5f; + private ArrayList> loops; + private ArrayList vertices; + + private ArrayList> triangles; + private int maxTriID = 0; + + + public CDTriangulator2D() { + this(0.5f); + } + + /** Constructor for a new Delaunay triangulator + * @param curveSharpness the curvature around + * the off-curve vertices + */ + public CDTriangulator2D(float curveSharpness) { + this.sharpness = curveSharpness; + reset(); + } + + /** Reset the triangulation to initial state + * Clearing cached data + */ + public void reset() { + maxTriID = 0; + vertices = new ArrayList(); + triangles = new ArrayList>(3); + loops = new ArrayList>(); + } + + /** Add a curve to the list of profiles provided + * @param polyline a bounding Outline + */ + public void addCurve(Outline polyline){ + Loop loop = null; + + if(!loops.isEmpty()){ + loop = getContainerLoop(polyline); + } + + if(loop == null) { + GraphOutline outline = new GraphOutline(polyline); + GraphOutline innerPoly = extractBoundaryTriangles(outline, false); + vertices.addAll(polyline.getVertices()); + loop = new Loop(innerPoly, VectorFloatUtil.CCW); + loops.add(loop); + } + else { + GraphOutline outline = new GraphOutline(polyline); + GraphOutline innerPoly = extractBoundaryTriangles(outline, true); + vertices.addAll(innerPoly.getPoints()); + loop.addConstraintCurve(innerPoly); + } + } + + /** Generate the triangulation of the provided + * List of Outlines + */ + public ArrayList> generateTriangulation(){ + for(int i=0;i loop = loops.get(i); + int numTries = 0; + int size = loop.computeLoopSize(); + while(!loop.isSimplex()){ + Triangle tri = null; + if(numTries > size){ + tri = loop.cut(false); + } + else{ + tri = loop.cut(true); + } + numTries++; + + if(tri != null) { + numTries = 0; + size--; + tri.setId(maxTriID++); + triangles.add(tri); + if(DEBUG){ + System.err.println(tri); + } + } + if(numTries > size*2){ + if(DEBUG){ + System.err.println("Triangulation not complete!"); + } + break; + } + } + Triangle tri = loop.cut(true); + if(tri != null) + triangles.add(tri); + } + return triangles; + } + + @SuppressWarnings("unchecked") + private GraphOutline extractBoundaryTriangles(GraphOutline outline, boolean hole){ + GraphOutline innerOutline = new GraphOutline(); + ArrayList> outVertices = outline.getGraphPoint(); + int size = outVertices.size(); + for(int i=0; i < size; i++) { + GraphPoint currentVertex = outVertices.get(i); + GraphPoint gv0 = outVertices.get((i+size-1)%size); + GraphPoint gv2 = outVertices.get((i+1)%size); + GraphPoint gv1 = currentVertex; + + if(!currentVertex.getPoint().isOnCurve()) { + T v0 = (T) gv0.getPoint().clone(); + T v2 = (T) gv2.getPoint().clone(); + T v1 = (T) gv1.getPoint().clone(); + + gv0.setBoundaryContained(true); + gv1.setBoundaryContained(true); + gv2.setBoundaryContained(true); + + Triangle t= null; + boolean holeLike = false; + if(VectorFloatUtil.ccw(v0,v1,v2)){ + t = new Triangle(v0, v1, v2); + } + else { + holeLike = true; + t = new Triangle(v2, v1, v0); + } + t.setId(maxTriID++); + triangles.add(t); + + if(hole || holeLike) { + v0.setTexCoord(0, -0.1f); + v2.setTexCoord(1, -0.1f); + v1.setTexCoord(0.5f, -1*sharpness -0.1f); + innerOutline.addVertex(currentVertex); + } + else { + v0.setTexCoord(0, 0.1f); + v2.setTexCoord(1, 0.1f); + v1.setTexCoord(0.5f, sharpness+0.1f); + } + } + else { + if(!gv2.getPoint().isOnCurve() || !gv0.getPoint().isOnCurve()){ + currentVertex.setBoundaryContained(true); + } + innerOutline.addVertex(currentVertex); + } + } + return innerOutline; + } + + private Loop getContainerLoop(Outline polyline){ + T v = polyline.getVertex(0); + + for (Loop loop:loops){ + if(loop.checkInside(v)){ + return loop; + } + } + return null; + } +} diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java new file mode 100644 index 000000000..5813225e4 --- /dev/null +++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java @@ -0,0 +1,367 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve.text; + +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.graph.curve.text.GlyphString; +import jogamp.graph.font.typecast.TypecastFontFactory; + +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.geom.plane.Path2D; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.opengl.Vertex; +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class HwTextRenderer { + protected static final boolean DEBUG = Debug.debug("TextRenderer"); + static final boolean FONTTOOL_CUSTOM = false; + + private static FontFactory fontFactory; + + static { + FontFactory _fontFactory = null; + + if(FONTTOOL_CUSTOM) { + _fontFactory = (FontFactory) ReflectionUtil.createInstance("jogamp.graph.font.ttf.TTFFontFactory", HwTextRenderer.class.getClassLoader()); + if(null!=_fontFactory) { + System.err.println("Using custom font tool"); + } + } + if(null==_fontFactory) { + _fontFactory = new TypecastFontFactory(); + } + fontFactory = _fontFactory; + } + + + public static FontFactory getFontFactory() { + return fontFactory; + } + + private ShaderState st; + private PMVMatrix pmvMatrix = new PMVMatrix(); + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private float sharpness = 0.5f; + private float alpha = 1.0f; + private float strength = 1.8f; + private boolean initialized = false; + + + private int regionType = Region.SINGLE_PASS; + private GLContext context; + private FloatBuffer color = FloatBuffer.allocate(3); + private HashMap strings = new HashMap(); + private final Point.Factory pointFactory; + + int win_width = 0; + int win_height = 0; + + /** Create a Hardware accelerated Text Renderer + * @param context OpenGL rendering context + * @param factory optional Point.Factory for PointTex construction. Default is Vertex.Factory. + */ + public HwTextRenderer(GLContext context, Point.Factory factory, int type) { + this.pointFactory = (null != factory) ? factory : Vertex.factory(); + this.context = context; + this.regionType = type; + init(context, 0.5f); + } + + public Font createFont(Point.Factory factory, String name, int size) { + return fontFactory.createFont(factory, name, size); + } + + + public Font createFont(Point.Factory factory, + String[] families, + String style, + String variant, + String weight, + String size) { + return fontFactory.createFont(factory, families, style, variant, weight, size); + } + + /** initialize shaders and bindings for GPU based text Rendering, should + * be called only onceangle + * @param drawable the current drawable + * @param shapvalue shaprness around the off-curve vertices + * @return true if init succeeded, false otherwise + */ + private boolean init(GLContext context, float sharpvalue){ + if(initialized){ + if(DEBUG) { + System.err.println("HWTextRenderer: Already initialized!"); + } + return true; + } + sharpness = sharpvalue; + + GL2ES2 gl = context.getGL().getGL2ES2(); + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.setSwapInterval(1); + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + initShader(gl); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + st.glUseProgram(gl, false); + + if(DEBUG) { + System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public float getAlpha() { + return alpha; + } + public void setAlpha(float alpha_t) { + alpha = alpha_t; + } + + public void setColor(float r, float g, float b){ + color.put(r); + color.put(g); + color.put(b); + color.rewind(); + } + + public void rotate(float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + } + public void translate(float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + } + + public void resetMatrix(){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + } + + /** + * @param drawable + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshape(GLAutoDrawable drawable, float angle, int width, int height, float near, float far){ + win_width = width; + win_height = height; + float ratio = (float)width/(float)height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null==st) { + if(DEBUG){ + System.err.println("HWTextRenderer: Shader State is null, or not"); + } + return false; + } + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + st.glUseProgram(gl, false); + return true; + } + + private void initShader(GL2ES2 gl) { + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWTextRenderer: Couldn't link program: "+sp); + } + + st = new ShaderState(); + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + } + + private GlyphString createString(Font font, String str) { + AffineTransform affineTransform = new AffineTransform(pointFactory); + + Path2D[] paths = new Path2D[str.length()]; + font.getOutline(str, affineTransform, paths); + + GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); + glyphString.createfromFontPath(paths, affineTransform); + + glyphString.generateRegion(context, sharpness, st, regionType); + return glyphString; + } + + + /** Render the String in 3D space wrt to the font provided at the position provided + * the outlines will be generated, if not yet generated + * @param font font to be used + * @param str text to be rendered + * @param position the lower left corner of the string + * @param size texture size for multipass render + * @throws Exception if TextRenderer not initialized + */ + public void renderString3D(Font font, String str, float[] position, int size) throws Exception{ + if(!initialized){ + throw new Exception("HWTextRenderer: not initialized!"); + } + String fontStrHash = getTextHashCode(font, str); + GlyphString glyphString = strings.get(fontStrHash); + if(null == glyphString) { + glyphString = createString(font, str); + strings.put(fontStrHash, glyphString); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + glyphString.renderString3D(pmvMatrix, win_width, win_height, size); + st.glUseProgram(gl, false); + } + + private String getTextHashCode(Font font, String str){ + return "" + str.hashCode() + font.getSize(); + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void clearCached() { + Iterator iterator = strings.values().iterator(); + while(iterator.hasNext()){ + GlyphString glyphString = iterator.next(); + glyphString.destroy(); + } + strings.clear(); + } +} diff --git a/src/com/jogamp/graph/math/Quaternion.java b/src/com/jogamp/graph/math/Quaternion.java new file mode 100755 index 000000000..b77a5fa08 --- /dev/null +++ b/src/com/jogamp/graph/math/Quaternion.java @@ -0,0 +1,382 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.math; + +import jogamp.graph.math.MathFloat; + +public class Quaternion { + protected float x,y,z,w; + + public Quaternion(){ + + } + + public Quaternion(float x, float y, float z, float w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + /** Constructor to create a rotation based quaternion from two vectors + * @param vector1 + * @param vector2 + */ + public Quaternion(float[] vector1, float[] vector2) + { + float theta = (float)MathFloat.acos(dot(vector1, vector2)); + float[] cross = cross(vector1,vector2); + cross = normalizeVec(cross); + + this.x = (float)MathFloat.sin(theta/2)*cross[0]; + this.y = (float)MathFloat.sin(theta/2)*cross[1]; + this.z = (float)MathFloat.sin(theta/2)*cross[2]; + this.w = (float)MathFloat.cos(theta/2); + this.normalize(); + } + + /** Transform the rotational quaternion to axis based rotation angles + * @return new float[4] with ,theta,Rx,Ry,Rz + */ + public float[] toAxis() + { + float[] vec = new float[4]; + float scale = (float)MathFloat.sqrt(x * x + y * y + z * z); + vec[0] =(float) MathFloat.acos(w) * 2.0f; + vec[1] = x / scale; + vec[2] = y / scale; + vec[3] = z / scale; + return vec; + } + + /** Normalize a vector + * @param vector input vector + * @return normalized vector + */ + private float[] normalizeVec(float[] vector) + { + float[] newVector = new float[3]; + + float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); + if(d> 0.0f) + { + newVector[0] = vector[0]/d; + newVector[1] = vector[1]/d; + newVector[2] = vector[2]/d; + } + return newVector; + } + /** compute the dot product of two points + * @param vec1 vector 1 + * @param vec2 vector 2 + * @return the dot product as float + */ + private float dot(float[] vec1, float[] vec2) + { + return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]); + } + /** cross product vec1 x vec2 + * @param vec1 vector 1 + * @param vec2 vecttor 2 + * @return the resulting vector + */ + private float[] cross(float[] vec1, float[] vec2) + { + float[] out = new float[3]; + + out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2]; + out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0]; + out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1]; + + return out; + } + public float getW() { + return w; + } + public void setW(float w) { + this.w = w; + } + public float getX() { + return x; + } + public void setX(float x) { + this.x = x; + } + public float getY() { + return y; + } + public void setY(float y) { + this.y = y; + } + public float getZ() { + return z; + } + public void setZ(float z) { + this.z = z; + } + + /** Add a quaternion + * @param q quaternion + */ + public void add(Quaternion q) + { + x+=q.x; + y+=q.y; + z+=q.z; + } + + /** Subtract a quaternion + * @param q quaternion + */ + public void subtract(Quaternion q) + { + x-=q.x; + y-=q.y; + z-=q.z; + } + + /** Divide a quaternion by a constant + * @param n a float to divide by + */ + public void divide(float n) + { + x/=n; + y/=n; + z/=n; + } + + /** Multiply this quaternion by + * the param quaternion + * @param q a quaternion to multiply with + */ + public void mult(Quaternion q) + { + float w1 = w*q.w - (x*q.x + y*q.y + z*q.z); + + float x1 = w*q.z + q.w*z + y*q.z - z*q.y; + float y1 = w*q.x + q.w*x + z*q.x - x*q.z; + float z1 = w*q.y + q.w*y + x*q.y - y*q.x; + + w = w1; + x = x1; + y = y1; + z = z1; + } + + /** Multiply a quaternion by a constant + * @param n a float constant + */ + public void mult(float n) + { + x*=n; + y*=n; + z*=n; + } + + /** Normalize a quaternion required if + * to be used as a rotational quaternion + */ + public void normalize() + { + float norme = (float)MathFloat.sqrt(w*w + x*x + y*y + z*z); + if (norme == 0.0f) + { + w = 1.0f; + x = y = z = 0.0f; + } + else + { + float recip = 1.0f/norme; + + w *= recip; + x *= recip; + y *= recip; + z *= recip; + } + } + + /** Invert the quaternion If rotational, + * will produce a the inverse rotation + */ + public void inverse() + { + float norm = w*w + x*x + y*y + z*z; + + float recip = 1.0f/norm; + + w *= recip; + x = -1*x*recip; + y = -1*y*recip; + z = -1*z*recip; + } + + /** Transform this quaternion to a + * 4x4 column matrix representing the rotation + * @return new float[16] column matrix 4x4 + */ + public float[] toMatrix() + { + float[] matrix = new float[16]; + matrix[0] = 1.0f - 2*y*y - 2*z*z; + matrix[1] = 2*x*y + 2*w*z; + matrix[2] = 2*x*z - 2*w*y; + matrix[3] = 0; + + matrix[4] = 2*x*y - 2*w*z; + matrix[5] = 1.0f - 2*x*x - 2*z*z; + matrix[6] = 2*y*z + 2*w*x; + matrix[7] = 0; + + matrix[8] = 2*x*z + 2*w*y; + matrix[9] = 2*y*z - 2*w*x; + matrix[10] = 1.0f - 2*x*x - 2*y*y; + matrix[11] = 0; + + matrix[12] = 0; + matrix[13] = 0; + matrix[14] = 0; + matrix[15] = 1; + return matrix; + } + + /** Set this quaternion from a Sphereical interpolation + * of two param quaternion, used mostly for rotational animation + * @param a initial quaternion + * @param b target quaternion + * @param t float between 0 and 1 representing interp. + */ + public void slerp(Quaternion a,Quaternion b, float t) + { + float omega, cosom, sinom, sclp, sclq; + cosom = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; + if ((1.0f+cosom) > MathFloat.E) { + if ((1.0f-cosom) > MathFloat.E) { + omega = (float)MathFloat.acos(cosom); + sinom = (float)MathFloat.sin(omega); + sclp = (float)MathFloat.sin((1.0f-t)*omega) / sinom; + sclq = (float)MathFloat.sin(t*omega) / sinom; + } + else { + sclp = 1.0f - t; + sclq = t; + } + x = sclp*a.x + sclq*b.x; + y = sclp*a.y + sclq*b.y; + z = sclp*a.z + sclq*b.z; + w = sclp*a.w + sclq*b.w; + } + else { + x =-a.y; + y = a.x; + z =-a.w; + w = a.z; + sclp = MathFloat.sin((1.0f-t) * MathFloat.PI * 0.5f); + sclq = MathFloat.sin(t * MathFloat.PI * 0.5f); + x = sclp*a.x + sclq*b.x; + y = sclp*a.y + sclq*b.y; + z = sclp*a.z + sclq*b.z; + } + } + + /** Check if this quaternion is empty, ie (0,0,0,1) + * @return true if empty, false otherwise + */ + public boolean isEmpty() + { + if (w==1 && x==0 && y==0 && z==0) + return true; + return false; + } + + /** Check if this quaternion represents an identity + * matrix, for rotation. + * @return true if it is an identity rep., false otherwise + */ + public boolean isIdentity() + { + if (w==0 && x==0 && y==0 && z==0) + return true; + return false; + } + + /** compute the quaternion from a 3x3 column matrix + * @param m 3x3 column matrix + */ + public void setFromMatrix(float[] m) { + float T= m[0] + m[4] + m[8] + 1; + if (T>0){ + float S = 0.5f / (float)MathFloat.sqrt(T); + w = 0.25f / S; + x = ( m[5] - m[7]) * S; + y = ( m[6] - m[2]) * S; + z = ( m[1] - m[3] ) * S; + } + else{ + if ((m[0] > m[4])&(m[0] > m[8])) { + float S = MathFloat.sqrt( 1.0f + m[0] - m[4] - m[8] ) * 2f; // S=4*qx + w = (m[7] - m[5]) / S; + x = 0.25f * S; + y = (m[3] + m[1]) / S; + z = (m[6] + m[2]) / S; + } + else if (m[4] > m[8]) { + float S = MathFloat.sqrt( 1.0f + m[4] - m[0] - m[8] ) * 2f; // S=4*qy + w = (m[6] - m[2]) / S; + x = (m[3] + m[1]) / S; + y = 0.25f * S; + z = (m[7] + m[5]) / S; + } + else { + float S = MathFloat.sqrt( 1.0f + m[8] - m[0] - m[4] ) * 2f; // S=4*qz + w = (m[3] - m[1]) / S; + x = (m[6] + m[2]) / S; + y = (m[7] + m[5]) / S; + z = 0.25f * S; + } + } + } + + /** Check if the the 3x3 matrix (param) is in fact + * an affine rotational matrix + * @param m 3x3 column matrix + * @return true if representing a rotational matrix, false otherwise + */ + public boolean isRotationMatrix(float[] m) { + double epsilon = 0.01; // margin to allow for rounding errors + if (MathFloat.abs(m[0]*m[3] + m[3]*m[4] + m[6]*m[7]) > epsilon) return false; + if (MathFloat.abs(m[0]*m[2] + m[3]*m[5] + m[6]*m[8]) > epsilon) return false; + if (MathFloat.abs(m[1]*m[2] + m[4]*m[5] + m[7]*m[8]) > epsilon) return false; + if (MathFloat.abs(m[0]*m[0] + m[3]*m[3] + m[6]*m[6] - 1) > epsilon) return false; + if (MathFloat.abs(m[1]*m[1] + m[4]*m[4] + m[7]*m[7] - 1) > epsilon) return false; + if (MathFloat.abs(m[2]*m[2] + m[5]*m[5] + m[8]*m[8] - 1) > epsilon) return false; + return (MathFloat.abs(determinant(m)-1) < epsilon); + } + private float determinant(float[] m) { + return m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[0]*m[7]*m[5] - m[3]*m[1]*m[8] - m[6]*m[4]*m[2]; + } +} diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java new file mode 100755 index 000000000..c728e74e5 --- /dev/null +++ b/src/demo/GPURegionNewtDemo01.java @@ -0,0 +1,230 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package demo; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.HwRegionRenderer; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +/** Demonstrate the rendering of multiple outlines into one region/OutlineShape + * These Outlines are not necessary connected or contained. + * The output of this demo shows two identical shapes but the left one + * has some vertices with off-curve flag set to true, and the right allt he vertices + * are on the curve. Demos the Res. Independent Nurbs based Curve rendering + * + */ +public class GPURegionNewtDemo01 { + private static void create(){ + new RegionNewtWindow(); + } + public static void main(String[] args) { + create(); + } +} + +class RegionNewtWindow { + RegionGLListener regionGLListener = null; + + public RegionNewtWindow(){ + createWindow(); + } + private void createWindow() { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + System.out.println(caps); + final GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(500, 500); + + window.setTitle("GPU Curve Region Newt Demo 01"); + regionGLListener = new RegionGLListener(); + window.addGLEventListener(regionGLListener); + + window.setVisible(true); + + window.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + regionGLListener.zoomIn(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + regionGLListener.zoomOut(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + regionGLListener.move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + regionGLListener.move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + regionGLListener.move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + regionGLListener.move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + regionGLListener.rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + regionGLListener.rotate(-1); + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + }); + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + window.addWindowListener(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent arg0) { + System.exit(0); + }; + }); + animator.start(); + } + private class RegionGLListener implements GLEventListener{ + HwRegionRenderer regionRenderer = null; + + OutlineShape outlineShape = null; + + public RegionGLListener() {} + + private void createTestOutline(){ + float offset = 0; + outlineShape = new OutlineShape(Vertex.factory()); + outlineShape.addVertex(0.0f,-10.0f, true); + outlineShape.addVertex(15.0f,-10.0f, true); + outlineShape.addVertex(10.0f,5.0f, false); + outlineShape.addVertex(15.0f,10.0f, true); + outlineShape.addVertex(6.0f,15.0f, false); + outlineShape.addVertex(5.0f,8.0f, false); + outlineShape.addVertex(0.0f,10.0f,true); + outlineShape.closeLastOutline(); + outlineShape.addEmptyOutline(); + outlineShape.addVertex(5.0f,-5.0f,true); + outlineShape.addVertex(10.0f,-5.0f, false); + outlineShape.addVertex(10.0f,0.0f, true); + outlineShape.addVertex(5.0f,0.0f, false); + outlineShape.closeLastOutline(); + + /** Same shape as above but without any off-curve vertices */ + outlineShape.addEmptyOutline(); + offset = 30; + outlineShape.addVertex(offset+0.0f,-10.0f, true); + outlineShape.addVertex(offset+17.0f,-10.0f, true); + outlineShape.addVertex(offset+11.0f,5.0f, true); + outlineShape.addVertex(offset+16.0f,10.0f, true); + outlineShape.addVertex(offset+7.0f,15.0f, true); + outlineShape.addVertex(offset+6.0f,8.0f, true); + outlineShape.addVertex(offset+0.0f,10.0f, true); + outlineShape.closeLastOutline(); + outlineShape.addEmptyOutline(); + outlineShape.addVertex(offset+5.0f,0.0f, true); + outlineShape.addVertex(offset+5.0f,-5.0f, true); + outlineShape.addVertex(offset+10.0f,-5.0f, true); + outlineShape.addVertex(offset+10.0f,0.0f, true); + outlineShape.closeLastOutline(); + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + regionRenderer = new HwRegionRenderer(drawable.getContext()); + createTestOutline(); + } + + float ang = 0; + float zoom = -70; + float xTran = -20; + float yTran = 5; + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + regionRenderer.resetMatrix(); + regionRenderer.translate(xTran, yTran, zoom); + regionRenderer.rotate(ang, 0, 1, 0); + + try { + regionRenderer.setAlpha(1.0f); + regionRenderer.setColor(0.0f, 0.0f, 1.0f); + + regionRenderer.renderOutlineShape(outlineShape, new float[]{0,0,0}); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(xstart, ystart, width, height); + + regionRenderer.reshape(drawable, 45.0f, (float)width / (float)height, 0.1f, 7000.0f); + } + + public void zoomIn(){ + zoom++; + } + public void zoomOut(){ + zoom--; + } + public void move(float x, float y){ + xTran += x; + yTran += y; + } + public void rotate(float delta){ + ang+= delta; + ang%=360; + } + public void dispose(GLAutoDrawable arg0) { + regionRenderer.clearCached(); + + } + } +} diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java new file mode 100755 index 000000000..414b7942d --- /dev/null +++ b/src/demo/GPURegionNewtDemo02.java @@ -0,0 +1,227 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package demo; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.HwRegionRenderer; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +/** Demonstrate the rendering of multiple OutlineShapes + * into one region + * + */ +public class GPURegionNewtDemo02 { + private static void create(){ + new RegionsNewtWindow(); + } + public static void main(String[] args) { + create(); + } +} + +class RegionsNewtWindow { + RegionGLListener regionGLListener = null; + + public RegionsNewtWindow(){ + createWindow(); + } + private void createWindow() { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + System.out.println(caps); + final GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(500, 500); + + window.setTitle("GPU Curve Region Newt Demo 01"); + regionGLListener = new RegionGLListener(); + window.addGLEventListener(regionGLListener); + + window.setVisible(true); + + window.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + regionGLListener.zoomIn(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + regionGLListener.zoomOut(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + regionGLListener.move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + regionGLListener.move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + regionGLListener.move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + regionGLListener.move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + regionGLListener.rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + regionGLListener.rotate(-1); + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + }); + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + window.addWindowListener(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent arg0) { + System.exit(0); + }; + }); + animator.start(); + } + private class RegionGLListener implements GLEventListener{ + HwRegionRenderer regionRenderer = null; + + OutlineShape[] outlineShapes = new OutlineShape[2]; + + public RegionGLListener() {} + + private void createTestOutline(){ + float offset = 0; + outlineShapes[0] = new OutlineShape(Vertex.factory()); + outlineShapes[0].addVertex(0.0f,-10.0f,true); + outlineShapes[0].addVertex(15.0f,-10.0f, true); + outlineShapes[0].addVertex(10.0f,5.0f, false); + outlineShapes[0].addVertex(15.0f,10.0f, true); + outlineShapes[0].addVertex(6.0f,15.0f, false); + outlineShapes[0].addVertex(5.0f,8.0f, false); + outlineShapes[0].addVertex(0.0f,10.0f,true); + outlineShapes[0].closeLastOutline(); + outlineShapes[0].addEmptyOutline(); + outlineShapes[0].addVertex(5.0f,-5.0f,true); + outlineShapes[0].addVertex(10.0f,-5.0f, false); + outlineShapes[0].addVertex(10.0f,0.0f, true); + outlineShapes[0].addVertex(5.0f,0.0f, false); + outlineShapes[0].closeLastOutline(); + + /** Same shape as above but without any off-curve vertices */ + outlineShapes[1] = new OutlineShape(Vertex.factory()); + offset = 30; + outlineShapes[1].addVertex(offset+0.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+17.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+11.0f,5.0f, true); + outlineShapes[1].addVertex(offset+16.0f,10.0f, true); + outlineShapes[1].addVertex(offset+7.0f,15.0f, true); + outlineShapes[1].addVertex(offset+6.0f,8.0f, true); + outlineShapes[1].addVertex(offset+0.0f,10.0f, true); + outlineShapes[1].closeLastOutline(); + outlineShapes[1].addEmptyOutline(); + outlineShapes[1].addVertex(offset+5.0f,0.0f, true); + outlineShapes[1].addVertex(offset+5.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,0.0f, true); + outlineShapes[1].closeLastOutline(); + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + regionRenderer = new HwRegionRenderer(drawable.getContext()); + createTestOutline(); + } + + float ang = 0; + float zoom = -70; + float xTran = -20; + float yTran = 5; + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + regionRenderer.resetMatrix(); + regionRenderer.translate(xTran, yTran, zoom); + regionRenderer.rotate(ang, 0, 1, 0); + + try { + regionRenderer.setAlpha(1.0f); + regionRenderer.setColor(0.0f, 0.0f, 1.0f); + + regionRenderer.renderOutlineShapes(outlineShapes, new float[]{0,0,0}); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(xstart, ystart, width, height); + + regionRenderer.reshape(drawable, 45.0f, (float)width / (float)height, 0.1f, 7000.0f); + } + + public void zoomIn(){ + zoom++; + } + public void zoomOut(){ + zoom--; + } + public void move(float x, float y){ + xTran += x; + yTran += y; + } + public void rotate(float delta){ + ang+= delta; + ang%=360; + } + public void dispose(GLAutoDrawable arg0) { + regionRenderer.clearCached(); + + } + } +} diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java new file mode 100644 index 000000000..fcd2134ae --- /dev/null +++ b/src/demo/GPUTextNewtDemo01.java @@ -0,0 +1,198 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.text.HwTextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +public class GPUTextNewtDemo01 { + private static void create(){ + new TextNewtWindow1(); + } + public static void main(String[] args) { + create(); + } +} + +class TextNewtWindow1 { + Point.Factory pointFactory = Vertex.factory(); + + TextGLListener textGLListener = null; + + public TextNewtWindow1(){ + createWindow(); + } + private void createWindow() { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); // FIXME: sure ? + caps.setNumSamples(4); // FIXME: sure ? + System.out.println("Requested: "+caps); + + final GLWindow window = GLWindow.create(caps); + + window.setPosition(10, 10); + window.setSize(500, 500); + + window.setTitle("GPU Text Newt Demo 01"); + textGLListener = new TextGLListener(); + window.addGLEventListener(textGLListener); + + window.setVisible(true); + + window.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + textGLListener.zoomIn(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + textGLListener.zoomOut(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + textGLListener.move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + textGLListener.move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + textGLListener.move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + textGLListener.move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + textGLListener.rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + textGLListener.rotate(-1); + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + }); + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + window.addWindowListener(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent arg0) { + System.exit(0); + }; + }); + animator.start(); + } + private class TextGLListener implements GLEventListener{ + HwTextRenderer textRenderer = null; + + public TextGLListener(){ + + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); + + System.out.println("Realised: "+drawable.getChosenGLCapabilities()); + System.out.println("MS: " + gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); + } + + float ang = 0; + float zoom = -70; + float xTran = -10; + float yTran = 10; + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + textRenderer.resetMatrix(); + textRenderer.translate(xTran, yTran, zoom); + textRenderer.rotate(ang, 0, 1, 0); + + String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + String text2 = text1.toUpperCase(); + + Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); + float[] position = new float[]{0,0,0}; + + try { + textRenderer.setAlpha(1.0f); + textRenderer.setColor(0.0f, 0.0f, 1.0f); + gl.glSampleCoverage(0.75f, false); + textRenderer.renderString3D(font, text2, position, 0); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(xstart, ystart, width, height); + + textRenderer.reshape(drawable, 45.0f, width, height, 0.1f, 7000.0f); + } + + public void zoomIn(){ + zoom++; + } + public void zoomOut(){ + zoom--; + } + public void move(float x, float y){ + xTran += x; + yTran += y; + } + public void rotate(float delta){ + ang+= delta; + ang%=360; + } + public void dispose(GLAutoDrawable arg0) { + textRenderer.clearCached(); + } + } +} diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java new file mode 100644 index 000000000..b0c7115ec --- /dev/null +++ b/src/demo/GPUTextNewtDemo02.java @@ -0,0 +1,215 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.text.HwTextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +public class GPUTextNewtDemo02 { + private static void create(){ + new TextNewtWindow(); + } + public static void main(String[] args) { + create(); + } +} + +class TextNewtWindow { + Point.Factory pointFactory = Vertex.factory(); + TextGLListener textGLListener = null; + + public TextNewtWindow(){ + createWindow(); + } + private void createWindow() { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.get(GLProfile.GL3); + + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + System.out.println("Requested: "+caps); + + final GLWindow window = GLWindow.create(caps); + + window.setPosition(10, 10); + window.setSize(1000, 1000); + + window.setTitle("GPU Text Newt Demo 02"); + textGLListener = new TextGLListener(); + window.addGLEventListener(textGLListener); + + window.setVisible(true); + + window.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + textGLListener.zoomIn(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + textGLListener.zoomOut(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_3){ + textGLListener.zoomIn(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_4){ + textGLListener.zoomOut(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + textGLListener.move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + textGLListener.move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + textGLListener.move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + textGLListener.move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + textGLListener.rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + textGLListener.rotate(-1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + textGLListener.size -= 10; + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + textGLListener.size += 10; + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + }); + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + window.addWindowListener(new WindowAdapter() { + public void windowDestroyNotify(WindowEvent arg0) { + System.exit(0); + }; + }); + animator.start(); + } + private class TextGLListener implements GLEventListener{ + HwTextRenderer textRenderer = null; + + public TextGLListener(){ + + } + + public void init(GLAutoDrawable drawable) { + GL3 gl = drawable.getGL().getGL3(); + gl.setSwapInterval(1); + gl.glEnable(GL3.GL_DEPTH_TEST); + + textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.TWO_PASS); + gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); + System.out.println("Realised: "+drawable.getChosenGLCapabilities()); + System.out.println("MS: " + gl.glIsEnabled(GL3.GL_MULTISAMPLE)); + } + + float ang = 0; + float zoom = -300; + float xTran = -100; + float yTran = 40; + int size = 200; + + public void display(GLAutoDrawable drawable) { + GL3 gl = drawable.getGL().getGL3(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + textRenderer.resetMatrix(); + textRenderer.translate(xTran, yTran, zoom); + textRenderer.rotate(ang, 0, 1, 0); + + String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + String text2 = text1.toUpperCase(); + + Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); + float[] position = new float[]{0,0,0}; + + try { + textRenderer.setAlpha(1.0f); + textRenderer.setColor(0.0f, 0.0f, 0.0f); + gl.glSampleCoverage(0.75f, false); + textRenderer.renderString3D(font, text2, position, size); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ + GL3 gl = drawable.getGL().getGL3(); + gl.glViewport(xstart, ystart, width, height); + + textRenderer.reshape(drawable, 45.0f, width , height, 0.1f, 7000.0f); + } + + public void zoomIn(float f){ + zoom+=f; + } + public void zoomOut(float f){ + zoom-=f; + System.err.println("Zoom: " + zoom); + } + public void move(float x, float y){ + xTran += x; + yTran += y; + } + public void rotate(float delta){ + ang+= delta; + ang%=360; + } + + public void dispose(GLAutoDrawable arg0) { + textRenderer.clearCached(); + } + } +} diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java new file mode 100644 index 000000000..c5182059e --- /dev/null +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -0,0 +1,363 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; + +import javax.media.opengl.GL3; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.common.nio.Buffers; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.PointTex; + +import com.jogamp.graph.curve.Region; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class VBORegion2PGL3 implements Region{ + private int numVertices = 0; + private IntBuffer vboIds; + + private IntBuffer t_vboIds; + + private ArrayList> triangles = new ArrayList>(); + private ArrayList vertices = new ArrayList(); + private GLContext context; + + private int numBuffers = 3; + + private boolean flipped = false; + + private boolean dirty = false; + + private AABBox box = null; + private IntBuffer texture = IntBuffer.allocate(1); + private IntBuffer fbo = IntBuffer.allocate(1); + private IntBuffer rbo = IntBuffer.allocate(1); + private boolean texInitialized = false; + + private int tex_width_c = 0; + private int tex_height_c = 0; + + private ShaderState st; + + public VBORegion2PGL3(GLContext context, ShaderState st){ + this.context =context; + this.st = st; + } + + public void update(){ + box = new AABBox(); + + GL3 gl = context.getGL().getGL3(); + ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); + + for(Triangle t:triangles){ + if(t.getVertices()[0].getId() == Integer.MAX_VALUE){ + t.getVertices()[0].setId(numVertices++); + t.getVertices()[1].setId(numVertices++); + t.getVertices()[2].setId(numVertices++); + + vertices.add(t.getVertices()[0]); + vertices.add(t.getVertices()[1]); + vertices.add(t.getVertices()[2]); + + indicies.put((short) t.getVertices()[0].getId()); + indicies.put((short) t.getVertices()[1].getId()); + indicies.put((short) t.getVertices()[2].getId()); + } + else{ + PointTex v1 = t.getVertices()[0]; + PointTex v2 = t.getVertices()[1]; + PointTex v3 = t.getVertices()[2]; + + indicies.put((short) v1.getId()); + indicies.put((short) v2.getId()); + indicies.put((short) v3.getId()); + } + } + indicies.rewind(); + + FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); + for(PointTex v:vertices){ + verticesBuffer.put(v.getX()); + if(flipped){ + verticesBuffer.put(-1*v.getY()); + } + else{ + verticesBuffer.put(v.getY()); + } + verticesBuffer.put(v.getZ()); + + box.resize(v.getX(), -1*v.getY(), v.getZ()); + } + verticesBuffer.rewind(); + + FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); + for(PointTex v:vertices){ + float[] tex = v.getTexCoord(); + texCoordBuffer.put(tex[0]); + texCoordBuffer.put(tex[1]); + } + texCoordBuffer.rewind(); + + vboIds = IntBuffer.allocate(numBuffers); + gl.glGenBuffers(numBuffers, vboIds); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(0)); // vertices + gl.glBufferData(GL3.GL_ARRAY_BUFFER, numVertices * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(1)); //texture + gl.glBufferData(GL3.GL_ARRAY_BUFFER, numVertices * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); //triangles + gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER, triangles.size()* 3 * Buffers.SIZEOF_SHORT, indicies, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0); + + dirty = false; + } + + public void render(PMVMatrix matrix, int vp_width, int vp_height, int width){ + if(null == matrix || vp_width <=0 || vp_height <= 0 || width <= 0){ + renderRegion(); + } + else { + if(width != tex_width_c){ + texInitialized = false; + tex_width_c = width; + } + if(!texInitialized){ + initFBOTexture(matrix,vp_width, vp_height); + texInitialized = true; + } +// System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3)); + renderTexture(matrix, vp_width, vp_height); + } + } + + private void renderTexture(PMVMatrix matrix, int width, int hight){ + GL3 gl = context.getGL().getGL3(); + gl.glViewport(0, 0, width, hight); + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, matrix.glGetPMvMatrixf()))){ + System.out.println("Cnt set tex based mat"); + } + gl.glEnable(GL3.GL_TEXTURE_2D); + gl.glActiveTexture(GL3.GL_TEXTURE0); + gl.glBindTexture(GL3.GL_TEXTURE_2D, texture.get(0)); + + st.glUniform(gl, new GLUniformData("texture", texture.get(0))); + int loc = gl.glGetUniformLocation(st.shaderProgram().id(), "texture"); + gl.glUniform1i(loc, 0); + + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(0)); + gl.glEnableVertexAttribArray(VERTEX_POS_INDX); + gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL3.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(1)); + gl.glEnableVertexAttribArray(TEX_COORD); + gl.glVertexAttribPointer(TEX_COORD, 2, GL3.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); + gl.glDrawElements(GL3.GL_TRIANGLES, 2 * 3, GL3.GL_UNSIGNED_SHORT, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + } + + private void setupBoundingBuffers(){ + GL3 gl = context.getGL().getGL3(); + ShortBuffer indicies = Buffers.newDirectShortBuffer(6); + indicies.put((short) 0); indicies.put((short) 1); indicies.put((short) 3); + indicies.put((short) 1); indicies.put((short) 2); indicies.put((short) 3); + indicies.rewind(); + + FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(4 * 3); + FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(4 * 2); + + verticesBuffer.put(box.getLow()[0]); + verticesBuffer.put(box.getLow()[1]); + verticesBuffer.put(box.getLow()[2]); + texCoordBuffer.put(5); + texCoordBuffer.put(5); + + verticesBuffer.put(box.getLow()[0]); + verticesBuffer.put(box.getHigh()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(5); + texCoordBuffer.put(6); + + verticesBuffer.put(box.getHigh()[0]); + verticesBuffer.put(box.getHigh()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(6); + texCoordBuffer.put(6); + + verticesBuffer.put(box.getHigh()[0]); + verticesBuffer.put(box.getLow()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(6); + texCoordBuffer.put(5); + + verticesBuffer.rewind(); + texCoordBuffer.rewind(); + + t_vboIds = IntBuffer.allocate(3); + gl.glGenBuffers(numBuffers, t_vboIds); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(0)); // vertices + gl.glBufferData(GL3.GL_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(1)); //texture + gl.glBufferData(GL3.GL_ARRAY_BUFFER, 4 * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); //triangles + gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_SHORT, indicies, GL3.GL_STATIC_DRAW); + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + private void initFBOTexture(PMVMatrix m, int width, int hight){ + tex_height_c = (int)(tex_width_c*box.getHeight()/box.getWidth()); + System.out.println("Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); + GL3 gl = context.getGL().getGL3(); + + gl.glDeleteFramebuffers(1, fbo); + gl.glDeleteTextures(1, texture); + + gl.glGenTextures(1, texture); + gl.glBindTexture(GL3.GL_TEXTURE_2D, texture.get(0)); + gl.glTexImage2D(GL3.GL_TEXTURE_2D, 0, GL3.GL_RGBA, tex_width_c, + tex_height_c, 0, GL3.GL_RGBA, GL3.GL_UNSIGNED_BYTE, null); + + gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_LINEAR); + gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_LINEAR); + gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE); + gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE); + + gl.glGenRenderbuffers(1,rbo); + gl.glBindRenderbuffer(GL3.GL_RENDERBUFFER, rbo.get(0)); + gl.glRenderbufferStorage(GL3.GL_RENDERBUFFER, GL3.GL_DEPTH_COMPONENT, tex_width_c, tex_height_c); + + gl.glGenFramebuffers(1, fbo); + gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo.get(0)); + gl.glFramebufferTexture2D(GL3.GL_DRAW_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, + GL3.GL_TEXTURE_2D, texture.get(0), 0); + gl.glFramebufferRenderbuffer(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_COMPONENT, GL3.GL_RENDERBUFFER, rbo.get(0)); + + int status = gl.glCheckFramebufferStatus(GL3.GL_FRAMEBUFFER); + if(status != GL3.GL_FRAMEBUFFER_COMPLETE){ + System.out.println("FRAAAAAAAAAAAAAAME"); + } + + //render texture + PMVMatrix tex_matrix = new PMVMatrix(); + gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo.get(0)); + gl.glViewport(0, 0, tex_width_c, tex_height_c); + tex_matrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + tex_matrix.glLoadIdentity(); + tex_matrix.glOrthof(box.getLow()[0], box.getHigh()[0], box.getLow()[1], box.getHigh()[1], -1, 1); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, tex_matrix.glGetPMvMatrixf()))){ + System.out.println("Cnt set tex based mat"); + } + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT); + renderRegion(); + + gl.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0); + gl.glBindTexture(GL3.GL_TEXTURE_2D, 0); + + setupBoundingBuffers(); + } + + private void renderRegion(){ + GL3 gl = context.getGL().getGL3(); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(0)); + gl.glEnableVertexAttribArray(VERTEX_POS_INDX); + gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL3.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(1)); + gl.glEnableVertexAttribArray(TEX_COORD); + gl.glVertexAttribPointer(TEX_COORD, 2, GL3.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); + gl.glDrawElements(GL3.GL_TRIANGLES, triangles.size() * 3, GL3.GL_UNSIGNED_SHORT, 0); + + gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); + } + + public void addTriangles(ArrayList> tris) { + triangles.addAll(tris); + dirty = true; + } + + public int getNumVertices(){ + return numVertices; + } + + public void addVertices(ArrayList verts){ + vertices.addAll(verts); + numVertices = vertices.size(); + dirty = true; + } + + public boolean isDirty(){ + return dirty; + } + + public void destroy() { + GL3 gl = context.getGL().getGL3(); + gl.glDeleteBuffers(numBuffers, vboIds); + gl.glDeleteFramebuffers(1, fbo); + gl.glDeleteTextures(1, texture); + } + + public boolean isFlipped() { + return flipped; + } + + public void setFlipped(boolean flipped) { + this.flipped = flipped; + } +} diff --git a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java new file mode 100644 index 000000000..5ef23d4e0 --- /dev/null +++ b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -0,0 +1,185 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLContext; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.opengl.util.PMVMatrix; + +public class VBORegionSPES2 implements Region{ + private int numVertices = 0; + private IntBuffer vboIds; + + private ArrayList> triangles = new ArrayList>(); + private ArrayList vertices = new ArrayList(); + + private GLContext context; + + private int numBuffers = 3; + + private boolean flipped = false; + private boolean dirty = false; + + public VBORegionSPES2(GLContext context){ + this.context =context; + } + + public void update(){ + GL2ES2 gl = context.getGL().getGL2ES2(); + ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); + + for(Triangle t:triangles){ + final PointTex[] t_vertices = t.getVertices(); + + if(t_vertices[0].getId() == Integer.MAX_VALUE){ + t_vertices[0].setId(numVertices++); + t_vertices[1].setId(numVertices++); + t_vertices[2].setId(numVertices++); + + vertices.add(t.getVertices()[0]); + vertices.add(t.getVertices()[1]); + vertices.add(t.getVertices()[2]); + + indicies.put((short) t.getVertices()[0].getId()); + indicies.put((short) t.getVertices()[1].getId()); + indicies.put((short) t.getVertices()[2].getId()); + } + else{ + PointTex v1 = t_vertices[0]; + PointTex v2 = t_vertices[1]; + PointTex v3 = t_vertices[2]; + + indicies.put((short) v1.getId()); + indicies.put((short) v2.getId()); + indicies.put((short) v3.getId()); + } + } + indicies.rewind(); + + FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); + for(PointTex v:vertices){ + verticesBuffer.put(v.getX()); + if(flipped){ + verticesBuffer.put(-1*v.getY()); + } + else{ + verticesBuffer.put(v.getY()); + } + verticesBuffer.put(v.getZ()); + } + verticesBuffer.rewind(); + + FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); + for(PointTex v:vertices){ + float[] tex = v.getTexCoord(); + texCoordBuffer.put(tex[0]); + texCoordBuffer.put(tex[1]); + } + texCoordBuffer.rewind(); + + vboIds = IntBuffer.allocate(numBuffers); + gl.glGenBuffers(numBuffers, vboIds); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); // vertices + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, numVertices * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); //texture + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, numVertices * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); //triangles + gl.glBufferData(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, triangles.size()* 3 * Buffers.SIZEOF_SHORT, indicies, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, 0); + + dirty = false; + } + + private void render() { + GL2ES2 gl = context.getGL().getGL2ES2(); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); + gl.glEnableVertexAttribArray(VERTEX_POS_INDX); + gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); + gl.glEnableVertexAttribArray(TEX_COORD); + gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); + gl.glDrawElements(GL2ES2.GL_TRIANGLES, triangles.size() * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + } + + public void render(PMVMatrix matrix, int vp_width, int vp_height, int width){ + render(); + } + + public void addTriangles(ArrayList> tris) { + triangles.addAll(tris); + dirty = true; + } + + public int getNumVertices(){ + return numVertices; + } + + public void addVertices(ArrayList verts){ + vertices.addAll(verts); + numVertices = vertices.size(); + dirty = true; + } + + public boolean isDirty(){ + return dirty; + } + + public void destroy() { + GL2ES2 gl = context.getGL().getGL2ES2(); + gl.glDeleteBuffers(numBuffers, vboIds); + } + + public boolean isFlipped() { + return flipped; + } + + public void setFlipped(boolean flipped) { + this.flipped = flipped; + } +} diff --git a/src/jogamp/graph/curve/tess/GraphOutline.java b/src/jogamp/graph/curve/tess/GraphOutline.java new file mode 100644 index 000000000..cf73ab379 --- /dev/null +++ b/src/jogamp/graph/curve/tess/GraphOutline.java @@ -0,0 +1,81 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.tess; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.Outline; +import com.jogamp.graph.geom.PointTex; + +public class GraphOutline { + final private Outline outline; + final private ArrayList> controlpoints = new ArrayList>(3); + + public GraphOutline(){ + this.outline = new Outline(); + } + + /**Create a control polyline of control vertices + * the curve pieces can be identified by onCurve flag + * of each cp the control polyline is open by default + */ + public GraphOutline(Outline ol){ + this.outline = ol; + ArrayList vertices = this.outline.getVertices(); + for(T v:vertices){ + this.controlpoints.add(new GraphPoint(v)); + } + } + + public Outline getOutline() { + return outline; + } + + /*public void setOutline(Outline outline) { + this.outline = outline; + }*/ + + + public ArrayList> getGraphPoint() { + return controlpoints; + } + + public ArrayList getPoints() { + return outline.getVertices(); + } + + /*public void setControlpoints(ArrayList> controlpoints) { + this.controlpoints = controlpoints; + }*/ + + public void addVertex(GraphPoint v) { + controlpoints.add(v); + outline.addVertex(v.getPoint()); + } + +} diff --git a/src/jogamp/graph/curve/tess/GraphPoint.java b/src/jogamp/graph/curve/tess/GraphPoint.java new file mode 100644 index 000000000..87d0b9929 --- /dev/null +++ b/src/jogamp/graph/curve/tess/GraphPoint.java @@ -0,0 +1,120 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.tess; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.PointTex; + +public class GraphPoint { + private T point; + private ArrayList> edges = null; + private boolean boundaryContained = false; + + public GraphPoint(T point) { + this.point = point; + } + + public T getPoint() { + return point; + } + + public float getX(){ + return point.getX(); + } + + public float getY(){ + return point.getY(); + } + + public float getZ(){ + return point.getZ(); + } + public float[] getCoord() { + return point.getCoord(); + } + + public void setPoint(T point) { + this.point = point; + } + + public ArrayList> getEdges() { + return edges; + } + + public void setEdges(ArrayList> edges) { + this.edges = edges; + } + + public void addEdge(HEdge edge){ + if(edges == null){ + edges = new ArrayList>(); + } + edges.add(edge); + } + public void removeEdge(HEdge edge){ + if(edges == null) + return; + edges.remove(edge); + if(edges.size() == 0){ + edges = null; + } + } + public HEdge findNextEdge(GraphPoint nextVert){ + for(HEdge e:edges){ + if(e.getNext().getGraphPoint() == nextVert){ + return e; + } + } + return null; + } + public HEdge findBoundEdge(){ + for(HEdge e:edges){ + if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){ + return e; + } + } + return null; + } + public HEdge findPrevEdge(GraphPoint prevVert){ + for(HEdge e:edges){ + if(e.getPrev().getGraphPoint() == prevVert){ + return e; + } + } + return null; + } + + public boolean isBoundaryContained() { + return boundaryContained; + } + + public void setBoundaryContained(boolean boundaryContained) { + this.boundaryContained = boundaryContained; + } +} diff --git a/src/jogamp/graph/curve/tess/HEdge.java b/src/jogamp/graph/curve/tess/HEdge.java new file mode 100644 index 000000000..acb32cb4d --- /dev/null +++ b/src/jogamp/graph/curve/tess/HEdge.java @@ -0,0 +1,131 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.tess; + +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Triangle; + + +public class HEdge { + public static int BOUNDARY = 3; + public static int INNER = 1; + public static int HOLE = 2; + + private GraphPoint vert; + private HEdge prev = null; + private HEdge next = null; + private HEdge sibling = null; + private int type = BOUNDARY; + private Triangle triangle = null; + + public HEdge(GraphPoint vert, int type) { + this.vert = vert; + this.type = type; + } + + public HEdge(GraphPoint vert, HEdge prev, HEdge next, HEdge sibling, int type) { + this.vert = vert; + this.prev = prev; + this.next = next; + this.sibling = sibling; + this.type = type; + } + + public HEdge(GraphPoint vert, HEdge prev, HEdge next, HEdge sibling, int type, + Triangle triangle) { + this.vert = vert; + this.prev = prev; + this.next = next; + this.sibling = sibling; + this.type = type; + this.triangle = triangle; + } + + public GraphPoint getGraphPoint() { + return vert; + } + + public void setVert(GraphPoint vert) { + this.vert = vert; + } + + public HEdge getPrev() { + return prev; + } + + public void setPrev(HEdge prev) { + this.prev = prev; + } + + public HEdge getNext() { + return next; + } + + public void setNext(HEdge next) { + this.next = next; + } + + public HEdge getSibling() { + return sibling; + } + + public void setSibling(HEdge sibling) { + this.sibling = sibling; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public Triangle getTriangle() { + return triangle; + } + + public void setTriangle(Triangle triangle) { + this.triangle = triangle; + } + + public static void connect(HEdge first, HEdge next){ + first.setNext(next); + next.setPrev(first); + } + + public static void makeSiblings(HEdge first, HEdge second){ + first.setSibling(second); + second.setSibling(first); + } + + public boolean vertexOnCurveVertex(){ + return vert.getPoint().isOnCurve(); + } + +} diff --git a/src/jogamp/graph/curve/tess/Loop.java b/src/jogamp/graph/curve/tess/Loop.java new file mode 100644 index 000000000..caebd64e4 --- /dev/null +++ b/src/jogamp/graph/curve/tess/Loop.java @@ -0,0 +1,376 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.tess; + +import java.util.ArrayList; + +import jogamp.graph.math.VectorFloatUtil; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Triangle; + +public class Loop { + private HEdge root = null; + private AABBox box = new AABBox(); + private GraphOutline initialOutline = null; + + public Loop(GraphOutline polyline, int direction){ + initialOutline = polyline; + this.root = initFromPolyline(initialOutline, direction); + } + + public HEdge getHEdge(){ + return root; + } + + public Triangle cut(boolean delaunay){ + if(isSimplex()){ + @SuppressWarnings("unchecked") + Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(), + root.getNext().getNext().getGraphPoint().getPoint()); + t.setVerticesBoundary(checkVerticesBoundary(root)); + return t; + } + HEdge prev = root.getPrev(); + HEdge next1 = root.getNext(); + + HEdge next2 =findClosestValidNeighbor(next1.getNext(), delaunay); + if(next2 == null){ + root = root.getNext(); + return null; + } + + GraphPoint v1 = root.getGraphPoint(); + GraphPoint v2 = next1.getGraphPoint(); + GraphPoint v3 = next2.getGraphPoint(); + + HEdge v3Edge = new HEdge(v3, HEdge.INNER); + + HEdge.connect(v3Edge, root); + HEdge.connect(next1, v3Edge); + + HEdge v3EdgeSib = v3Edge.getSibling(); + if(v3EdgeSib == null){ + v3EdgeSib = new HEdge(v3Edge.getNext().getGraphPoint(), HEdge.INNER); + HEdge.makeSiblings(v3Edge, v3EdgeSib); + } + + HEdge.connect(prev, v3EdgeSib); + HEdge.connect(v3EdgeSib, next2); + + Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root); + this.root = next2; + return t; + } + + public boolean isSimplex(){ + return (root.getNext().getNext().getNext() == root); + } + + /**Create a connected list of half edges (loop) + * from the boundary profile + * @param direction requested winding of edges (CCW or CW) + */ + private HEdge initFromPolyline(GraphOutline outline, int direction){ + ArrayList> vertices = outline.getGraphPoint(); + + if(vertices.size()<3) { + throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size()); + } + boolean isCCW = VectorFloatUtil.ccw(vertices.get(0).getPoint(), vertices.get(1).getPoint(), + vertices.get(2).getPoint()); + boolean invert = isCCW && (direction == VectorFloatUtil.CW); + + HEdge firstEdge = null; + HEdge lastEdge = null; + int index =0; + int max = vertices.size(); + + int edgeType = HEdge.BOUNDARY; + if(invert){ + index = vertices.size() -1; + max = -1; + edgeType = HEdge.HOLE; + } + + while(index != max){ + GraphPoint v1 = vertices.get(index); + box.resize(v1.getX(), v1.getY(), v1.getZ()); + + HEdge edge = new HEdge(v1, edgeType); + + v1.addEdge(edge); + if(lastEdge != null){ + lastEdge.setNext(edge); + edge.setPrev(lastEdge); + } + else{ + firstEdge = edge; + } + + if(!invert){ + if(index == vertices.size()-1){ + edge.setNext(firstEdge); + firstEdge.setPrev(edge); + } + } + else if (index == 0){ + edge.setNext(firstEdge); + firstEdge.setPrev(edge); + } + + lastEdge = edge; + + if(!invert){ + index++; + } + else{ + index--; + } + } + return firstEdge; + } + + public void addConstraintCurve(GraphOutline polyline) { + // GraphOutline outline = new GraphOutline(polyline); + /**needed to generate vertex references.*/ + initFromPolyline(polyline, VectorFloatUtil.CW); + + GraphPoint v3 = locateClosestVertex(polyline); + HEdge v3Edge = v3.findBoundEdge(); + HEdge v3EdgeP = v3Edge.getPrev(); + HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER); + + HEdge.connect(root.getPrev(), crossEdge); + HEdge.connect(crossEdge, v3Edge); + + HEdge crossEdgeSib = crossEdge.getSibling(); + if(crossEdgeSib == null) { + crossEdgeSib = new HEdge(crossEdge.getNext().getGraphPoint(), HEdge.INNER); + HEdge.makeSiblings(crossEdge, crossEdgeSib); + } + + HEdge.connect(v3EdgeP, crossEdgeSib); + HEdge.connect(crossEdgeSib, root); + } + + /** Locates the vertex and update the loops root + * to have (root + vertex) as closest pair + * @param polyline the control polyline + * to search for closestvertices + * @return the vertex that is closest to the newly set root Hedge. + */ + private GraphPoint locateClosestVertex(GraphOutline polyline) { + HEdge closestE = null; + GraphPoint closestV = null; + + float minDistance = Float.MAX_VALUE; + boolean inValid = false; + ArrayList> initVertices = initialOutline.getGraphPoint(); + ArrayList> vertices = polyline.getGraphPoint(); + + for(int i=0; i< initVertices.size()-1; i++){ + GraphPoint v = initVertices.get(i); + GraphPoint nextV = initVertices.get(i+1); + for(GraphPoint cand:vertices){ + float distance = VectorFloatUtil.computeLength(v.getCoord(), cand.getCoord()); + if(distance < minDistance){ + for (GraphPoint vert:vertices){ + if(vert == v || vert == nextV || vert == cand) + continue; + inValid = VectorFloatUtil.inCircle(v.getPoint(), nextV.getPoint(), + cand.getPoint(), vert.getPoint()); + if(inValid){ + break; + } + } + if(!inValid){ + closestV = cand; + minDistance = distance; + closestE = v.findBoundEdge(); + } + } + + } + } + + if(closestE != null){ + root = closestE; + } + + return closestV; + } + + private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) { + HEdge next = root.getNext(); + + if(!VectorFloatUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), + edge.getGraphPoint().getPoint())){ + return null; + } + + HEdge candEdge = edge; + boolean inValid = false; + + if(delaunay){ + T cand = candEdge.getGraphPoint().getPoint(); + HEdge e = candEdge.getNext(); + while (e != candEdge){ + if(e.getGraphPoint() == root.getGraphPoint() + || e.getGraphPoint() == next.getGraphPoint() + || e.getGraphPoint().getPoint() == cand){ + e = e.getNext(); + continue; + } + inValid = VectorFloatUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), + cand, e.getGraphPoint().getPoint()); + if(inValid){ + break; + } + e = e.getNext(); + } + } + if(!inValid){ + return candEdge; + } + return null; + } + + /** Create a triangle from the param vertices only if + * the triangle is valid. IE not outside region. + * @param v1 vertex 1 + * @param v2 vertex 2 + * @param v3 vertex 3 + * @param root and edge of this triangle + * @return the triangle iff it satisfies, null otherwise + */ + private Triangle createTriangle(T v1, T v2, T v3, HEdge rootT){ + @SuppressWarnings("unchecked") + Triangle t = new Triangle(v1, v2, v3); + t.setVerticesBoundary(checkVerticesBoundary(rootT)); + return t; + } + + private boolean[] checkVerticesBoundary(HEdge rootT) { + boolean[] boundary = new boolean[3]; + HEdge e1 = rootT; + HEdge e2 = rootT.getNext(); + HEdge e3 = rootT.getNext().getNext(); + + if(e1.getGraphPoint().isBoundaryContained()){ + boundary[0] = true; + } + if(e2.getGraphPoint().isBoundaryContained()){ + boundary[1] = true; + } + if(e3.getGraphPoint().isBoundaryContained()){ + boundary[2] = true; + } + return boundary; + } + + + /** Check if vertex inside the Loop + * @param vertex the Vertex + * @return true if the vertex is inside, false otherwise + */ + public boolean checkInside(T vertex) { + if(!box.contains(vertex.getX(), vertex.getY(), vertex.getZ())){ + return false; + } + + float[] center = box.getCenter(); + + int hits = 0; + HEdge current = root; + HEdge next = root.getNext(); + while(next!= root){ + if(current.getType() == HEdge.INNER || next.getType() == HEdge.INNER){ + current = next; + next = current.getNext(); + continue; + } + + T vert1 = current.getGraphPoint().getPoint(); + T vert2 = next.getGraphPoint().getPoint(); + + /** The ray is P0+s*D0, where P0 is the ray origin, D0 is a direction vector and s >= 0. + * The segment is P1+t*D1, where P1 and P1+D1 are the endpoints, and 0 <= t <= 1. + * perp(x,y) = (y,-x). + * if Dot(perp(D1),D0) is not zero, + * s = Dot(perp(D1),P1-P0)/Dot(perp(D1),D0) + * t = Dot(perp(D0),P1-P0)/Dot(perp(D1),D0) + */ + + float[] d0 = new float[]{center[0] - vertex.getX(), center[1]-vertex.getY(), + center[2]-vertex.getZ()}; + float[] d1 = {vert2.getX() - vert1.getX(), vert2.getY() - vert1.getY(), + vert2.getZ() - vert1.getZ()}; + + float[] prepD1 = {d1[1],-1*d1[0], d1[2]}; + float[] prepD0 = {d0[1],-1*d0[0], d0[2]}; + + float[] p0p1 = new float[]{vert1.getX() - vertex.getX(), vert1.getY() - vertex.getY(), + vert1.getZ() - vertex.getZ()}; + + float dotD1D0 = VectorFloatUtil.dot(prepD1, d0); + if(dotD1D0 == 0){ + /** ray parallel to segment */ + current = next; + next = current.getNext(); + continue; + } + + float s = VectorFloatUtil.dot(prepD1,p0p1)/dotD1D0; + float t = VectorFloatUtil.dot(prepD0,p0p1)/dotD1D0; + + if(s >= 0 && t >= 0 && t<= 1){ + hits++; + } + current = next; + next = current.getNext(); + } + + if(hits % 2 != 0){ + /** check if hit count is even */ + return true; + } + return false; + } + + public int computeLoopSize(){ + int size = 0; + HEdge e = root; + do{ + size++; + e = e.getNext(); + }while(e != root); + return size; + } +} diff --git a/src/jogamp/graph/curve/text/GlyphShape.java b/src/jogamp/graph/curve/text/GlyphShape.java new file mode 100644 index 000000000..9862a5407 --- /dev/null +++ b/src/jogamp/graph/curve/text/GlyphShape.java @@ -0,0 +1,169 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.text; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.plane.PathIterator; +import com.jogamp.graph.geom.Line; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Triangle; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.math.Quaternion; + +public class GlyphShape { + + private Quaternion quat= null; + private int numVertices = 0; + private OutlineShape shape = null; + + /** Create a new Glyph shape + * based on Parametric curve control polyline + */ + public GlyphShape(Point.Factory factory){ + shape = new OutlineShape(factory); + } + + /** Create a GlyphShape from a font Path Iterator + * @param pathIterator the path iterator + * + * @see PathIterator + */ + public GlyphShape(Point.Factory factory, PathIterator pathIterator){ + this(factory); + + if(null != pathIterator){ + while(!pathIterator.isDone()){ + float[] coords = new float[6]; + int segmentType = pathIterator.currentSegment(coords); + addOutlineVerticesFromGlyphVector(coords, segmentType); + + pathIterator.next(); + } + } + shape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + } + + public final Point.Factory pointFactory() { return shape.pointFactory(); } + + private void addVertexToLastOutline(PointTex vertex){ + shape.addVertex(vertex); + } + + private void addOutlineVerticesFromGlyphVector(float[] coords, int segmentType){ + if(segmentType == PathIterator.SEG_MOVETO){ + if(!shape.getLastOutline().isEmpty()){ + shape.addEmptyOutline(); + } + PointTex vert = pointFactory().create(coords[0],coords[1]); + vert.setOnCurve(true); + addVertexToLastOutline(vert); + + numVertices++; + } + else if(segmentType == PathIterator.SEG_LINETO){ + PointTex vert1 = pointFactory().create(coords[0],coords[1]); + vert1.setOnCurve(true); + addVertexToLastOutline(vert1); + + numVertices++; + } + else if(segmentType == PathIterator.SEG_QUADTO){ + PointTex vert1 = pointFactory().create(coords[0],coords[1]); + vert1.setOnCurve(false); + addVertexToLastOutline(vert1); + + PointTex vert2 = pointFactory().create(coords[2],coords[3]); + vert2.setOnCurve(true); + addVertexToLastOutline(vert2); + + numVertices+=2; + } + else if(segmentType == PathIterator.SEG_CUBICTO){ + PointTex vert1 = pointFactory().create(coords[0],coords[1]); + vert1.setOnCurve(false); + addVertexToLastOutline(vert1); + + PointTex vert2 = pointFactory().create(coords[2],coords[3]); + vert2.setOnCurve(false); + addVertexToLastOutline(vert2); + + PointTex vert3 = pointFactory().create(coords[4],coords[5]); + vert3.setOnCurve(true); + addVertexToLastOutline(vert3); + + numVertices+=3; + } + else if(segmentType == PathIterator.SEG_CLOSE){ + shape.closeLastOutline(); + } + } + + public int getNumVertices() { + return numVertices; + } + + /** Get the rotational Quaternion attached to this Shape + * @return the Quaternion Object + */ + public Quaternion getQuat() { + return quat; + } + + /** Set the Quaternion that shall defien the rotation + * of this shape. + * @param quat + */ + public void setQuat(Quaternion quat) { + this.quat = quat; + } + + /** Triangluate the glyph shape + * @param sharpness sharpness of the curved regions default = 0.5 + * @return ArrayList of triangles which define this shape + */ + public ArrayList> triangulate(float sharpness){ + return shape.triangulate(sharpness); + } + + /** Get the list of Vertices of this Object + * @return arrayList of Vertices + */ + public ArrayList getVertices(){ + return shape.getVertices(); + } + + /** Get the list of AA lines defined by this object + * @return arraylist of lines + */ + public ArrayList> getLines(){ + return shape.getLines(); + } +} diff --git a/src/jogamp/graph/curve/text/GlyphString.java b/src/jogamp/graph/curve/text/GlyphString.java new file mode 100644 index 000000000..d85e59c43 --- /dev/null +++ b/src/jogamp/graph/curve/text/GlyphString.java @@ -0,0 +1,163 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.text; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.plane.AffineTransform; +import com.jogamp.graph.geom.plane.Path2D; +import com.jogamp.graph.geom.plane.PathIterator; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.opengl.Vertex; + +import javax.media.opengl.GLContext; + + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.RegionFactory; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class GlyphString { + private final Point.Factory pointFactory; + private ArrayList glyphs = new ArrayList(); + private String str = ""; + private String fontname = ""; + private Region region; + + private Vertex origin = new Vertex(); + + /** Create a new GlyphString object + * @param fontname the name of the font that this String is + * associated with + * @param str the string object + */ + public GlyphString(Point.Factory factory, String fontname, String str){ + pointFactory = factory; + this.fontname = fontname; + this.str = str; + } + + public final Point.Factory pointFactory() { return pointFactory; } + + public void addGlyphShape(GlyphShape glyph){ + glyphs.add(glyph); + } + public String getString(){ + return str; + } + + /** Creates the Curve based Glyphs from a Font + * @param paths a list of FontPath2D objects that define the outline + * @param affineTransform a global affine transformation applied to the paths. + */ + public void createfromFontPath(Path2D[] paths, AffineTransform affineTransform){ + final int numGlyps = paths.length; + for (int index=0;index> initializeTriangles(float sharpness){ + ArrayList> triangles = new ArrayList>(); + for(GlyphShape glyph:glyphs){ + ArrayList> tris = glyph.triangulate(sharpness); + triangles.addAll(tris); + } + return triangles; + } + + /** Generate a OGL Region to represent this Object. + * @param context the GLContext which the region is defined by. + * @param shaprness the curvature sharpness of the object. + * @param st shader state + */ + public void generateRegion(GLContext context, float shaprness, ShaderState st, int type){ + region = RegionFactory.create(context, st, type); + region.setFlipped(true); + + ArrayList> tris = initializeTriangles(shaprness); + region.addTriangles(tris); + + int numVertices = region.getNumVertices(); + for(GlyphShape glyph:glyphs){ + ArrayList gVertices = glyph.getVertices(); + for(PointTex vert:gVertices){ + vert.setId(numVertices++); + } + region.addVertices(gVertices); + } + + /** initialize the region */ + region.update(); + } + + /** Generate a Hashcode for this object + * @return a string defining the hashcode + */ + public String getTextHashCode(){ + return "" + fontname.hashCode() + str.hashCode(); + } + + /** Render the Object based using the associated Region + * previously generated. + */ + public void renderString3D() { + region.render(null, 0, 0, 0); + } + /** Render the Object based using the associated Region + * previously generated. + */ + public void renderString3D(PMVMatrix matrix, int vp_width, int vp_height, int size) { + region.render(matrix, vp_width, vp_height, size); + } + + /** Get the Origion of this GlyphString + * @return + */ + public PointTex getOrigin() { + return origin; + } + + /** Destroy the associated OGL objects + */ + public void destroy(){ + region.destroy(); + } +} diff --git a/src/jogamp/graph/math/VectorFloatUtil.java b/src/jogamp/graph/math/VectorFloatUtil.java new file mode 100755 index 000000000..172cacd09 --- /dev/null +++ b/src/jogamp/graph/math/VectorFloatUtil.java @@ -0,0 +1,293 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.math; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.Point; + +public class VectorFloatUtil { + + public static final int CW = -1; + public static final int CCW = 1; + public static final int COLLINEAR = 0; + + /** compute the dot product of two points + * @param vec1 vector 1 + * @param vec2 vector 2 + * @return the dot product as float + */ + public static float dot(float[] vec1, float[] vec2) + { + return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]); + } + /** Normalize a vector + * @param vector input vector + * @return normalized vector + */ + public static float[] normalize(float[] vector) + { + float[] newVector = new float[3]; + + float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); + if(d> 0.0f) + { + newVector[0] = vector[0]/d; + newVector[1] = vector[1]/d; + newVector[2] = vector[2]/d; + } + return newVector; + } + + /** Scales a vector by param + * @param vector input vector + * @param scale constant to scale by + * @return scaled vector + */ + public static float[] scale(float[] vector, float scale) + { + float[] newVector = new float[3]; + + newVector[0] = vector[0]*scale; + newVector[1] = vector[1]*scale; + newVector[2] = vector[2]*scale; + return newVector; + } + + /** Adds to vectors + * @param v1 vector 1 + * @param v2 vector 2 + * @return v1 + v2 + */ + public static float[] vectorAdd(float[] v1, float[] v2) + { + float[] newVector = new float[3]; + + newVector[0] = v1[0] + v2[0]; + newVector[1] = v1[1] + v2[1]; + newVector[2] = v1[2] + v2[2]; + return newVector; + } + + /** cross product vec1 x vec2 + * @param vec1 vector 1 + * @param vec2 vecttor 2 + * @return the resulting vector + */ + public static float[] cross(float[] vec1, float[] vec2) + { + float[] out = new float[3]; + + out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2]; + out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0]; + out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1]; + + return out; + } + + /** Column Matrix Vector multiplication + * @param colMatrix column matrix (4x4) + * @param vec vector(x,y,z) + * @return result new float[3] + */ + public static float[] colMatrixVectorMult(float[] colMatrix, float[] vec) + { + float[] out = new float[3]; + + out[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12]; + out[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13]; + out[2] = vec[0]*colMatrix[2] + vec[1]*colMatrix[6] + vec[2]*colMatrix[10] + colMatrix[14]; + + return out; + } + + /** Matrix Vector multiplication + * @param rawMatrix column matrix (4x4) + * @param vec vector(x,y,z) + * @return result new float[3] + */ + public static float[] rowMatrixVectorMult(float[] rawMatrix, float[] vec) + { + float[] out = new float[3]; + + out[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3]; + out[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7]; + out[2] = vec[0]*rawMatrix[8] + vec[1]*rawMatrix[9] + vec[2]*rawMatrix[10] + rawMatrix[11]; + + return out; + } + + /** Calculate the midpoint of two values + * @param p1 first value + * @param p2 second vale + * @return midpoint + */ + public static float mid(float p1, float p2) + { + return (p1+p2)/2.0f; + } + /** Calculate the midpoint of two points + * @param p1 first point + * @param p2 second point + * @return midpoint + */ + public static float[] mid(float[] p1, float[] p2) + { + float[] midPoint = new float[3]; + midPoint[0] = (p1[0] + p2[0])/2.0f; + midPoint[1] = (p1[1] + p2[1])/2.0f; + midPoint[2] = (p1[2] + p2[2])/2.0f; + + return midPoint; + } + /** Compute the norm of a vector + * @param vec vector + * @return vorm + */ + public static float norm(float[] vec) + { + return MathFloat.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); + } + /** Compute distance between 2 points + * @param p0 a ref point on the line + * @param vec vector representing the direction of the line + * @param point the point to compute the relative distance of + * @return distance float + */ + public static float computeLength(float[] p0, float[] point) + { + float[] w = new float[]{point[0]-p0[0],point[1]-p0[1],point[2]-p0[2]}; + + float distance = MathFloat.sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]); + + return distance; + } + + /**Check equality of 2 vec3 vectors + * @param v1 vertex 1 + * @param v2 vertex 2 + * @return + */ + public static boolean checkEquality(float[] v1, float[] v2) + { + if(Float.compare(v1[0], v2[0]) == 0 + && Float.compare(v1[1] , v2[1]) == 0 + && Float.compare(v1[2], v2[2]) == 0 ) + return true; + return false; + } + + /** Compute the determinant of 3 vectors + * @param a vector 1 + * @param b vector 2 + * @param c vector 3 + * @return the determinant value + */ + public static float computeDeterminant(float[] a, float[] b, float[] c) + { + float area = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0]; + return area; + } + + /** Check if three vertices are colliniear + * @param v1 vertex 1 + * @param v2 vertex 2 + * @param v3 vertex 3 + * @return true if collinear, false otherwise + */ + public static boolean checkCollinear(float[] v1, float[] v2, float[] v3) + { + return (computeDeterminant(v1, v2, v3) == VectorFloatUtil.COLLINEAR); + } + + /** Compute Vector + * @param v1 vertex 1 + * @param v2 vertex2 2 + * @return Vector V1V2 + */ + public static float[] computeVector(float[] v1, float[] v2) + { + float[] vector = new float[3]; + vector[0] = v2[0] - v1[0]; + vector[1] = v2[1] - v1[1]; + vector[2] = v2[2] - v1[2]; + return vector; + } + + /** Check if vertices in triangle circumcircle + * @param a triangle vertex 1 + * @param b triangle vertex 2 + * @param c triangle vertex 3 + * @param d vertex in question + * @return true if the vertex d is inside the circle defined by the + * vertices a, b, c. from paper by Guibas and Stolfi (1985). + */ + public static boolean inCircle(Point a, Point b, Point c, Point d){ + return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) - + (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) + + (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) - + (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0; + } + + /** Computes oriented area of a triangle + * @param a first vertex + * @param b second vertex + * @param c third vertex + * @return compute twice the area of the oriented triangle (a,b,c), the area + * is positive if the triangle is oriented counterclockwise. + */ + public static float triArea(Point a, Point b, Point c){ + return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX()); + } + + /** Check if points are in ccw order + * @param a first vertex + * @param b second vertex + * @param c third vertex + * @return true if the points a,b,c are in a ccw order + */ + public static boolean ccw(Point a, Point b, Point c){ + return triArea(a,b,c) > 0; + } + + /** Computes the area of a list of vertices to check if ccw + * @param vertices + * @return positve area if ccw else negative area value + */ + public static float area(ArrayList vertices) { + int n = vertices.size(); + float area = 0.0f; + for (int p = n - 1, q = 0; q < n; p = q++) + { + float[] pCoord = vertices.get(p).getCoord(); + float[] qCoord = vertices.get(q).getCoord(); + area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1]; + } + return area; + } +} -- cgit v1.2.3 From c87998372f09466dd682f208fcddebae954c7af8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 04:18:23 +0100 Subject: Add LICENSE file --- LICENSE.txt | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 000000000..58d8691de --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,90 @@ + +L.1) The JOGL source tree contains code from the JogAmp Community + which is covered by the Simplified BSD 2-clause license: + + Copyright 2010 JogAmp Community. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The views and conclusions contained in the software and documentation are those of the + authors and should not be interpreted as representing official policies, either expressed + or implied, of JogAmp Community. + + You can address the JogAmp Community via: + Web http://jogamp.org/ + Forum/Mailinglist http://jogamp.762907.n3.nabble.com/ + JogAmp Channel server: conference.jabber.org room: jogamp + Repository http://jogamp.org/git/ + Email mediastream _at_ jogamp _dot_ org + + +++++ + +L.2) The JOGL source tree contains code from The Apache Software Foundation + which is covered by the Apache License Version 2.0 + +Apache Harmony - Open Source Java SE +===================================== + + + +Author: The Apache Software Foundation (http://www.apache.org/). + +Copyright 2006, 2010 The Apache Software Foundation. + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +Files: + src/com/jogamp/graph/geom/plane/AffineTransform.java + src/com/jogamp/graph/geom/plane/IllegalPathStateException.java + src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java + src/com/jogamp/graph/geom/plane/PathIterator.java + src/com/jogamp/graph/geom/plane/Path2D.java + src/jogamp/graph/math/plane/Crossing.java + src/org/apache/harmony/misc/HashCode.java + +++++ + +L.3) The JOGL source tree contains code from David Schweinsberg + which is covered by the Apache License Version 2.0 + +Typecast +======== + +Typecast is a font development environment for OpenType font technology. + + + +Author: David Schweinsberg + +Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +Files: + src/net/java/dev/typecast/** + +++++ + -- cgit v1.2.3 From 56de85032f687748d99af63f90b6798d14b9c04b Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 08:51:24 +0100 Subject: Make com.jogamp.graph.geom.plane non public: jogamp.graph.geom.plane, this incl. creating the non public FontInt interface for Path2D access --- .../jogamp/graph/curve/text/HwTextRenderer.java | 7 +- src/com/jogamp/graph/font/Font.java | 8 - .../jogamp/graph/geom/plane/AffineTransform.java | 573 --------------------- .../geom/plane/IllegalPathStateException.java | 34 -- .../plane/NoninvertibleTransformException.java | 31 -- src/com/jogamp/graph/geom/plane/Path2D.java | 430 ---------------- src/com/jogamp/graph/geom/plane/PathIterator.java | 42 -- src/jogamp/graph/curve/text/GlyphShape.java | 3 +- src/jogamp/graph/curve/text/GlyphString.java | 7 +- src/jogamp/graph/font/FontInt.java | 45 ++ src/jogamp/graph/font/typecast/TypecastFont.java | 7 +- src/jogamp/graph/font/typecast/TypecastGlyph.java | 8 +- .../graph/font/typecast/TypecastRenderer.java | 5 +- src/jogamp/graph/geom/plane/AffineTransform.java | 573 +++++++++++++++++++++ .../geom/plane/IllegalPathStateException.java | 34 ++ .../plane/NoninvertibleTransformException.java | 31 ++ src/jogamp/graph/geom/plane/Path2D.java | 430 ++++++++++++++++ src/jogamp/graph/geom/plane/PathIterator.java | 42 ++ src/jogamp/graph/math/plane/Crossing.java | 4 +- 19 files changed, 1179 insertions(+), 1135 deletions(-) delete mode 100644 src/com/jogamp/graph/geom/plane/AffineTransform.java delete mode 100644 src/com/jogamp/graph/geom/plane/IllegalPathStateException.java delete mode 100644 src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java delete mode 100644 src/com/jogamp/graph/geom/plane/Path2D.java delete mode 100644 src/com/jogamp/graph/geom/plane/PathIterator.java create mode 100644 src/jogamp/graph/font/FontInt.java create mode 100644 src/jogamp/graph/geom/plane/AffineTransform.java create mode 100644 src/jogamp/graph/geom/plane/IllegalPathStateException.java create mode 100644 src/jogamp/graph/geom/plane/NoninvertibleTransformException.java create mode 100644 src/jogamp/graph/geom/plane/Path2D.java create mode 100644 src/jogamp/graph/geom/plane/PathIterator.java diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java index 5813225e4..61d8309c7 100644 --- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java +++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java @@ -39,14 +39,15 @@ import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; import jogamp.graph.curve.text.GlyphString; +import jogamp.graph.font.FontInt; import jogamp.graph.font.typecast.TypecastFontFactory; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.graph.curve.Region; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.geom.Point; import com.jogamp.graph.geom.PointTex; import com.jogamp.graph.geom.opengl.Vertex; @@ -299,7 +300,7 @@ public class HwTextRenderer { AffineTransform affineTransform = new AffineTransform(pointFactory); Path2D[] paths = new Path2D[str.length()]; - font.getOutline(str, affineTransform, paths); + ((FontInt)font).getOutline(str, affineTransform, paths); GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); glyphString.createfromFontPath(paths, affineTransform); diff --git a/src/com/jogamp/graph/font/Font.java b/src/com/jogamp/graph/font/Font.java index 5c26e8626..0abaad5b5 100644 --- a/src/com/jogamp/graph/font/Font.java +++ b/src/com/jogamp/graph/font/Font.java @@ -28,8 +28,6 @@ package com.jogamp.graph.font; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; public interface Font { @@ -60,8 +58,6 @@ public interface Font { public AABBox getBBox(); public float getAdvance(); public float getAdvanceForPixelSize(float pixelSize, boolean useFrationalMetrics); - public Path2D getPath(); - public Path2D getPathForPixelSize(float pixelSize); } @@ -74,9 +70,5 @@ public interface Font { public float getStringHeight(String string); public AABBox getStringBounds(CharSequence string); - public void getOutline(String string, - AffineTransform transform, - Path2D[] result); - public int getNumGlyphs(); } \ No newline at end of file diff --git a/src/com/jogamp/graph/geom/plane/AffineTransform.java b/src/com/jogamp/graph/geom/plane/AffineTransform.java deleted file mode 100644 index 321551edc..000000000 --- a/src/com/jogamp/graph/geom/plane/AffineTransform.java +++ /dev/null @@ -1,573 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package com.jogamp.graph.geom.plane; - -import java.io.IOException; -import java.io.Serializable; - -import jogamp.graph.math.MathFloat; -import org.apache.harmony.misc.HashCode; - -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.Point.Factory; - -public class AffineTransform implements Cloneable, Serializable { - - private static final long serialVersionUID = 1330973210523860834L; - - static final String determinantIsZero = "Determinant is zero"; - - public static final int TYPE_IDENTITY = 0; - public static final int TYPE_TRANSLATION = 1; - public static final int TYPE_UNIFORM_SCALE = 2; - public static final int TYPE_GENERAL_SCALE = 4; - public static final int TYPE_QUADRANT_ROTATION = 8; - public static final int TYPE_GENERAL_ROTATION = 16; - public static final int TYPE_GENERAL_TRANSFORM = 32; - public static final int TYPE_FLIP = 64; - public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; - public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION; - - /** - * The TYPE_UNKNOWN is an initial type value - */ - static final int TYPE_UNKNOWN = -1; - - /** - * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. - */ - static final float ZERO = (float) 1E-10; - - private final Point.Factory pointFactory; - - /** - * The values of transformation matrix - */ - float m00; - float m10; - float m01; - float m11; - float m02; - float m12; - - /** - * The transformation type - */ - transient int type; - - public AffineTransform(Factory factory) { - pointFactory = factory; - type = TYPE_IDENTITY; - m00 = m11 = 1.0f; - m10 = m01 = m02 = m12 = 0.0f; - } - - public AffineTransform(AffineTransform t) { - this.pointFactory = t.pointFactory; - this.type = t.type; - this.m00 = t.m00; - this.m10 = t.m10; - this.m01 = t.m01; - this.m11 = t.m11; - this.m02 = t.m02; - this.m12 = t.m12; - } - - public AffineTransform(Point.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { - pointFactory = factory; - this.type = TYPE_UNKNOWN; - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - } - - public AffineTransform(Point.Factory factory, float[] matrix) { - pointFactory = factory; - this.type = TYPE_UNKNOWN; - m00 = matrix[0]; - m10 = matrix[1]; - m01 = matrix[2]; - m11 = matrix[3]; - if (matrix.length > 4) { - m02 = matrix[4]; - m12 = matrix[5]; - } - } - - /* - * Method returns type of affine transformation. - * - * Transform matrix is - * m00 m01 m02 - * m10 m11 m12 - * - * According analytic geometry new basis vectors are (m00, m01) and (m10, m11), - * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1). - * Type transformations classification: - * TYPE_IDENTITY - new basis equals original one and zero translation - * TYPE_TRANSLATION - translation vector isn't zero - * TYPE_UNIFORM_SCALE - vectors length of new basis equals - * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal - * TYPE_FLIP - new basis vector orientation differ from original one - * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees - * TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle - * TYPE_GENERAL_TRANSFORM - transformation can't be inversed - */ - public int getType() { - if (type != TYPE_UNKNOWN) { - return type; - } - - int type = 0; - - if (m00 * m01 + m10 * m11 != 0.0) { - type |= TYPE_GENERAL_TRANSFORM; - return type; - } - - if (m02 != 0.0 || m12 != 0.0) { - type |= TYPE_TRANSLATION; - } else - if (m00 == 1.0 && m11 == 1.0 && m01 == 0.0 && m10 == 0.0) { - type = TYPE_IDENTITY; - return type; - } - - if (m00 * m11 - m01 * m10 < 0.0) { - type |= TYPE_FLIP; - } - - float dx = m00 * m00 + m10 * m10; - float dy = m01 * m01 + m11 * m11; - if (dx != dy) { - type |= TYPE_GENERAL_SCALE; - } else - if (dx != 1.0) { - type |= TYPE_UNIFORM_SCALE; - } - - if ((m00 == 0.0 && m11 == 0.0) || - (m10 == 0.0 && m01 == 0.0 && (m00 < 0.0 || m11 < 0.0))) - { - type |= TYPE_QUADRANT_ROTATION; - } else - if (m01 != 0.0 || m10 != 0.0) { - type |= TYPE_GENERAL_ROTATION; - } - - return type; - } - - public float getScaleX() { - return m00; - } - - public float getScaleY() { - return m11; - } - - public float getShearX() { - return m01; - } - - public float getShearY() { - return m10; - } - - public float getTranslateX() { - return m02; - } - - public float getTranslateY() { - return m12; - } - - public boolean isIdentity() { - return getType() == TYPE_IDENTITY; - } - - public void getMatrix(float[] matrix) { - matrix[0] = m00; - matrix[1] = m10; - matrix[2] = m01; - matrix[3] = m11; - if (matrix.length > 4) { - matrix[4] = m02; - matrix[5] = m12; - } - } - - public float getDeterminant() { - return m00 * m11 - m01 * m10; - } - - public void setTransform(float m00, float m10, float m01, float m11, float m02, float m12) { - this.type = TYPE_UNKNOWN; - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - } - - public void setTransform(AffineTransform t) { - type = t.type; - setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12); - } - - public void setToIdentity() { - type = TYPE_IDENTITY; - m00 = m11 = 1.0f; - m10 = m01 = m02 = m12 = 0.0f; - } - - public void setToTranslation(float mx, float my) { - m00 = m11 = 1.0f; - m01 = m10 = 0.0f; - m02 = mx; - m12 = my; - if (mx == 0.0f && my == 0.0f) { - type = TYPE_IDENTITY; - } else { - type = TYPE_TRANSLATION; - } - } - - public void setToScale(float scx, float scy) { - m00 = scx; - m11 = scy; - m10 = m01 = m02 = m12 = 0.0f; - if (scx != 1.0f || scy != 1.0f) { - type = TYPE_UNKNOWN; - } else { - type = TYPE_IDENTITY; - } - } - - public void setToShear(float shx, float shy) { - m00 = m11 = 1.0f; - m02 = m12 = 0.0f; - m01 = shx; - m10 = shy; - if (shx != 0.0f || shy != 0.0f) { - type = TYPE_UNKNOWN; - } else { - type = TYPE_IDENTITY; - } - } - - public void setToRotation(float angle) { - float sin = MathFloat.sin(angle); - float cos = MathFloat.cos(angle); - if (MathFloat.abs(cos) < ZERO) { - cos = 0.0f; - sin = sin > 0.0f ? 1.0f : -1.0f; - } else - if (MathFloat.abs(sin) < ZERO) { - sin = 0.0f; - cos = cos > 0.0f ? 1.0f : -1.0f; - } - m00 = m11 = cos; - m01 = -sin; - m10 = sin; - m02 = m12 = 0.0f; - type = TYPE_UNKNOWN; - } - - public void setToRotation(float angle, float px, float py) { - setToRotation(angle); - m02 = px * (1.0f - m00) + py * m10; - m12 = py * (1.0f - m00) - px * m10; - type = TYPE_UNKNOWN; - } - - public static AffineTransform getTranslateInstance(Point.Factory factory, float mx, float my) { - AffineTransform t = new AffineTransform(factory); - t.setToTranslation(mx, my); - return t; - } - - public static AffineTransform getScaleInstance(Point.Factory factory, float scx, float scY) { - AffineTransform t = new AffineTransform(factory); - t.setToScale(scx, scY); - return t; - } - - public static AffineTransform getShearInstance(Point.Factory factory, float shx, float shy) { - AffineTransform t = new AffineTransform(factory); - t.setToShear(shx, shy); - return t; - } - - public static AffineTransform getRotateInstance(Point.Factory factory, float angle) { - AffineTransform t = new AffineTransform(factory); - t.setToRotation(angle); - return t; - } - - public static AffineTransform getRotateInstance(Point.Factory factory, float angle, float x, float y) { - AffineTransform t = new AffineTransform(factory); - t.setToRotation(angle, x, y); - return t; - } - - public void translate(float mx, float my) { - concatenate(AffineTransform.getTranslateInstance(pointFactory, mx, my)); - } - - public void scale(float scx, float scy) { - concatenate(AffineTransform.getScaleInstance(pointFactory, scx, scy)); - } - - public void shear(float shx, float shy) { - concatenate(AffineTransform.getShearInstance(pointFactory, shx, shy)); - } - - public void rotate(float angle) { - concatenate(AffineTransform.getRotateInstance(pointFactory, angle)); - } - - public void rotate(float angle, float px, float py) { - concatenate(AffineTransform.getRotateInstance(pointFactory, angle, px, py)); - } - - /** - * Multiply matrix of two AffineTransform objects. - * The first argument's {@link Point.Factory} is being used. - * - * @param t1 - the AffineTransform object is a multiplicand - * @param t2 - the AffineTransform object is a multiplier - * @return an AffineTransform object that is a result of t1 multiplied by matrix t2. - */ - AffineTransform multiply(AffineTransform t1, AffineTransform t2) { - return new AffineTransform(t1.pointFactory, - t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00 - t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01 - t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10 - t1.m01 * t2.m10 + t1.m11 * t2.m11, // m11 - t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02 - t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12 - } - - public void concatenate(AffineTransform t) { - setTransform(multiply(t, this)); - } - - public void preConcatenate(AffineTransform t) { - setTransform(multiply(this, t)); - } - - public AffineTransform createInverse() throws NoninvertibleTransformException { - float det = getDeterminant(); - if (MathFloat.abs(det) < ZERO) { - throw new NoninvertibleTransformException(determinantIsZero); - } - return new AffineTransform( - this.pointFactory, - m11 / det, // m00 - -m10 / det, // m10 - -m01 / det, // m01 - m00 / det, // m11 - (m01 * m12 - m11 * m02) / det, // m02 - (m10 * m02 - m00 * m12) / det // m12 - ); - } - - public Point transform(Point src, Point dst) { - if (dst == null) { - dst = pointFactory.create(); - } - - float x = src.getX(); - float y = src.getY(); - - dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); - return dst; - } - - public void transform(Point[] src, int srcOff, Point[] dst, int dstOff, int length) { - while (--length >= 0) { - Point srcPoint = src[srcOff++]; - float x = srcPoint.getX(); - float y = srcPoint.getY(); - Point dstPoint = dst[dstOff]; - if (dstPoint == null) { - throw new IllegalArgumentException("dst["+dstOff+"] is null"); - } - dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); - dst[dstOff++] = dstPoint; - } - } - - public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) { - int step = 2; - if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { - srcOff = srcOff + length * 2 - 2; - dstOff = dstOff + length * 2 - 2; - step = -2; - } - while (--length >= 0) { - float x = src[srcOff + 0]; - float y = src[srcOff + 1]; - dst[dstOff + 0] = x * m00 + y * m01 + m02; - dst[dstOff + 1] = x * m10 + y * m11 + m12; - srcOff += step; - dstOff += step; - } - } - - public Point deltaTransform(Point src, Point dst) { - if (dst == null) { - dst = pointFactory.create(); - } - - float x = src.getX(); - float y = src.getY(); - - dst.setCoord(x * m00 + y * m01, x * m10 + y * m11); - return dst; - } - - public void deltaTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) { - while (--length >= 0) { - float x = src[srcOff++]; - float y = src[srcOff++]; - dst[dstOff++] = x * m00 + y * m01; - dst[dstOff++] = x * m10 + y * m11; - } - } - - public Point inverseTransform(Point src, Point dst) throws NoninvertibleTransformException { - float det = getDeterminant(); - if (MathFloat.abs(det) < ZERO) { - throw new NoninvertibleTransformException(determinantIsZero); - } - if (dst == null) { - dst = pointFactory.create(); - } - - float x = src.getX() - m02; - float y = src.getY() - m12; - - dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); - return dst; - } - - public void inverseTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) - throws NoninvertibleTransformException - { - float det = getDeterminant(); - if (MathFloat.abs(det) < ZERO) { - throw new NoninvertibleTransformException(determinantIsZero); - } - - while (--length >= 0) { - float x = src[srcOff++] - m02; - float y = src[srcOff++] - m12; - dst[dstOff++] = (x * m11 - y * m01) / det; - dst[dstOff++] = (y * m00 - x * m10) / det; - } - } - - public Path2D createTransformedShape(Path2D src) { - if (src == null) { - return null; - } - if (src instanceof Path2D) { - return ((Path2D)src).createTransformedShape(this); - } - PathIterator path = src.iterator(this); - Path2D dst = new Path2D(path.getWindingRule()); - dst.append(path, false); - return dst; - } - - @Override - public String toString() { - return - getClass().getName() + - "[[" + m00 + ", " + m01 + ", " + m02 + "], [" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - + m10 + ", " + m11 + ", " + m12 + "]]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } - - @Override - public int hashCode() { - HashCode hash = new HashCode(); - hash.append(m00); - hash.append(m01); - hash.append(m02); - hash.append(m10); - hash.append(m11); - hash.append(m12); - return hash.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof AffineTransform) { - AffineTransform t = (AffineTransform)obj; - return - m00 == t.m00 && m01 == t.m01 && - m02 == t.m02 && m10 == t.m10 && - m11 == t.m11 && m12 == t.m12; - } - return false; - } - - - /** - * Write AffineTrasform object to the output steam. - * @param stream - the output stream - * @throws IOException - if there are I/O errors while writing to the output strem - */ - private void writeObject(java.io.ObjectOutputStream stream) throws IOException { - stream.defaultWriteObject(); - } - - - /** - * Read AffineTransform object from the input stream - * @param stream - the input steam - * @throws IOException - if there are I/O errors while reading from the input strem - * @throws ClassNotFoundException - if class could not be found - */ - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { - stream.defaultReadObject(); - type = TYPE_UNKNOWN; - } - -} - diff --git a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java deleted file mode 100644 index 15f629b88..000000000 --- a/src/com/jogamp/graph/geom/plane/IllegalPathStateException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package com.jogamp.graph.geom.plane; - -public class IllegalPathStateException extends RuntimeException { - - private static final long serialVersionUID = -5158084205220481094L; - - public IllegalPathStateException() { - } - - public IllegalPathStateException(String s) { - super(s); - } - -} - diff --git a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java deleted file mode 100644 index cd1ec8d16..000000000 --- a/src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package com.jogamp.graph.geom.plane; - -public class NoninvertibleTransformException extends java.lang.Exception { - - private static final long serialVersionUID = 6137225240503990466L; - - public NoninvertibleTransformException(String s) { - super(s); - } - -} - diff --git a/src/com/jogamp/graph/geom/plane/Path2D.java b/src/com/jogamp/graph/geom/plane/Path2D.java deleted file mode 100644 index 031450c8e..000000000 --- a/src/com/jogamp/graph/geom/plane/Path2D.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package com.jogamp.graph.geom.plane; - -import java.util.NoSuchElementException; - -import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.opengl.Vertex; - -import jogamp.graph.math.plane.Crossing; - -public final class Path2D implements Cloneable { - - public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; - public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; - - static final String invalidWindingRuleValue = "Invalid winding rule value"; - static final String iteratorOutOfBounds = "Iterator out of bounds"; - - /** - * The buffers size - */ - private static final int BUFFER_SIZE = 10; - - /** - * The buffers capacity - */ - private static final int BUFFER_CAPACITY = 10; - - /** - * The point's types buffer - */ - byte[] types; - - /** - * The points buffer - */ - float[] points; - - /** - * The point's type buffer size - */ - int typeSize; - - /** - * The points buffer size - */ - int pointSize; - - /** - * The path rule - */ - int rule; - - /** - * The space amount in points buffer for different segmenet's types - */ - static int pointShift[] = { - 2, // MOVETO - 2, // LINETO - 4, // QUADTO - 6, // CUBICTO - 0}; // CLOSE - - /* - * GeneralPath path iterator - */ - class Iterator implements PathIterator { - - /** - * The current cursor position in types buffer - */ - int typeIndex; - - /** - * The current cursor position in points buffer - */ - int pointIndex; - - /** - * The source GeneralPath object - */ - Path2D p; - - /** - * The path iterator transformation - */ - AffineTransform t; - - /** - * Constructs a new GeneralPath.Iterator for given general path - * @param path - the source GeneralPath object - */ - Iterator(Path2D path) { - this(path, null); - } - - /** - * Constructs a new GeneralPath.Iterator for given general path and transformation - * @param path - the source GeneralPath object - * @param at - the AffineTransform object to apply rectangle path - */ - Iterator(Path2D path, AffineTransform at) { - this.p = path; - this.t = at; - } - - public int getWindingRule() { - return p.getWindingRule(); - } - - public boolean isDone() { - return typeIndex >= p.typeSize; - } - - public void next() { - typeIndex++; - } - - public int currentSegment(float[] coords) { - if (isDone()) { - throw new NoSuchElementException(iteratorOutOfBounds); - } - int type = p.types[typeIndex]; - int count = Path2D.pointShift[type]; - System.arraycopy(p.points, pointIndex, coords, 0, count); - if (t != null) { - t.transform(coords, 0, coords, 0, count / 2); - } - pointIndex += count; - return type; - } - - } - - public Path2D() { - this(WIND_NON_ZERO, BUFFER_SIZE); - } - - public Path2D(int rule) { - this(rule, BUFFER_SIZE); - } - - public Path2D(int rule, int initialCapacity) { - setWindingRule(rule); - types = new byte[initialCapacity]; - points = new float[initialCapacity * 2]; - } - - public Path2D(Path2D path) { - this(WIND_NON_ZERO, BUFFER_SIZE); - PathIterator p = path.iterator(null); - setWindingRule(p.getWindingRule()); - append(p, false); - } - - public void setWindingRule(int rule) { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { - throw new NoSuchElementException(invalidWindingRuleValue); - } - this.rule = rule; - } - - public int getWindingRule() { - return rule; - } - - /** - * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. - * @param pointCount - the point count to be added in buffer - */ - void checkBuf(int pointCount, boolean checkMove) { - if (checkMove && typeSize == 0) { - throw new IllegalPathStateException("First segment should be SEG_MOVETO type"); - } - if (typeSize == types.length) { - byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; - System.arraycopy(types, 0, tmp, 0, typeSize); - types = tmp; - } - if (pointSize + pointCount > points.length) { - float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; - System.arraycopy(points, 0, tmp, 0, pointSize); - points = tmp; - } - } - - public void moveTo(float x, float y) { - if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { - points[pointSize - 2] = x; - points[pointSize - 1] = y; - } else { - checkBuf(2, false); - types[typeSize++] = PathIterator.SEG_MOVETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - } - - public void lineTo(float x, float y) { - checkBuf(2, true); - types[typeSize++] = PathIterator.SEG_LINETO; - points[pointSize++] = x; - points[pointSize++] = y; - } - - public void quadTo(float x1, float y1, float x2, float y2) { - checkBuf(4, true); - types[typeSize++] = PathIterator.SEG_QUADTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - } - - public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { - checkBuf(6, true); - types[typeSize++] = PathIterator.SEG_CUBICTO; - points[pointSize++] = x1; - points[pointSize++] = y1; - points[pointSize++] = x2; - points[pointSize++] = y2; - points[pointSize++] = x3; - points[pointSize++] = y3; - } - - final public int size() { - return typeSize; - } - - final public boolean isClosed() { - return typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_CLOSE ; - } - - public void closePath() { - if (!isClosed()) { - checkBuf(0, true); - types[typeSize++] = PathIterator.SEG_CLOSE; - } - } - - public String toString() { - return "[size "+size()+", closed "+isClosed()+"]"; - } - - public void append(Path2D path, boolean connect) { - PathIterator p = path.iterator(null); - append(p, connect); - } - - public void append(PathIterator path, boolean connect) { - while (!path.isDone()) { - float coords[] = new float[6]; - switch (path.currentSegment(coords)) { - case PathIterator.SEG_MOVETO: - if (!connect || typeSize == 0) { - moveTo(coords[0], coords[1]); - break; - } - if (types[typeSize - 1] != PathIterator.SEG_CLOSE && - points[pointSize - 2] == coords[0] && - points[pointSize - 1] == coords[1]) - { - break; - } - // NO BREAK; - case PathIterator.SEG_LINETO: - lineTo(coords[0], coords[1]); - break; - case PathIterator.SEG_QUADTO: - quadTo(coords[0], coords[1], coords[2], coords[3]); - break; - case PathIterator.SEG_CUBICTO: - curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); - break; - case PathIterator.SEG_CLOSE: - closePath(); - break; - } - path.next(); - connect = false; - } - } - - public Vertex getCurrentPoint() { - if (typeSize == 0) { - return null; - } - int j = pointSize - 2; - if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { - - for (int i = typeSize - 2; i > 0; i--) { - int type = types[i]; - if (type == PathIterator.SEG_MOVETO) { - break; - } - j -= pointShift[type]; - } - } - return new Vertex(points[j], points[j + 1]); - } - - public void reset() { - typeSize = 0; - pointSize = 0; - } - - public void transform(AffineTransform t) { - t.transform(points, 0, points, 0, pointSize / 2); - } - - public Path2D createTransformedShape(AffineTransform t) { - Path2D p = (Path2D)clone(); - if (t != null) { - p.transform(t); - } - return p; - } - - public final synchronized AABBox getBounds2D() { - float rx1, ry1, rx2, ry2; - if (pointSize == 0) { - rx1 = ry1 = rx2 = ry2 = 0.0f; - } else { - int i = pointSize - 1; - ry1 = ry2 = points[i--]; - rx1 = rx2 = points[i--]; - while (i > 0) { - float y = points[i--]; - float x = points[i--]; - if (x < rx1) { - rx1 = x; - } else - if (x > rx2) { - rx2 = x; - } - if (y < ry1) { - ry1 = y; - } else - if (y > ry2) { - ry2 = y; - } - } - } - // FIXME: Rami's code had this in, but AABBox uses upper left - lower right - right ? - // return new AABBox(rx1, ry1, 0f, rx2 - rx1, ry2 - ry1, 0f); - return new AABBox(rx1, ry1, 0f, rx2, ry2, 0f); - } - - /** - * Checks cross count according to path rule to define is it point inside shape or not. - * @param cross - the point cross count - * @return true if point is inside path, or false otherwise - */ - boolean isInside(int cross) { - if (rule == WIND_NON_ZERO) { - return Crossing.isInsideNonZero(cross); - } - return Crossing.isInsideEvenOdd(cross); - } - - public boolean contains(float px, float py) { - return isInside(Crossing.crossShape(this, px, py)); - } - - public boolean contains(float rx, float ry, float rw, float rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross != Crossing.CROSSING && isInside(cross); - } - - public boolean intersects(float rx, float ry, float rw, float rh) { - int cross = Crossing.intersectShape(this, rx, ry, rw, rh); - return cross == Crossing.CROSSING || isInside(cross); - } - - public boolean contains(Point p) { - return contains(p.getX(), p.getY()); - } - - public boolean contains(AABBox r) { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - public boolean intersects(AABBox r) { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - public PathIterator iterator() { - return new Iterator(this); - } - - public PathIterator iterator(AffineTransform t) { - return new Iterator(this, t); - } - - /* public PathIterator getPathIterator(AffineTransform t, float flatness) { - return new FlatteningPathIterator(getPathIterator(t), flatness); - } */ - - @Override - public Object clone() { - try { - Path2D p = (Path2D) super.clone(); - p.types = types.clone(); - p.points = points.clone(); - return p; - } catch (CloneNotSupportedException e) { - throw new InternalError(); - } - } -} - diff --git a/src/com/jogamp/graph/geom/plane/PathIterator.java b/src/com/jogamp/graph/geom/plane/PathIterator.java deleted file mode 100644 index b4681df0a..000000000 --- a/src/com/jogamp/graph/geom/plane/PathIterator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ -/** - * @author Denis M. Kishenko - */ -package com.jogamp.graph.geom.plane; - -public interface PathIterator { - - public static final int WIND_EVEN_ODD = 0; - public static final int WIND_NON_ZERO = 1; - - public static final int SEG_MOVETO = 0; - public static final int SEG_LINETO = 1; - public static final int SEG_QUADTO = 2; - public static final int SEG_CUBICTO = 3; - public static final int SEG_CLOSE = 4; - - public int getWindingRule(); - - public boolean isDone(); - - public void next(); - - public int currentSegment(float[] coords); - -} - diff --git a/src/jogamp/graph/curve/text/GlyphShape.java b/src/jogamp/graph/curve/text/GlyphShape.java index 9862a5407..8e16de1a4 100644 --- a/src/jogamp/graph/curve/text/GlyphShape.java +++ b/src/jogamp/graph/curve/text/GlyphShape.java @@ -29,7 +29,8 @@ package jogamp.graph.curve.text; import java.util.ArrayList; -import com.jogamp.graph.geom.plane.PathIterator; +import jogamp.graph.geom.plane.PathIterator; + import com.jogamp.graph.geom.Line; import com.jogamp.graph.geom.Point; import com.jogamp.graph.geom.PointTex; diff --git a/src/jogamp/graph/curve/text/GlyphString.java b/src/jogamp/graph/curve/text/GlyphString.java index d85e59c43..75d7e4402 100644 --- a/src/jogamp/graph/curve/text/GlyphString.java +++ b/src/jogamp/graph/curve/text/GlyphString.java @@ -29,9 +29,6 @@ package jogamp.graph.curve.text; import java.util.ArrayList; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; -import com.jogamp.graph.geom.plane.PathIterator; import com.jogamp.graph.geom.Point; import com.jogamp.graph.geom.PointTex; import com.jogamp.graph.geom.Triangle; @@ -39,6 +36,10 @@ import com.jogamp.graph.geom.opengl.Vertex; import javax.media.opengl.GLContext; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; +import jogamp.graph.geom.plane.PathIterator; + import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.RegionFactory; diff --git a/src/jogamp/graph/font/FontInt.java b/src/jogamp/graph/font/FontInt.java new file mode 100644 index 000000000..5b938bdbf --- /dev/null +++ b/src/jogamp/graph/font/FontInt.java @@ -0,0 +1,45 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font; + +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + +import com.jogamp.graph.font.Font; + +public interface FontInt extends Font { + + public interface Glyph extends Font.Glyph { + public Path2D getPath(); + public Path2D getPathForPixelSize(float pixelSize); + } + + public void getOutline(String string, + AffineTransform transform, + Path2D[] result); +} diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index 7cc80cc13..d054635e4 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -30,7 +30,10 @@ package jogamp.graph.font.typecast; import java.io.File; import java.io.IOException; +import jogamp.graph.font.FontInt; import jogamp.graph.font.JavaFontLoader; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; import net.java.dev.typecast.ot.OTFont; import net.java.dev.typecast.ot.OTFontCollection; @@ -41,12 +44,10 @@ import net.java.dev.typecast.ot.table.ID; import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.geom.PointTex; import com.jogamp.graph.geom.Point; -class TypecastFont implements Font { +class TypecastFont implements FontInt { static final boolean DEBUG = false; final Point.Factory pointFactory; diff --git a/src/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogamp/graph/font/typecast/TypecastGlyph.java index faca8c779..9bb582974 100644 --- a/src/jogamp/graph/font/typecast/TypecastGlyph.java +++ b/src/jogamp/graph/font/typecast/TypecastGlyph.java @@ -27,12 +27,14 @@ */ package jogamp.graph.font.typecast; +import jogamp.graph.font.FontInt; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; -public class TypecastGlyph implements Font.Glyph { +public class TypecastGlyph implements FontInt.Glyph { public class Advance { Font font; diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java index 7b36d22b5..3813eb474 100644 --- a/src/jogamp/graph/font/typecast/TypecastRenderer.java +++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java @@ -27,9 +27,10 @@ */ package jogamp.graph.font.typecast; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.plane.AffineTransform; -import com.jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.geom.PointTex; import com.jogamp.graph.geom.Point.Factory; diff --git a/src/jogamp/graph/geom/plane/AffineTransform.java b/src/jogamp/graph/geom/plane/AffineTransform.java new file mode 100644 index 000000000..02fb9993d --- /dev/null +++ b/src/jogamp/graph/geom/plane/AffineTransform.java @@ -0,0 +1,573 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package jogamp.graph.geom.plane; + +import java.io.IOException; +import java.io.Serializable; + +import jogamp.graph.math.MathFloat; +import org.apache.harmony.misc.HashCode; + +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Point.Factory; + +public class AffineTransform implements Cloneable, Serializable { + + private static final long serialVersionUID = 1330973210523860834L; + + static final String determinantIsZero = "Determinant is zero"; + + public static final int TYPE_IDENTITY = 0; + public static final int TYPE_TRANSLATION = 1; + public static final int TYPE_UNIFORM_SCALE = 2; + public static final int TYPE_GENERAL_SCALE = 4; + public static final int TYPE_QUADRANT_ROTATION = 8; + public static final int TYPE_GENERAL_ROTATION = 16; + public static final int TYPE_GENERAL_TRANSFORM = 32; + public static final int TYPE_FLIP = 64; + public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; + public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION; + + /** + * The TYPE_UNKNOWN is an initial type value + */ + static final int TYPE_UNKNOWN = -1; + + /** + * The min value equivalent to zero. If absolute value less then ZERO it considered as zero. + */ + static final float ZERO = (float) 1E-10; + + private final Point.Factory pointFactory; + + /** + * The values of transformation matrix + */ + float m00; + float m10; + float m01; + float m11; + float m02; + float m12; + + /** + * The transformation type + */ + transient int type; + + public AffineTransform(Factory factory) { + pointFactory = factory; + type = TYPE_IDENTITY; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; + } + + public AffineTransform(AffineTransform t) { + this.pointFactory = t.pointFactory; + this.type = t.type; + this.m00 = t.m00; + this.m10 = t.m10; + this.m01 = t.m01; + this.m11 = t.m11; + this.m02 = t.m02; + this.m12 = t.m12; + } + + public AffineTransform(Point.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { + pointFactory = factory; + this.type = TYPE_UNKNOWN; + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + } + + public AffineTransform(Point.Factory factory, float[] matrix) { + pointFactory = factory; + this.type = TYPE_UNKNOWN; + m00 = matrix[0]; + m10 = matrix[1]; + m01 = matrix[2]; + m11 = matrix[3]; + if (matrix.length > 4) { + m02 = matrix[4]; + m12 = matrix[5]; + } + } + + /* + * Method returns type of affine transformation. + * + * Transform matrix is + * m00 m01 m02 + * m10 m11 m12 + * + * According analytic geometry new basis vectors are (m00, m01) and (m10, m11), + * translation vector is (m02, m12). Original basis vectors are (1, 0) and (0, 1). + * Type transformations classification: + * TYPE_IDENTITY - new basis equals original one and zero translation + * TYPE_TRANSLATION - translation vector isn't zero + * TYPE_UNIFORM_SCALE - vectors length of new basis equals + * TYPE_GENERAL_SCALE - vectors length of new basis doesn't equal + * TYPE_FLIP - new basis vector orientation differ from original one + * TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360 degrees + * TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle + * TYPE_GENERAL_TRANSFORM - transformation can't be inversed + */ + public int getType() { + if (type != TYPE_UNKNOWN) { + return type; + } + + int type = 0; + + if (m00 * m01 + m10 * m11 != 0.0) { + type |= TYPE_GENERAL_TRANSFORM; + return type; + } + + if (m02 != 0.0 || m12 != 0.0) { + type |= TYPE_TRANSLATION; + } else + if (m00 == 1.0 && m11 == 1.0 && m01 == 0.0 && m10 == 0.0) { + type = TYPE_IDENTITY; + return type; + } + + if (m00 * m11 - m01 * m10 < 0.0) { + type |= TYPE_FLIP; + } + + float dx = m00 * m00 + m10 * m10; + float dy = m01 * m01 + m11 * m11; + if (dx != dy) { + type |= TYPE_GENERAL_SCALE; + } else + if (dx != 1.0) { + type |= TYPE_UNIFORM_SCALE; + } + + if ((m00 == 0.0 && m11 == 0.0) || + (m10 == 0.0 && m01 == 0.0 && (m00 < 0.0 || m11 < 0.0))) + { + type |= TYPE_QUADRANT_ROTATION; + } else + if (m01 != 0.0 || m10 != 0.0) { + type |= TYPE_GENERAL_ROTATION; + } + + return type; + } + + public float getScaleX() { + return m00; + } + + public float getScaleY() { + return m11; + } + + public float getShearX() { + return m01; + } + + public float getShearY() { + return m10; + } + + public float getTranslateX() { + return m02; + } + + public float getTranslateY() { + return m12; + } + + public boolean isIdentity() { + return getType() == TYPE_IDENTITY; + } + + public void getMatrix(float[] matrix) { + matrix[0] = m00; + matrix[1] = m10; + matrix[2] = m01; + matrix[3] = m11; + if (matrix.length > 4) { + matrix[4] = m02; + matrix[5] = m12; + } + } + + public float getDeterminant() { + return m00 * m11 - m01 * m10; + } + + public void setTransform(float m00, float m10, float m01, float m11, float m02, float m12) { + this.type = TYPE_UNKNOWN; + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m11 = m11; + this.m02 = m02; + this.m12 = m12; + } + + public void setTransform(AffineTransform t) { + type = t.type; + setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12); + } + + public void setToIdentity() { + type = TYPE_IDENTITY; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; + } + + public void setToTranslation(float mx, float my) { + m00 = m11 = 1.0f; + m01 = m10 = 0.0f; + m02 = mx; + m12 = my; + if (mx == 0.0f && my == 0.0f) { + type = TYPE_IDENTITY; + } else { + type = TYPE_TRANSLATION; + } + } + + public void setToScale(float scx, float scy) { + m00 = scx; + m11 = scy; + m10 = m01 = m02 = m12 = 0.0f; + if (scx != 1.0f || scy != 1.0f) { + type = TYPE_UNKNOWN; + } else { + type = TYPE_IDENTITY; + } + } + + public void setToShear(float shx, float shy) { + m00 = m11 = 1.0f; + m02 = m12 = 0.0f; + m01 = shx; + m10 = shy; + if (shx != 0.0f || shy != 0.0f) { + type = TYPE_UNKNOWN; + } else { + type = TYPE_IDENTITY; + } + } + + public void setToRotation(float angle) { + float sin = MathFloat.sin(angle); + float cos = MathFloat.cos(angle); + if (MathFloat.abs(cos) < ZERO) { + cos = 0.0f; + sin = sin > 0.0f ? 1.0f : -1.0f; + } else + if (MathFloat.abs(sin) < ZERO) { + sin = 0.0f; + cos = cos > 0.0f ? 1.0f : -1.0f; + } + m00 = m11 = cos; + m01 = -sin; + m10 = sin; + m02 = m12 = 0.0f; + type = TYPE_UNKNOWN; + } + + public void setToRotation(float angle, float px, float py) { + setToRotation(angle); + m02 = px * (1.0f - m00) + py * m10; + m12 = py * (1.0f - m00) - px * m10; + type = TYPE_UNKNOWN; + } + + public static AffineTransform getTranslateInstance(Point.Factory factory, float mx, float my) { + AffineTransform t = new AffineTransform(factory); + t.setToTranslation(mx, my); + return t; + } + + public static AffineTransform getScaleInstance(Point.Factory factory, float scx, float scY) { + AffineTransform t = new AffineTransform(factory); + t.setToScale(scx, scY); + return t; + } + + public static AffineTransform getShearInstance(Point.Factory factory, float shx, float shy) { + AffineTransform t = new AffineTransform(factory); + t.setToShear(shx, shy); + return t; + } + + public static AffineTransform getRotateInstance(Point.Factory factory, float angle) { + AffineTransform t = new AffineTransform(factory); + t.setToRotation(angle); + return t; + } + + public static AffineTransform getRotateInstance(Point.Factory factory, float angle, float x, float y) { + AffineTransform t = new AffineTransform(factory); + t.setToRotation(angle, x, y); + return t; + } + + public void translate(float mx, float my) { + concatenate(AffineTransform.getTranslateInstance(pointFactory, mx, my)); + } + + public void scale(float scx, float scy) { + concatenate(AffineTransform.getScaleInstance(pointFactory, scx, scy)); + } + + public void shear(float shx, float shy) { + concatenate(AffineTransform.getShearInstance(pointFactory, shx, shy)); + } + + public void rotate(float angle) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle)); + } + + public void rotate(float angle, float px, float py) { + concatenate(AffineTransform.getRotateInstance(pointFactory, angle, px, py)); + } + + /** + * Multiply matrix of two AffineTransform objects. + * The first argument's {@link Point.Factory} is being used. + * + * @param t1 - the AffineTransform object is a multiplicand + * @param t2 - the AffineTransform object is a multiplier + * @return an AffineTransform object that is a result of t1 multiplied by matrix t2. + */ + AffineTransform multiply(AffineTransform t1, AffineTransform t2) { + return new AffineTransform(t1.pointFactory, + t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00 + t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01 + t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10 + t1.m01 * t2.m10 + t1.m11 * t2.m11, // m11 + t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02 + t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12);// m12 + } + + public void concatenate(AffineTransform t) { + setTransform(multiply(t, this)); + } + + public void preConcatenate(AffineTransform t) { + setTransform(multiply(this, t)); + } + + public AffineTransform createInverse() throws NoninvertibleTransformException { + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); + } + return new AffineTransform( + this.pointFactory, + m11 / det, // m00 + -m10 / det, // m10 + -m01 / det, // m01 + m00 / det, // m11 + (m01 * m12 - m11 * m02) / det, // m02 + (m10 * m02 - m00 * m12) / det // m12 + ); + } + + public Point transform(Point src, Point dst) { + if (dst == null) { + dst = pointFactory.create(); + } + + float x = src.getX(); + float y = src.getY(); + + dst.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + return dst; + } + + public void transform(Point[] src, int srcOff, Point[] dst, int dstOff, int length) { + while (--length >= 0) { + Point srcPoint = src[srcOff++]; + float x = srcPoint.getX(); + float y = srcPoint.getY(); + Point dstPoint = dst[dstOff]; + if (dstPoint == null) { + throw new IllegalArgumentException("dst["+dstOff+"] is null"); + } + dstPoint.setCoord(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12); + dst[dstOff++] = dstPoint; + } + } + + public void transform(float[] src, int srcOff, float[] dst, int dstOff, int length) { + int step = 2; + if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { + srcOff = srcOff + length * 2 - 2; + dstOff = dstOff + length * 2 - 2; + step = -2; + } + while (--length >= 0) { + float x = src[srcOff + 0]; + float y = src[srcOff + 1]; + dst[dstOff + 0] = x * m00 + y * m01 + m02; + dst[dstOff + 1] = x * m10 + y * m11 + m12; + srcOff += step; + dstOff += step; + } + } + + public Point deltaTransform(Point src, Point dst) { + if (dst == null) { + dst = pointFactory.create(); + } + + float x = src.getX(); + float y = src.getY(); + + dst.setCoord(x * m00 + y * m01, x * m10 + y * m11); + return dst; + } + + public void deltaTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) { + while (--length >= 0) { + float x = src[srcOff++]; + float y = src[srcOff++]; + dst[dstOff++] = x * m00 + y * m01; + dst[dstOff++] = x * m10 + y * m11; + } + } + + public Point inverseTransform(Point src, Point dst) throws NoninvertibleTransformException { + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); + } + if (dst == null) { + dst = pointFactory.create(); + } + + float x = src.getX() - m02; + float y = src.getY() - m12; + + dst.setCoord((x * m11 - y * m01) / det, (y * m00 - x * m10) / det); + return dst; + } + + public void inverseTransform(float[] src, int srcOff, float[] dst, int dstOff, int length) + throws NoninvertibleTransformException + { + float det = getDeterminant(); + if (MathFloat.abs(det) < ZERO) { + throw new NoninvertibleTransformException(determinantIsZero); + } + + while (--length >= 0) { + float x = src[srcOff++] - m02; + float y = src[srcOff++] - m12; + dst[dstOff++] = (x * m11 - y * m01) / det; + dst[dstOff++] = (y * m00 - x * m10) / det; + } + } + + public Path2D createTransformedShape(Path2D src) { + if (src == null) { + return null; + } + if (src instanceof Path2D) { + return ((Path2D)src).createTransformedShape(this); + } + PathIterator path = src.iterator(this); + Path2D dst = new Path2D(path.getWindingRule()); + dst.append(path, false); + return dst; + } + + @Override + public String toString() { + return + getClass().getName() + + "[[" + m00 + ", " + m01 + ", " + m02 + "], [" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + + m10 + ", " + m11 + ", " + m12 + "]]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } + + @Override + public int hashCode() { + HashCode hash = new HashCode(); + hash.append(m00); + hash.append(m01); + hash.append(m02); + hash.append(m10); + hash.append(m11); + hash.append(m12); + return hash.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof AffineTransform) { + AffineTransform t = (AffineTransform)obj; + return + m00 == t.m00 && m01 == t.m01 && + m02 == t.m02 && m10 == t.m10 && + m11 == t.m11 && m12 == t.m12; + } + return false; + } + + + /** + * Write AffineTrasform object to the output steam. + * @param stream - the output stream + * @throws IOException - if there are I/O errors while writing to the output strem + */ + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + } + + + /** + * Read AffineTransform object from the input stream + * @param stream - the input steam + * @throws IOException - if there are I/O errors while reading from the input strem + * @throws ClassNotFoundException - if class could not be found + */ + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + type = TYPE_UNKNOWN; + } + +} + diff --git a/src/jogamp/graph/geom/plane/IllegalPathStateException.java b/src/jogamp/graph/geom/plane/IllegalPathStateException.java new file mode 100644 index 000000000..55211b3f9 --- /dev/null +++ b/src/jogamp/graph/geom/plane/IllegalPathStateException.java @@ -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. + */ +/** + * @author Denis M. Kishenko + */ +package jogamp.graph.geom.plane; + +public class IllegalPathStateException extends RuntimeException { + + private static final long serialVersionUID = -5158084205220481094L; + + public IllegalPathStateException() { + } + + public IllegalPathStateException(String s) { + super(s); + } + +} + diff --git a/src/jogamp/graph/geom/plane/NoninvertibleTransformException.java b/src/jogamp/graph/geom/plane/NoninvertibleTransformException.java new file mode 100644 index 000000000..398a03fca --- /dev/null +++ b/src/jogamp/graph/geom/plane/NoninvertibleTransformException.java @@ -0,0 +1,31 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package jogamp.graph.geom.plane; + +public class NoninvertibleTransformException extends java.lang.Exception { + + private static final long serialVersionUID = 6137225240503990466L; + + public NoninvertibleTransformException(String s) { + super(s); + } + +} + diff --git a/src/jogamp/graph/geom/plane/Path2D.java b/src/jogamp/graph/geom/plane/Path2D.java new file mode 100644 index 000000000..cfb966ac4 --- /dev/null +++ b/src/jogamp/graph/geom/plane/Path2D.java @@ -0,0 +1,430 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package jogamp.graph.geom.plane; + +import java.util.NoSuchElementException; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.opengl.Vertex; + +import jogamp.graph.math.plane.Crossing; + +public final class Path2D implements Cloneable { + + public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; + public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; + + static final String invalidWindingRuleValue = "Invalid winding rule value"; + static final String iteratorOutOfBounds = "Iterator out of bounds"; + + /** + * The buffers size + */ + private static final int BUFFER_SIZE = 10; + + /** + * The buffers capacity + */ + private static final int BUFFER_CAPACITY = 10; + + /** + * The point's types buffer + */ + byte[] types; + + /** + * The points buffer + */ + float[] points; + + /** + * The point's type buffer size + */ + int typeSize; + + /** + * The points buffer size + */ + int pointSize; + + /** + * The path rule + */ + int rule; + + /** + * The space amount in points buffer for different segmenet's types + */ + static int pointShift[] = { + 2, // MOVETO + 2, // LINETO + 4, // QUADTO + 6, // CUBICTO + 0}; // CLOSE + + /* + * GeneralPath path iterator + */ + class Iterator implements PathIterator { + + /** + * The current cursor position in types buffer + */ + int typeIndex; + + /** + * The current cursor position in points buffer + */ + int pointIndex; + + /** + * The source GeneralPath object + */ + Path2D p; + + /** + * The path iterator transformation + */ + AffineTransform t; + + /** + * Constructs a new GeneralPath.Iterator for given general path + * @param path - the source GeneralPath object + */ + Iterator(Path2D path) { + this(path, null); + } + + /** + * Constructs a new GeneralPath.Iterator for given general path and transformation + * @param path - the source GeneralPath object + * @param at - the AffineTransform object to apply rectangle path + */ + Iterator(Path2D path, AffineTransform at) { + this.p = path; + this.t = at; + } + + public int getWindingRule() { + return p.getWindingRule(); + } + + public boolean isDone() { + return typeIndex >= p.typeSize; + } + + public void next() { + typeIndex++; + } + + public int currentSegment(float[] coords) { + if (isDone()) { + throw new NoSuchElementException(iteratorOutOfBounds); + } + int type = p.types[typeIndex]; + int count = Path2D.pointShift[type]; + System.arraycopy(p.points, pointIndex, coords, 0, count); + if (t != null) { + t.transform(coords, 0, coords, 0, count / 2); + } + pointIndex += count; + return type; + } + + } + + public Path2D() { + this(WIND_NON_ZERO, BUFFER_SIZE); + } + + public Path2D(int rule) { + this(rule, BUFFER_SIZE); + } + + public Path2D(int rule, int initialCapacity) { + setWindingRule(rule); + types = new byte[initialCapacity]; + points = new float[initialCapacity * 2]; + } + + public Path2D(Path2D path) { + this(WIND_NON_ZERO, BUFFER_SIZE); + PathIterator p = path.iterator(null); + setWindingRule(p.getWindingRule()); + append(p, false); + } + + public void setWindingRule(int rule) { + if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) { + throw new NoSuchElementException(invalidWindingRuleValue); + } + this.rule = rule; + } + + public int getWindingRule() { + return rule; + } + + /** + * Checks points and types buffer size to add pointCount points. If necessary realloc buffers to enlarge size. + * @param pointCount - the point count to be added in buffer + */ + void checkBuf(int pointCount, boolean checkMove) { + if (checkMove && typeSize == 0) { + throw new IllegalPathStateException("First segment should be SEG_MOVETO type"); + } + if (typeSize == types.length) { + byte tmp[] = new byte[typeSize + BUFFER_CAPACITY]; + System.arraycopy(types, 0, tmp, 0, typeSize); + types = tmp; + } + if (pointSize + pointCount > points.length) { + float tmp[] = new float[pointSize + Math.max(BUFFER_CAPACITY * 2, pointCount)]; + System.arraycopy(points, 0, tmp, 0, pointSize); + points = tmp; + } + } + + public void moveTo(float x, float y) { + if (typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_MOVETO) { + points[pointSize - 2] = x; + points[pointSize - 1] = y; + } else { + checkBuf(2, false); + types[typeSize++] = PathIterator.SEG_MOVETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + } + + public void lineTo(float x, float y) { + checkBuf(2, true); + types[typeSize++] = PathIterator.SEG_LINETO; + points[pointSize++] = x; + points[pointSize++] = y; + } + + public void quadTo(float x1, float y1, float x2, float y2) { + checkBuf(4, true); + types[typeSize++] = PathIterator.SEG_QUADTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + } + + public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { + checkBuf(6, true); + types[typeSize++] = PathIterator.SEG_CUBICTO; + points[pointSize++] = x1; + points[pointSize++] = y1; + points[pointSize++] = x2; + points[pointSize++] = y2; + points[pointSize++] = x3; + points[pointSize++] = y3; + } + + final public int size() { + return typeSize; + } + + final public boolean isClosed() { + return typeSize > 0 && types[typeSize - 1] == PathIterator.SEG_CLOSE ; + } + + public void closePath() { + if (!isClosed()) { + checkBuf(0, true); + types[typeSize++] = PathIterator.SEG_CLOSE; + } + } + + public String toString() { + return "[size "+size()+", closed "+isClosed()+"]"; + } + + public void append(Path2D path, boolean connect) { + PathIterator p = path.iterator(null); + append(p, connect); + } + + public void append(PathIterator path, boolean connect) { + while (!path.isDone()) { + float coords[] = new float[6]; + switch (path.currentSegment(coords)) { + case PathIterator.SEG_MOVETO: + if (!connect || typeSize == 0) { + moveTo(coords[0], coords[1]); + break; + } + if (types[typeSize - 1] != PathIterator.SEG_CLOSE && + points[pointSize - 2] == coords[0] && + points[pointSize - 1] == coords[1]) + { + break; + } + // NO BREAK; + case PathIterator.SEG_LINETO: + lineTo(coords[0], coords[1]); + break; + case PathIterator.SEG_QUADTO: + quadTo(coords[0], coords[1], coords[2], coords[3]); + break; + case PathIterator.SEG_CUBICTO: + curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); + break; + case PathIterator.SEG_CLOSE: + closePath(); + break; + } + path.next(); + connect = false; + } + } + + public Vertex getCurrentPoint() { + if (typeSize == 0) { + return null; + } + int j = pointSize - 2; + if (types[typeSize - 1] == PathIterator.SEG_CLOSE) { + + for (int i = typeSize - 2; i > 0; i--) { + int type = types[i]; + if (type == PathIterator.SEG_MOVETO) { + break; + } + j -= pointShift[type]; + } + } + return new Vertex(points[j], points[j + 1]); + } + + public void reset() { + typeSize = 0; + pointSize = 0; + } + + public void transform(AffineTransform t) { + t.transform(points, 0, points, 0, pointSize / 2); + } + + public Path2D createTransformedShape(AffineTransform t) { + Path2D p = (Path2D)clone(); + if (t != null) { + p.transform(t); + } + return p; + } + + public final synchronized AABBox getBounds2D() { + float rx1, ry1, rx2, ry2; + if (pointSize == 0) { + rx1 = ry1 = rx2 = ry2 = 0.0f; + } else { + int i = pointSize - 1; + ry1 = ry2 = points[i--]; + rx1 = rx2 = points[i--]; + while (i > 0) { + float y = points[i--]; + float x = points[i--]; + if (x < rx1) { + rx1 = x; + } else + if (x > rx2) { + rx2 = x; + } + if (y < ry1) { + ry1 = y; + } else + if (y > ry2) { + ry2 = y; + } + } + } + // FIXME: Rami's code had this in, but AABBox uses upper left - lower right - right ? + // return new AABBox(rx1, ry1, 0f, rx2 - rx1, ry2 - ry1, 0f); + return new AABBox(rx1, ry1, 0f, rx2, ry2, 0f); + } + + /** + * Checks cross count according to path rule to define is it point inside shape or not. + * @param cross - the point cross count + * @return true if point is inside path, or false otherwise + */ + boolean isInside(int cross) { + if (rule == WIND_NON_ZERO) { + return Crossing.isInsideNonZero(cross); + } + return Crossing.isInsideEvenOdd(cross); + } + + public boolean contains(float px, float py) { + return isInside(Crossing.crossShape(this, px, py)); + } + + public boolean contains(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross != Crossing.CROSSING && isInside(cross); + } + + public boolean intersects(float rx, float ry, float rw, float rh) { + int cross = Crossing.intersectShape(this, rx, ry, rw, rh); + return cross == Crossing.CROSSING || isInside(cross); + } + + public boolean contains(Point p) { + return contains(p.getX(), p.getY()); + } + + public boolean contains(AABBox r) { + return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public boolean intersects(AABBox r) { + return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + } + + public PathIterator iterator() { + return new Iterator(this); + } + + public PathIterator iterator(AffineTransform t) { + return new Iterator(this, t); + } + + /* public PathIterator getPathIterator(AffineTransform t, float flatness) { + return new FlatteningPathIterator(getPathIterator(t), flatness); + } */ + + @Override + public Object clone() { + try { + Path2D p = (Path2D) super.clone(); + p.types = types.clone(); + p.points = points.clone(); + return p; + } catch (CloneNotSupportedException e) { + throw new InternalError(); + } + } +} + diff --git a/src/jogamp/graph/geom/plane/PathIterator.java b/src/jogamp/graph/geom/plane/PathIterator.java new file mode 100644 index 000000000..8868a8c58 --- /dev/null +++ b/src/jogamp/graph/geom/plane/PathIterator.java @@ -0,0 +1,42 @@ +/* + * 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. + */ +/** + * @author Denis M. Kishenko + */ +package jogamp.graph.geom.plane; + +public interface PathIterator { + + public static final int WIND_EVEN_ODD = 0; + public static final int WIND_NON_ZERO = 1; + + public static final int SEG_MOVETO = 0; + public static final int SEG_LINETO = 1; + public static final int SEG_QUADTO = 2; + public static final int SEG_CUBICTO = 3; + public static final int SEG_CLOSE = 4; + + public int getWindingRule(); + + public boolean isDone(); + + public void next(); + + public int currentSegment(float[] coords); + +} + diff --git a/src/jogamp/graph/math/plane/Crossing.java b/src/jogamp/graph/math/plane/Crossing.java index 5620da73a..8f8638632 100644 --- a/src/jogamp/graph/math/plane/Crossing.java +++ b/src/jogamp/graph/math/plane/Crossing.java @@ -19,10 +19,10 @@ */ package jogamp.graph.math.plane; +import jogamp.graph.geom.plane.Path2D; +import jogamp.graph.geom.plane.PathIterator; import jogamp.graph.math.MathFloat; -import com.jogamp.graph.geom.plane.Path2D; -import com.jogamp.graph.geom.plane.PathIterator; public class Crossing { -- cgit v1.2.3 From b01b243241635ab4d210aa88cdbff6cc5713a815 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 08:57:18 +0100 Subject: updated file names --- LICENSE.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 58d8691de..3326fd124 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -55,11 +55,11 @@ Version 2.0, January 2004 http://www.apache.org/licenses/ Files: - src/com/jogamp/graph/geom/plane/AffineTransform.java - src/com/jogamp/graph/geom/plane/IllegalPathStateException.java - src/com/jogamp/graph/geom/plane/NoninvertibleTransformException.java - src/com/jogamp/graph/geom/plane/PathIterator.java - src/com/jogamp/graph/geom/plane/Path2D.java + src/jogamp/graph/geom/plane/AffineTransform.java + src/jogamp/graph/geom/plane/IllegalPathStateException.java + src/jogamp/graph/geom/plane/NoninvertibleTransformException.java + src/jogamp/graph/geom/plane/PathIterator.java + src/jogamp/graph/geom/plane/Path2D.java src/jogamp/graph/math/plane/Crossing.java src/org/apache/harmony/misc/HashCode.java -- cgit v1.2.3 From 526af50c03af2e00a028caf4b8504e6c3f3c4221 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Fri, 25 Mar 2011 12:00:55 +0200 Subject: Refactored Vertex Point PointTex GraphPoint namings Vertex class --> SVertex (Simple vertex wwhere memory impl is float[]) Point interface --> Vertex (which combines in it PointTex Interface) GraphPoint --> GraphVertex --- src/com/jogamp/graph/curve/HwRegionRenderer.java | 14 +- src/com/jogamp/graph/curve/OutlineShape.java | 68 ++++---- src/com/jogamp/graph/curve/Region.java | 6 +- .../jogamp/graph/curve/tess/CDTriangulator2D.java | 16 +- .../jogamp/graph/curve/text/HwTextRenderer.java | 17 +- src/com/jogamp/graph/font/FontFactory.java | 7 +- src/com/jogamp/graph/geom/Line.java | 2 +- src/com/jogamp/graph/geom/Outline.java | 14 +- src/com/jogamp/graph/geom/Point.java | 78 --------- src/com/jogamp/graph/geom/PointTex.java | 37 ----- src/com/jogamp/graph/geom/Triangle.java | 2 +- src/com/jogamp/graph/geom/Vertex.java | 82 ++++++++++ src/com/jogamp/graph/geom/opengl/SVertex.java | 179 ++++++++++++++++++++ src/com/jogamp/graph/geom/opengl/Vertex.java | 180 --------------------- src/demo/GPURegionNewtDemo01.java | 4 +- src/demo/GPURegionNewtDemo02.java | 6 +- src/demo/GPUTextNewtDemo01.java | 6 +- src/demo/GPUTextNewtDemo02.java | 6 +- src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 22 +-- src/jogamp/graph/curve/opengl/VBORegionSPES2.java | 24 +-- src/jogamp/graph/curve/tess/GraphOutline.java | 12 +- src/jogamp/graph/curve/tess/GraphPoint.java | 120 -------------- src/jogamp/graph/curve/tess/GraphVertex.java | 120 ++++++++++++++ src/jogamp/graph/curve/tess/HEdge.java | 20 +-- src/jogamp/graph/curve/tess/Loop.java | 32 ++-- src/jogamp/graph/curve/text/GlyphShape.java | 31 ++-- src/jogamp/graph/curve/text/GlyphString.java | 27 ++-- src/jogamp/graph/font/typecast/TypecastFont.java | 10 +- .../graph/font/typecast/TypecastFontFactory.java | 8 +- .../graph/font/typecast/TypecastRenderer.java | 6 +- src/jogamp/graph/geom/plane/AffineTransform.java | 36 ++--- src/jogamp/graph/geom/plane/Path2D.java | 10 +- src/jogamp/graph/math/VectorFloatUtil.java | 10 +- 33 files changed, 587 insertions(+), 625 deletions(-) delete mode 100644 src/com/jogamp/graph/geom/Point.java delete mode 100644 src/com/jogamp/graph/geom/PointTex.java create mode 100644 src/com/jogamp/graph/geom/Vertex.java create mode 100644 src/com/jogamp/graph/geom/opengl/SVertex.java delete mode 100644 src/com/jogamp/graph/geom/opengl/Vertex.java delete mode 100644 src/jogamp/graph/curve/tess/GraphPoint.java create mode 100644 src/jogamp/graph/curve/tess/GraphVertex.java diff --git a/src/com/jogamp/graph/curve/HwRegionRenderer.java b/src/com/jogamp/graph/curve/HwRegionRenderer.java index 3c3142061..2caa6bb7e 100755 --- a/src/com/jogamp/graph/curve/HwRegionRenderer.java +++ b/src/com/jogamp/graph/curve/HwRegionRenderer.java @@ -40,7 +40,7 @@ import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import jogamp.opengl.Debug; import com.jogamp.opengl.util.PMVMatrix; @@ -71,7 +71,7 @@ public class HwRegionRenderer { /** Create a Hardware accelerated Region Renderer * @param context OpenGL rendering context - * @param factory optional Point.Factory for PointTex construction. Default is Vertex.Factory. + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. */ public HwRegionRenderer(GLContext context) { this.context = context; @@ -248,8 +248,8 @@ public class HwRegionRenderer { outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); - ArrayList vertices = (ArrayList) outlineShape.getVertices(); + ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList vertices = (ArrayList) outlineShape.getVertices(); region.addVertices(vertices); region.addTriangles(triangles); @@ -265,11 +265,11 @@ public class HwRegionRenderer { for(OutlineShape outlineShape:outlineShapes){ outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - ArrayList> triangles = outlineShape.triangulate(sharpness); + ArrayList> triangles = outlineShape.triangulate(sharpness); region.addTriangles(triangles); - ArrayList vertices = outlineShape.getVertices(); - for(PointTex vert:vertices){ + ArrayList vertices = outlineShape.getVertices(); + for(Vertex vert:vertices){ vert.setId(numVertices++); } region.addVertices(vertices); diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index d939d7427..b48804b4d 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -35,8 +35,8 @@ import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Line; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.curve.tess.CDTriangulator2D; @@ -54,24 +54,24 @@ import com.jogamp.graph.curve.tess.CDTriangulator2D; */ public class OutlineShape { public static final int QUADRATIC_NURBS = 10; - private final Point.Factory pointFactory; - private ArrayList> outlines = new ArrayList>(3); + private final Vertex.Factory pointFactory; + private ArrayList> outlines = new ArrayList>(3); /** Create a new Outline based Shape */ - public OutlineShape(Point.Factory factory) { + public OutlineShape(Vertex.Factory factory) { pointFactory = factory; - outlines.add(new Outline()); + outlines.add(new Outline()); } - public final Point.Factory pointFactory() { return pointFactory; } + public final Vertex.Factory pointFactory() { return pointFactory; } /** Add a new empty outline * to the shape, this new outline will * be placed at the end of the outline list. */ public void addEmptyOutline(){ - outlines.add(new Outline()); + outlines.add(new Outline()); } /** Adds an outline to the OutlineShape object @@ -80,7 +80,7 @@ public class OutlineShape { * it will do nothing. * @param outline an Outline object */ - public void addOutline(Outline outline){ + public void addOutline(Outline outline){ if(outline.isEmpty()){ return; } @@ -94,7 +94,7 @@ public class OutlineShape { * shape * @param point */ - public final void addVertex(PointTex point){ + public final void addVertex(Vertex point){ getLastOutline().addVertex(point); } @@ -123,7 +123,7 @@ public class OutlineShape { * of outlines that define the shape * @return the last outline */ - public final Outline getLastOutline(){ + public final Outline getLastOutline(){ return outlines.get(outlines.size()-1); } /** Make sure that the outlines represent @@ -138,19 +138,19 @@ public class OutlineShape { } private void transformOutlinesQuadratic(){ - ArrayList> newOutlines = new ArrayList>(3); + ArrayList> newOutlines = new ArrayList>(3); /**loop over the outlines and make sure no * adj off-curve vertices */ - for(Outline outline:outlines){ - Outline newOutline = new Outline(); + for(Outline outline:outlines){ + Outline newOutline = new Outline(); - ArrayList vertices = outline.getVertices(); + ArrayList vertices = outline.getVertices(); int size =vertices.size()-1; for(int i=0;i outline:outlines){ - ArrayList vertices = outline.getVertices(); - for(PointTex vert:vertices){ + for(Outline outline:outlines){ + ArrayList vertices = outline.getVertices(); + for(Vertex vert:vertices){ vert.setId(maxVertexId); maxVertexId++; } @@ -180,9 +180,9 @@ public class OutlineShape { /** @return the list of vertices associated with the * {@code Outline} list of this object */ - public ArrayList getVertices(){ - ArrayList vertices = new ArrayList(); - for(Outline polyline:outlines){ + public ArrayList getVertices(){ + ArrayList vertices = new ArrayList(); + for(Outline polyline:outlines){ vertices.addAll(polyline.getVertices()); } return vertices; @@ -193,17 +193,17 @@ public class OutlineShape { * parts of this graph * @return arraylist of lines */ - public ArrayList> getLines(){ - ArrayList> lines = new ArrayList>(); - for(Outline outline:outlines){ - ArrayList outVertices = outline.getVertices(); + public ArrayList> getLines(){ + ArrayList> lines = new ArrayList>(); + for(Outline outline:outlines){ + ArrayList outVertices = outline.getVertices(); int size = outVertices.size(); for(int i=0; i < size; i++) { - PointTex currentVertex = outVertices.get(i); + Vertex currentVertex = outVertices.get(i); if(currentVertex.isOnCurve()) { - PointTex v2 = outVertices.get((i+1)%size); + Vertex v2 = outVertices.get((i+1)%size); if(v2.isOnCurve()){ - lines.add(new Line(currentVertex, v2)); + lines.add(new Line(currentVertex, v2)); } } } @@ -214,21 +214,21 @@ public class OutlineShape { /** Triangluate the graph object * @param sharpness sharpness of the curved regions default = 0.5 */ - public ArrayList> triangulate(float sharpness){ + public ArrayList> triangulate(float sharpness){ if(outlines.size() == 0){ return null; } sortOutlines(); generateVertexIds(); - CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); + CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); for(int index = 0; index< outlines.size();index++){ - Outline outline = outlines.get(index); + Outline outline = outlines.get(index); triangulator2d.addCurve(outline); } - ArrayList> triangles = triangulator2d.generateTriangulation(); + ArrayList> triangles = triangulator2d.generateTriangulation(); triangulator2d.reset(); return triangles; diff --git a/src/com/jogamp/graph/curve/Region.java b/src/com/jogamp/graph/curve/Region.java index 44f426313..f3a87bb7f 100755 --- a/src/com/jogamp/graph/curve/Region.java +++ b/src/com/jogamp/graph/curve/Region.java @@ -30,7 +30,7 @@ package com.jogamp.graph.curve; import java.util.ArrayList; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.opengl.util.PMVMatrix; /** A Region is the OGL binding of one or more OutlineShapes @@ -80,7 +80,7 @@ public interface Region { * * @see update() */ - public void addTriangles(ArrayList> tris); + public void addTriangles(ArrayList> tris); /** Get the current number of vertices associated * with this region. This number is not necessary equal to @@ -98,7 +98,7 @@ public interface Region { * * @see update() */ - public void addVertices(ArrayList verts); + public void addVertices(ArrayList verts); /** Check if this region is dirty. A region is marked dirty * when new Vertices, Triangles, and or Lines are added after a diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index 936965f0c..00c97d463 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -31,13 +31,13 @@ package com.jogamp.graph.curve.tess; import java.util.ArrayList; import jogamp.graph.curve.tess.GraphOutline; -import jogamp.graph.curve.tess.GraphPoint; +import jogamp.graph.curve.tess.GraphVertex; import jogamp.graph.curve.tess.Loop; import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import jogamp.opengl.Debug; /** Constrained Delaunay Triangulation @@ -45,7 +45,7 @@ import jogamp.opengl.Debug; * Closed Regions with optional n holes. * */ -public class CDTriangulator2D { +public class CDTriangulator2D { protected static final boolean DEBUG = Debug.debug("Triangulation"); @@ -149,13 +149,13 @@ public class CDTriangulator2D { @SuppressWarnings("unchecked") private GraphOutline extractBoundaryTriangles(GraphOutline outline, boolean hole){ GraphOutline innerOutline = new GraphOutline(); - ArrayList> outVertices = outline.getGraphPoint(); + ArrayList> outVertices = outline.getGraphPoint(); int size = outVertices.size(); for(int i=0; i < size; i++) { - GraphPoint currentVertex = outVertices.get(i); - GraphPoint gv0 = outVertices.get((i+size-1)%size); - GraphPoint gv2 = outVertices.get((i+1)%size); - GraphPoint gv1 = currentVertex; + GraphVertex currentVertex = outVertices.get(i); + GraphVertex gv0 = outVertices.get((i+size-1)%size); + GraphVertex gv2 = outVertices.get((i+1)%size); + GraphVertex gv1 = currentVertex; if(!currentVertex.getPoint().isOnCurve()) { T v0 = (T) gv0.getPoint().clone(); diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java index 61d8309c7..bbe62f158 100644 --- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java +++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java @@ -48,9 +48,8 @@ import com.jogamp.common.util.ReflectionUtil; import com.jogamp.graph.curve.Region; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.PointTex; -import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; import jogamp.opengl.Debug; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -100,28 +99,28 @@ public class HwTextRenderer { private GLContext context; private FloatBuffer color = FloatBuffer.allocate(3); private HashMap strings = new HashMap(); - private final Point.Factory pointFactory; + private final Vertex.Factory pointFactory; int win_width = 0; int win_height = 0; /** Create a Hardware accelerated Text Renderer * @param context OpenGL rendering context - * @param factory optional Point.Factory for PointTex construction. Default is Vertex.Factory. + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. */ - public HwTextRenderer(GLContext context, Point.Factory factory, int type) { - this.pointFactory = (null != factory) ? factory : Vertex.factory(); + public HwTextRenderer(GLContext context, Vertex.Factory factory, int type) { + this.pointFactory = (null != factory) ? factory : SVertex.factory(); this.context = context; this.regionType = type; init(context, 0.5f); } - public Font createFont(Point.Factory factory, String name, int size) { + public Font createFont(Vertex.Factory factory, String name, int size) { return fontFactory.createFont(factory, name, size); } - public Font createFont(Point.Factory factory, + public Font createFont(Vertex.Factory factory, String[] families, String style, String variant, diff --git a/src/com/jogamp/graph/font/FontFactory.java b/src/com/jogamp/graph/font/FontFactory.java index d10e1c38b..a96dac1b8 100644 --- a/src/com/jogamp/graph/font/FontFactory.java +++ b/src/com/jogamp/graph/font/FontFactory.java @@ -27,19 +27,18 @@ */ package com.jogamp.graph.font; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; public interface FontFactory { - Font createFont(Point.Factory factory, + Font createFont(Vertex.Factory factory, String[] families, String style, String variant, String weight, String size); - Font createFont(Point.Factory factory, + Font createFont(Vertex.Factory factory, String name, int size); } \ No newline at end of file diff --git a/src/com/jogamp/graph/geom/Line.java b/src/com/jogamp/graph/geom/Line.java index dbdee569c..92d1b007f 100644 --- a/src/com/jogamp/graph/geom/Line.java +++ b/src/com/jogamp/graph/geom/Line.java @@ -27,7 +27,7 @@ */ package com.jogamp.graph.geom; -public class Line { +public class Line { private T v1; private T v2; diff --git a/src/com/jogamp/graph/geom/Outline.java b/src/com/jogamp/graph/geom/Outline.java index b8b824a1c..d9bde4177 100644 --- a/src/com/jogamp/graph/geom/Outline.java +++ b/src/com/jogamp/graph/geom/Outline.java @@ -29,7 +29,7 @@ package com.jogamp.graph.geom; import java.util.ArrayList; -import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Vertex; import jogamp.graph.math.VectorFloatUtil; @@ -45,7 +45,7 @@ import jogamp.graph.math.VectorFloatUtil; * @see OutlineShape, Region * */ -public class Outline implements Comparable>{ +public class Outline implements Comparable>{ private ArrayList vertices = new ArrayList(3); private boolean closed = false; @@ -68,20 +68,20 @@ public class Outline implements Comparable>{ box.resize(vertex.getX(), vertex.getY(), vertex.getZ()); } - public final void addVertex(Point.Factory factory, float x, float y, boolean onCurve) { + public final void addVertex(Vertex.Factory factory, float x, float y, boolean onCurve) { addVertex(factory, x, y, 0f, onCurve); } @SuppressWarnings("unchecked") - public final void addVertex(Point.Factory factory, float x, float y, float z, boolean onCurve) { - Point v = factory.create(x, y, z); + public final void addVertex(Vertex.Factory factory, float x, float y, float z, boolean onCurve) { + Vertex v = factory.create(x, y, z); v.setOnCurve(onCurve); addVertex((T)v); } @SuppressWarnings("unchecked") - public final void addVertex(Point.Factory factory, float[] coordsBuffer, int offset, int length, boolean onCurve) { - Point v = factory.create(coordsBuffer, offset, length); + public final void addVertex(Vertex.Factory factory, float[] coordsBuffer, int offset, int length, boolean onCurve) { + Vertex v = factory.create(coordsBuffer, offset, length); v.setOnCurve(onCurve); addVertex((T)v); } diff --git a/src/com/jogamp/graph/geom/Point.java b/src/com/jogamp/graph/geom/Point.java deleted file mode 100644 index 5f85801f8..000000000 --- a/src/com/jogamp/graph/geom/Point.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.geom; - -/** - * A point with custom memory layout using custom factory. - */ -public interface Point extends Comparable, Cloneable { - - public static interface Factory { - T create(); - - T create(float x, float y); - - T create(float x, float y, float z); - - T create(float[] coordsBuffer, int offset, int length); - - // T[] create(T ... v); - } - - void setCoord(float x, float y); - - void setCoord(float x, float y, float z); - - void setCoord(float[] coordsBuffer, int offset, int length); - - float[] getCoord(); - - void setX(float x); - - void setY(float y); - - void setZ(float z); - - float getX(); - - float getY(); - - float getZ(); - - boolean isOnCurve(); - - void setOnCurve(boolean onCurve); - - int getId(); - - void setId(int id); - - int compareTo(Point p); - - Point clone(); -} diff --git a/src/com/jogamp/graph/geom/PointTex.java b/src/com/jogamp/graph/geom/PointTex.java deleted file mode 100644 index 59f7ee0c6..000000000 --- a/src/com/jogamp/graph/geom/PointTex.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.geom; - -/** - * A Point with texture coordinates - */ -public interface PointTex extends Point { - float[] getTexCoord(); - - void setTexCoord(float s, float t); -} diff --git a/src/com/jogamp/graph/geom/Triangle.java b/src/com/jogamp/graph/geom/Triangle.java index 341a4483b..7b11ba23d 100644 --- a/src/com/jogamp/graph/geom/Triangle.java +++ b/src/com/jogamp/graph/geom/Triangle.java @@ -27,7 +27,7 @@ */ package com.jogamp.graph.geom; -public class Triangle { +public class Triangle { private int id = Integer.MAX_VALUE; final private T[] vertices; private boolean[] boundaryEdges = new boolean[3]; diff --git a/src/com/jogamp/graph/geom/Vertex.java b/src/com/jogamp/graph/geom/Vertex.java new file mode 100644 index 000000000..9d19c89f6 --- /dev/null +++ b/src/com/jogamp/graph/geom/Vertex.java @@ -0,0 +1,82 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom; + +/** + * A Vertex with custom memory layout using custom factory. + */ +public interface Vertex extends Comparable, Cloneable { + + public static interface Factory { + T create(); + + T create(float x, float y); + + T create(float x, float y, float z); + + T create(float[] coordsBuffer, int offset, int length); + + // T[] create(T ... v); + } + + void setCoord(float x, float y); + + void setCoord(float x, float y, float z); + + void setCoord(float[] coordsBuffer, int offset, int length); + + float[] getCoord(); + + void setX(float x); + + void setY(float y); + + void setZ(float z); + + float getX(); + + float getY(); + + float getZ(); + + boolean isOnCurve(); + + void setOnCurve(boolean onCurve); + + int getId(); + + void setId(int id); + + int compareTo(Vertex p); + + float[] getTexCoord(); + + void setTexCoord(float s, float t); + + Vertex clone(); +} diff --git a/src/com/jogamp/graph/geom/opengl/SVertex.java b/src/com/jogamp/graph/geom/opengl/SVertex.java new file mode 100644 index 000000000..86b95854d --- /dev/null +++ b/src/com/jogamp/graph/geom/opengl/SVertex.java @@ -0,0 +1,179 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.geom.opengl; + +import jogamp.graph.math.VectorFloatUtil; + +import com.jogamp.graph.geom.Vertex; + +public class SVertex implements Vertex { + private int id = Integer.MAX_VALUE; + protected float[] coord = new float[3]; + protected boolean onCurve = true; + private float[] texCoord = new float[2]; + + static final Factory factory = new Factory(); + + public static Factory factory() { return factory; } + + public static class Factory implements Vertex.Factory { + @Override + public SVertex create() { + return new SVertex(); + } + + @Override + public SVertex create(float x, float y) { + return new SVertex(x, y); + } + + @Override + public SVertex create(float x, float y, float z) { + return new SVertex(x, y, z); + } + + @Override + public SVertex create(float[] coordsBuffer, int offset, int length) { + return new SVertex(coordsBuffer, offset, length); + } + + /* @Override + public Vertex[] create(Vertex ... v) { + return v; + } */ + } + + public SVertex() { + } + + public SVertex(float x, float y) { + setCoord(x, y); + } + public SVertex(float x, float y, float z) { + setCoord(x, y, z); + } + public SVertex(float[] coordsBuffer, int offset, int length) { + setCoord(coordsBuffer, offset, length); + } + + public void setCoord(float x, float y) { + this.coord[0] = x; + this.coord[1] = y; + this.coord[2] = 0f; + } + + public void setCoord(float x, float y, float z) { + this.coord[0] = x; + this.coord[1] = y; + this.coord[2] = z; + } + + public void setCoord(float[] coordsBuffer, int offset, int length) { + if(length > coordsBuffer.length - offset) { + throw new IndexOutOfBoundsException("coordsBuffer too small: "+coordsBuffer.length+" - "+offset+" < "+length); + } + if(length > 3) { + throw new IndexOutOfBoundsException("length too bug: "+length+" > "+3); + } + int i=0; + while(i { - @Override - public Vertex create() { - return new Vertex(); - } - - @Override - public Vertex create(float x, float y) { - return new Vertex(x, y); - } - - @Override - public Vertex create(float x, float y, float z) { - return new Vertex(x, y, z); - } - - @Override - public Vertex create(float[] coordsBuffer, int offset, int length) { - return new Vertex(coordsBuffer, offset, length); - } - - /* @Override - public Vertex[] create(Vertex ... v) { - return v; - } */ - } - - public Vertex() { - } - - public Vertex(float x, float y) { - setCoord(x, y); - } - public Vertex(float x, float y, float z) { - setCoord(x, y, z); - } - public Vertex(float[] coordsBuffer, int offset, int length) { - setCoord(coordsBuffer, offset, length); - } - - public void setCoord(float x, float y) { - this.coord[0] = x; - this.coord[1] = y; - this.coord[2] = 0f; - } - - public void setCoord(float x, float y, float z) { - this.coord[0] = x; - this.coord[1] = y; - this.coord[2] = z; - } - - public void setCoord(float[] coordsBuffer, int offset, int length) { - if(length > coordsBuffer.length - offset) { - throw new IndexOutOfBoundsException("coordsBuffer too small: "+coordsBuffer.length+" - "+offset+" < "+length); - } - if(length > 3) { - throw new IndexOutOfBoundsException("length too bug: "+length+" > "+3); - } - int i=0; - while(i pointFactory = Vertex.factory(); + Vertex.Factory pointFactory = SVertex.factory(); TextGLListener textGLListener = null; diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index b0c7115ec..b048a3a68 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -38,8 +38,8 @@ import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.text.HwTextRenderer; import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.event.WindowAdapter; @@ -57,7 +57,7 @@ public class GPUTextNewtDemo02 { } class TextNewtWindow { - Point.Factory pointFactory = Vertex.factory(); + Vertex.Factory pointFactory = SVertex.factory(); TextGLListener textGLListener = null; public TextNewtWindow(){ diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java index c5182059e..4f2714494 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -41,7 +41,7 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.curve.Region; import com.jogamp.opengl.util.PMVMatrix; @@ -53,8 +53,8 @@ public class VBORegion2PGL3 implements Region{ private IntBuffer t_vboIds; - private ArrayList> triangles = new ArrayList>(); - private ArrayList vertices = new ArrayList(); + private ArrayList> triangles = new ArrayList>(); + private ArrayList vertices = new ArrayList(); private GLContext context; private int numBuffers = 3; @@ -85,7 +85,7 @@ public class VBORegion2PGL3 implements Region{ GL3 gl = context.getGL().getGL3(); ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); - for(Triangle t:triangles){ + for(Triangle t:triangles){ if(t.getVertices()[0].getId() == Integer.MAX_VALUE){ t.getVertices()[0].setId(numVertices++); t.getVertices()[1].setId(numVertices++); @@ -100,9 +100,9 @@ public class VBORegion2PGL3 implements Region{ indicies.put((short) t.getVertices()[2].getId()); } else{ - PointTex v1 = t.getVertices()[0]; - PointTex v2 = t.getVertices()[1]; - PointTex v3 = t.getVertices()[2]; + Vertex v1 = t.getVertices()[0]; + Vertex v2 = t.getVertices()[1]; + Vertex v3 = t.getVertices()[2]; indicies.put((short) v1.getId()); indicies.put((short) v2.getId()); @@ -112,7 +112,7 @@ public class VBORegion2PGL3 implements Region{ indicies.rewind(); FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); - for(PointTex v:vertices){ + for(Vertex v:vertices){ verticesBuffer.put(v.getX()); if(flipped){ verticesBuffer.put(-1*v.getY()); @@ -127,7 +127,7 @@ public class VBORegion2PGL3 implements Region{ verticesBuffer.rewind(); FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); - for(PointTex v:vertices){ + for(Vertex v:vertices){ float[] tex = v.getTexCoord(); texCoordBuffer.put(tex[0]); texCoordBuffer.put(tex[1]); @@ -327,7 +327,7 @@ public class VBORegion2PGL3 implements Region{ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); } - public void addTriangles(ArrayList> tris) { + public void addTriangles(ArrayList> tris) { triangles.addAll(tris); dirty = true; } @@ -336,7 +336,7 @@ public class VBORegion2PGL3 implements Region{ return numVertices; } - public void addVertices(ArrayList verts){ + public void addVertices(ArrayList verts){ vertices.addAll(verts); numVertices = vertices.size(); dirty = true; diff --git a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java index 5ef23d4e0..155d35f0b 100644 --- a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -37,7 +37,7 @@ import javax.media.opengl.GLContext; import com.jogamp.common.nio.Buffers; import com.jogamp.graph.curve.Region; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; import com.jogamp.opengl.util.PMVMatrix; @@ -45,8 +45,8 @@ public class VBORegionSPES2 implements Region{ private int numVertices = 0; private IntBuffer vboIds; - private ArrayList> triangles = new ArrayList>(); - private ArrayList vertices = new ArrayList(); + private ArrayList> triangles = new ArrayList>(); + private ArrayList vertices = new ArrayList(); private GLContext context; @@ -63,8 +63,8 @@ public class VBORegionSPES2 implements Region{ GL2ES2 gl = context.getGL().getGL2ES2(); ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); - for(Triangle t:triangles){ - final PointTex[] t_vertices = t.getVertices(); + for(Triangle t:triangles){ + final Vertex[] t_vertices = t.getVertices(); if(t_vertices[0].getId() == Integer.MAX_VALUE){ t_vertices[0].setId(numVertices++); @@ -80,9 +80,9 @@ public class VBORegionSPES2 implements Region{ indicies.put((short) t.getVertices()[2].getId()); } else{ - PointTex v1 = t_vertices[0]; - PointTex v2 = t_vertices[1]; - PointTex v3 = t_vertices[2]; + Vertex v1 = t_vertices[0]; + Vertex v2 = t_vertices[1]; + Vertex v3 = t_vertices[2]; indicies.put((short) v1.getId()); indicies.put((short) v2.getId()); @@ -92,7 +92,7 @@ public class VBORegionSPES2 implements Region{ indicies.rewind(); FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); - for(PointTex v:vertices){ + for(Vertex v:vertices){ verticesBuffer.put(v.getX()); if(flipped){ verticesBuffer.put(-1*v.getY()); @@ -105,7 +105,7 @@ public class VBORegionSPES2 implements Region{ verticesBuffer.rewind(); FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); - for(PointTex v:vertices){ + for(Vertex v:vertices){ float[] tex = v.getTexCoord(); texCoordBuffer.put(tex[0]); texCoordBuffer.put(tex[1]); @@ -151,7 +151,7 @@ public class VBORegionSPES2 implements Region{ render(); } - public void addTriangles(ArrayList> tris) { + public void addTriangles(ArrayList> tris) { triangles.addAll(tris); dirty = true; } @@ -160,7 +160,7 @@ public class VBORegionSPES2 implements Region{ return numVertices; } - public void addVertices(ArrayList verts){ + public void addVertices(ArrayList verts){ vertices.addAll(verts); numVertices = vertices.size(); dirty = true; diff --git a/src/jogamp/graph/curve/tess/GraphOutline.java b/src/jogamp/graph/curve/tess/GraphOutline.java index cf73ab379..bb262ce5b 100644 --- a/src/jogamp/graph/curve/tess/GraphOutline.java +++ b/src/jogamp/graph/curve/tess/GraphOutline.java @@ -30,11 +30,11 @@ package jogamp.graph.curve.tess; import java.util.ArrayList; import com.jogamp.graph.geom.Outline; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; -public class GraphOutline { +public class GraphOutline { final private Outline outline; - final private ArrayList> controlpoints = new ArrayList>(3); + final private ArrayList> controlpoints = new ArrayList>(3); public GraphOutline(){ this.outline = new Outline(); @@ -48,7 +48,7 @@ public class GraphOutline { this.outline = ol; ArrayList vertices = this.outline.getVertices(); for(T v:vertices){ - this.controlpoints.add(new GraphPoint(v)); + this.controlpoints.add(new GraphVertex(v)); } } @@ -61,7 +61,7 @@ public class GraphOutline { }*/ - public ArrayList> getGraphPoint() { + public ArrayList> getGraphPoint() { return controlpoints; } @@ -73,7 +73,7 @@ public class GraphOutline { this.controlpoints = controlpoints; }*/ - public void addVertex(GraphPoint v) { + public void addVertex(GraphVertex v) { controlpoints.add(v); outline.addVertex(v.getPoint()); } diff --git a/src/jogamp/graph/curve/tess/GraphPoint.java b/src/jogamp/graph/curve/tess/GraphPoint.java deleted file mode 100644 index 87d0b9929..000000000 --- a/src/jogamp/graph/curve/tess/GraphPoint.java +++ /dev/null @@ -1,120 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.graph.curve.tess; - -import java.util.ArrayList; - -import com.jogamp.graph.geom.PointTex; - -public class GraphPoint { - private T point; - private ArrayList> edges = null; - private boolean boundaryContained = false; - - public GraphPoint(T point) { - this.point = point; - } - - public T getPoint() { - return point; - } - - public float getX(){ - return point.getX(); - } - - public float getY(){ - return point.getY(); - } - - public float getZ(){ - return point.getZ(); - } - public float[] getCoord() { - return point.getCoord(); - } - - public void setPoint(T point) { - this.point = point; - } - - public ArrayList> getEdges() { - return edges; - } - - public void setEdges(ArrayList> edges) { - this.edges = edges; - } - - public void addEdge(HEdge edge){ - if(edges == null){ - edges = new ArrayList>(); - } - edges.add(edge); - } - public void removeEdge(HEdge edge){ - if(edges == null) - return; - edges.remove(edge); - if(edges.size() == 0){ - edges = null; - } - } - public HEdge findNextEdge(GraphPoint nextVert){ - for(HEdge e:edges){ - if(e.getNext().getGraphPoint() == nextVert){ - return e; - } - } - return null; - } - public HEdge findBoundEdge(){ - for(HEdge e:edges){ - if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){ - return e; - } - } - return null; - } - public HEdge findPrevEdge(GraphPoint prevVert){ - for(HEdge e:edges){ - if(e.getPrev().getGraphPoint() == prevVert){ - return e; - } - } - return null; - } - - public boolean isBoundaryContained() { - return boundaryContained; - } - - public void setBoundaryContained(boolean boundaryContained) { - this.boundaryContained = boundaryContained; - } -} diff --git a/src/jogamp/graph/curve/tess/GraphVertex.java b/src/jogamp/graph/curve/tess/GraphVertex.java new file mode 100644 index 000000000..a474a002e --- /dev/null +++ b/src/jogamp/graph/curve/tess/GraphVertex.java @@ -0,0 +1,120 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.tess; + +import java.util.ArrayList; + +import com.jogamp.graph.geom.Vertex; + +public class GraphVertex { + private T point; + private ArrayList> edges = null; + private boolean boundaryContained = false; + + public GraphVertex(T point) { + this.point = point; + } + + public T getPoint() { + return point; + } + + public float getX(){ + return point.getX(); + } + + public float getY(){ + return point.getY(); + } + + public float getZ(){ + return point.getZ(); + } + public float[] getCoord() { + return point.getCoord(); + } + + public void setPoint(T point) { + this.point = point; + } + + public ArrayList> getEdges() { + return edges; + } + + public void setEdges(ArrayList> edges) { + this.edges = edges; + } + + public void addEdge(HEdge edge){ + if(edges == null){ + edges = new ArrayList>(); + } + edges.add(edge); + } + public void removeEdge(HEdge edge){ + if(edges == null) + return; + edges.remove(edge); + if(edges.size() == 0){ + edges = null; + } + } + public HEdge findNextEdge(GraphVertex nextVert){ + for(HEdge e:edges){ + if(e.getNext().getGraphPoint() == nextVert){ + return e; + } + } + return null; + } + public HEdge findBoundEdge(){ + for(HEdge e:edges){ + if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){ + return e; + } + } + return null; + } + public HEdge findPrevEdge(GraphVertex prevVert){ + for(HEdge e:edges){ + if(e.getPrev().getGraphPoint() == prevVert){ + return e; + } + } + return null; + } + + public boolean isBoundaryContained() { + return boundaryContained; + } + + public void setBoundaryContained(boolean boundaryContained) { + this.boundaryContained = boundaryContained; + } +} diff --git a/src/jogamp/graph/curve/tess/HEdge.java b/src/jogamp/graph/curve/tess/HEdge.java index acb32cb4d..5635e2c31 100644 --- a/src/jogamp/graph/curve/tess/HEdge.java +++ b/src/jogamp/graph/curve/tess/HEdge.java @@ -27,28 +27,28 @@ */ package jogamp.graph.curve.tess; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; -public class HEdge { +public class HEdge { public static int BOUNDARY = 3; public static int INNER = 1; public static int HOLE = 2; - private GraphPoint vert; + private GraphVertex vert; private HEdge prev = null; private HEdge next = null; private HEdge sibling = null; private int type = BOUNDARY; private Triangle triangle = null; - public HEdge(GraphPoint vert, int type) { + public HEdge(GraphVertex vert, int type) { this.vert = vert; this.type = type; } - public HEdge(GraphPoint vert, HEdge prev, HEdge next, HEdge sibling, int type) { + public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) { this.vert = vert; this.prev = prev; this.next = next; @@ -56,7 +56,7 @@ public class HEdge { this.type = type; } - public HEdge(GraphPoint vert, HEdge prev, HEdge next, HEdge sibling, int type, + public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, Triangle triangle) { this.vert = vert; this.prev = prev; @@ -66,11 +66,11 @@ public class HEdge { this.triangle = triangle; } - public GraphPoint getGraphPoint() { + public GraphVertex getGraphPoint() { return vert; } - public void setVert(GraphPoint vert) { + public void setVert(GraphVertex vert) { this.vert = vert; } @@ -114,12 +114,12 @@ public class HEdge { this.triangle = triangle; } - public static void connect(HEdge first, HEdge next){ + public static void connect(HEdge first, HEdge next){ first.setNext(next); next.setPrev(first); } - public static void makeSiblings(HEdge first, HEdge second){ + public static void makeSiblings(HEdge first, HEdge second){ first.setSibling(second); second.setSibling(first); } diff --git a/src/jogamp/graph/curve/tess/Loop.java b/src/jogamp/graph/curve/tess/Loop.java index caebd64e4..e4553968b 100644 --- a/src/jogamp/graph/curve/tess/Loop.java +++ b/src/jogamp/graph/curve/tess/Loop.java @@ -32,10 +32,10 @@ import java.util.ArrayList; import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; -public class Loop { +public class Loop { private HEdge root = null; private AABBox box = new AABBox(); private GraphOutline initialOutline = null; @@ -66,9 +66,9 @@ public class Loop { return null; } - GraphPoint v1 = root.getGraphPoint(); - GraphPoint v2 = next1.getGraphPoint(); - GraphPoint v3 = next2.getGraphPoint(); + GraphVertex v1 = root.getGraphPoint(); + GraphVertex v2 = next1.getGraphPoint(); + GraphVertex v3 = next2.getGraphPoint(); HEdge v3Edge = new HEdge(v3, HEdge.INNER); @@ -98,7 +98,7 @@ public class Loop { * @param direction requested winding of edges (CCW or CW) */ private HEdge initFromPolyline(GraphOutline outline, int direction){ - ArrayList> vertices = outline.getGraphPoint(); + ArrayList> vertices = outline.getGraphPoint(); if(vertices.size()<3) { throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size()); @@ -120,7 +120,7 @@ public class Loop { } while(index != max){ - GraphPoint v1 = vertices.get(index); + GraphVertex v1 = vertices.get(index); box.resize(v1.getX(), v1.getY(), v1.getZ()); HEdge edge = new HEdge(v1, edgeType); @@ -162,7 +162,7 @@ public class Loop { /**needed to generate vertex references.*/ initFromPolyline(polyline, VectorFloatUtil.CW); - GraphPoint v3 = locateClosestVertex(polyline); + GraphVertex v3 = locateClosestVertex(polyline); HEdge v3Edge = v3.findBoundEdge(); HEdge v3EdgeP = v3Edge.getPrev(); HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER); @@ -186,22 +186,22 @@ public class Loop { * to search for closestvertices * @return the vertex that is closest to the newly set root Hedge. */ - private GraphPoint locateClosestVertex(GraphOutline polyline) { + private GraphVertex locateClosestVertex(GraphOutline polyline) { HEdge closestE = null; - GraphPoint closestV = null; + GraphVertex closestV = null; float minDistance = Float.MAX_VALUE; boolean inValid = false; - ArrayList> initVertices = initialOutline.getGraphPoint(); - ArrayList> vertices = polyline.getGraphPoint(); + ArrayList> initVertices = initialOutline.getGraphPoint(); + ArrayList> vertices = polyline.getGraphPoint(); for(int i=0; i< initVertices.size()-1; i++){ - GraphPoint v = initVertices.get(i); - GraphPoint nextV = initVertices.get(i+1); - for(GraphPoint cand:vertices){ + GraphVertex v = initVertices.get(i); + GraphVertex nextV = initVertices.get(i+1); + for(GraphVertex cand:vertices){ float distance = VectorFloatUtil.computeLength(v.getCoord(), cand.getCoord()); if(distance < minDistance){ - for (GraphPoint vert:vertices){ + for (GraphVertex vert:vertices){ if(vert == v || vert == nextV || vert == cand) continue; inValid = VectorFloatUtil.inCircle(v.getPoint(), nextV.getPoint(), diff --git a/src/jogamp/graph/curve/text/GlyphShape.java b/src/jogamp/graph/curve/text/GlyphShape.java index 8e16de1a4..78ae7396c 100644 --- a/src/jogamp/graph/curve/text/GlyphShape.java +++ b/src/jogamp/graph/curve/text/GlyphShape.java @@ -32,8 +32,7 @@ import java.util.ArrayList; import jogamp.graph.geom.plane.PathIterator; import com.jogamp.graph.geom.Line; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.curve.OutlineShape; @@ -48,7 +47,7 @@ public class GlyphShape { /** Create a new Glyph shape * based on Parametric curve control polyline */ - public GlyphShape(Point.Factory factory){ + public GlyphShape(Vertex.Factory factory){ shape = new OutlineShape(factory); } @@ -57,7 +56,7 @@ public class GlyphShape { * * @see PathIterator */ - public GlyphShape(Point.Factory factory, PathIterator pathIterator){ + public GlyphShape(Vertex.Factory factory, PathIterator pathIterator){ this(factory); if(null != pathIterator){ @@ -72,9 +71,9 @@ public class GlyphShape { shape.transformOutlines(OutlineShape.QUADRATIC_NURBS); } - public final Point.Factory pointFactory() { return shape.pointFactory(); } + public final Vertex.Factory pointFactory() { return shape.pointFactory(); } - private void addVertexToLastOutline(PointTex vertex){ + private void addVertexToLastOutline(Vertex vertex){ shape.addVertex(vertex); } @@ -83,40 +82,40 @@ public class GlyphShape { if(!shape.getLastOutline().isEmpty()){ shape.addEmptyOutline(); } - PointTex vert = pointFactory().create(coords[0],coords[1]); + Vertex vert = pointFactory().create(coords[0],coords[1]); vert.setOnCurve(true); addVertexToLastOutline(vert); numVertices++; } else if(segmentType == PathIterator.SEG_LINETO){ - PointTex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = pointFactory().create(coords[0],coords[1]); vert1.setOnCurve(true); addVertexToLastOutline(vert1); numVertices++; } else if(segmentType == PathIterator.SEG_QUADTO){ - PointTex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = pointFactory().create(coords[0],coords[1]); vert1.setOnCurve(false); addVertexToLastOutline(vert1); - PointTex vert2 = pointFactory().create(coords[2],coords[3]); + Vertex vert2 = pointFactory().create(coords[2],coords[3]); vert2.setOnCurve(true); addVertexToLastOutline(vert2); numVertices+=2; } else if(segmentType == PathIterator.SEG_CUBICTO){ - PointTex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = pointFactory().create(coords[0],coords[1]); vert1.setOnCurve(false); addVertexToLastOutline(vert1); - PointTex vert2 = pointFactory().create(coords[2],coords[3]); + Vertex vert2 = pointFactory().create(coords[2],coords[3]); vert2.setOnCurve(false); addVertexToLastOutline(vert2); - PointTex vert3 = pointFactory().create(coords[4],coords[5]); + Vertex vert3 = pointFactory().create(coords[4],coords[5]); vert3.setOnCurve(true); addVertexToLastOutline(vert3); @@ -150,21 +149,21 @@ public class GlyphShape { * @param sharpness sharpness of the curved regions default = 0.5 * @return ArrayList of triangles which define this shape */ - public ArrayList> triangulate(float sharpness){ + public ArrayList> triangulate(float sharpness){ return shape.triangulate(sharpness); } /** Get the list of Vertices of this Object * @return arrayList of Vertices */ - public ArrayList getVertices(){ + public ArrayList getVertices(){ return shape.getVertices(); } /** Get the list of AA lines defined by this object * @return arraylist of lines */ - public ArrayList> getLines(){ + public ArrayList> getLines(){ return shape.getLines(); } } diff --git a/src/jogamp/graph/curve/text/GlyphString.java b/src/jogamp/graph/curve/text/GlyphString.java index 75d7e4402..a7418c6de 100644 --- a/src/jogamp/graph/curve/text/GlyphString.java +++ b/src/jogamp/graph/curve/text/GlyphString.java @@ -29,10 +29,9 @@ package jogamp.graph.curve.text; import java.util.ArrayList; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; import javax.media.opengl.GLContext; @@ -47,26 +46,26 @@ import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; public class GlyphString { - private final Point.Factory pointFactory; + private final Vertex.Factory pointFactory; private ArrayList glyphs = new ArrayList(); private String str = ""; private String fontname = ""; private Region region; - private Vertex origin = new Vertex(); + private SVertex origin = new SVertex(); /** Create a new GlyphString object * @param fontname the name of the font that this String is * associated with * @param str the string object */ - public GlyphString(Point.Factory factory, String fontname, String str){ + public GlyphString(Vertex.Factory factory, String fontname, String str){ pointFactory = factory; this.fontname = fontname; this.str = str; } - public final Point.Factory pointFactory() { return pointFactory; } + public final Vertex.Factory pointFactory() { return pointFactory; } public void addGlyphShape(GlyphShape glyph){ glyphs.add(glyph); @@ -95,10 +94,10 @@ public class GlyphString { } } - private ArrayList> initializeTriangles(float sharpness){ - ArrayList> triangles = new ArrayList>(); + private ArrayList> initializeTriangles(float sharpness){ + ArrayList> triangles = new ArrayList>(); for(GlyphShape glyph:glyphs){ - ArrayList> tris = glyph.triangulate(sharpness); + ArrayList> tris = glyph.triangulate(sharpness); triangles.addAll(tris); } return triangles; @@ -113,13 +112,13 @@ public class GlyphString { region = RegionFactory.create(context, st, type); region.setFlipped(true); - ArrayList> tris = initializeTriangles(shaprness); + ArrayList> tris = initializeTriangles(shaprness); region.addTriangles(tris); int numVertices = region.getNumVertices(); for(GlyphShape glyph:glyphs){ - ArrayList gVertices = glyph.getVertices(); - for(PointTex vert:gVertices){ + ArrayList gVertices = glyph.getVertices(); + for(Vertex vert:gVertices){ vert.setId(numVertices++); } region.addVertices(gVertices); @@ -152,7 +151,7 @@ public class GlyphString { /** Get the Origion of this GlyphString * @return */ - public PointTex getOrigin() { + public Vertex getOrigin() { return origin; } diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index d054635e4..b44a7d86b 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -44,13 +44,13 @@ import net.java.dev.typecast.ot.table.ID; import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.PointTex; -import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex; class TypecastFont implements FontInt { static final boolean DEBUG = false; - final Point.Factory pointFactory; + final Vertex.Factory pointFactory; final OTFontCollection fontset; final OTFont font; final int size; @@ -60,7 +60,7 @@ class TypecastFont implements FontInt { // final IntIntHashMap char2Code; IntObjectHashMap char2Glyph; - public static TypecastFont create(Point.Factory factory, String name, int size) { + public static TypecastFont create(Vertex.Factory factory, String name, int size) { String path = JavaFontLoader.getByName(name); OTFontCollection fontset; try { @@ -72,7 +72,7 @@ class TypecastFont implements FontInt { return null; } - public TypecastFont(Point.Factory factory, OTFontCollection fontset, int size) { + public TypecastFont(Vertex.Factory factory, OTFontCollection fontset, int size) { this.pointFactory = factory; this.fontset = fontset; this.font = fontset.getFont(0); diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java index f66772029..6179986fe 100644 --- a/src/jogamp/graph/font/typecast/TypecastFontFactory.java +++ b/src/jogamp/graph/font/typecast/TypecastFontFactory.java @@ -32,15 +32,15 @@ import java.util.Map; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Point.Factory; -import com.jogamp.graph.geom.PointTex; +import com.jogamp.graph.geom.Vertex.Factory; +import com.jogamp.graph.geom.Vertex; public class TypecastFontFactory implements FontFactory { Map fonts = new HashMap(); - public Font createFont(Factory factory, String name, int size) { + public Font createFont(Factory factory, String name, int size) { Font result = fonts.get(name + ":"+size); if (result == null) { result = TypecastFont.create(factory, name, size); @@ -52,7 +52,7 @@ public class TypecastFontFactory implements FontFactory { } - public Font createFont(Factory factory, + public Font createFont(Factory factory, String[] families, String style, String variant, diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java index 3813eb474..74e5cd604 100644 --- a/src/jogamp/graph/font/typecast/TypecastRenderer.java +++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java @@ -31,8 +31,8 @@ import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.PointTex; -import com.jogamp.graph.geom.Point.Factory; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; import net.java.dev.typecast.ot.Point; import net.java.dev.typecast.ot.OTGlyph; @@ -43,7 +43,7 @@ import net.java.dev.typecast.ot.OTGlyph; */ public class TypecastRenderer { - public static void getOutline(Factory factory, TypecastFont font, + public static void getOutline(Factory factory, TypecastFont font, String string, AffineTransform transform, Path2D[] p) { if (string == null) { diff --git a/src/jogamp/graph/geom/plane/AffineTransform.java b/src/jogamp/graph/geom/plane/AffineTransform.java index 02fb9993d..de13ff9de 100644 --- a/src/jogamp/graph/geom/plane/AffineTransform.java +++ b/src/jogamp/graph/geom/plane/AffineTransform.java @@ -25,8 +25,8 @@ import java.io.Serializable; import jogamp.graph.math.MathFloat; import org.apache.harmony.misc.HashCode; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.Point.Factory; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.Vertex.Factory; public class AffineTransform implements Cloneable, Serializable { @@ -55,7 +55,7 @@ public class AffineTransform implements Cloneable, Serializable { */ static final float ZERO = (float) 1E-10; - private final Point.Factory pointFactory; + private final Vertex.Factory pointFactory; /** * The values of transformation matrix @@ -72,7 +72,7 @@ public class AffineTransform implements Cloneable, Serializable { */ transient int type; - public AffineTransform(Factory factory) { + public AffineTransform(Factory factory) { pointFactory = factory; type = TYPE_IDENTITY; m00 = m11 = 1.0f; @@ -90,7 +90,7 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = t.m12; } - public AffineTransform(Point.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { + public AffineTransform(Vertex.Factory factory, float m00, float m10, float m01, float m11, float m02, float m12) { pointFactory = factory; this.type = TYPE_UNKNOWN; this.m00 = m00; @@ -101,7 +101,7 @@ public class AffineTransform implements Cloneable, Serializable { this.m12 = m12; } - public AffineTransform(Point.Factory factory, float[] matrix) { + public AffineTransform(Vertex.Factory factory, float[] matrix) { pointFactory = factory; this.type = TYPE_UNKNOWN; m00 = matrix[0]; @@ -302,31 +302,31 @@ public class AffineTransform implements Cloneable, Serializable { type = TYPE_UNKNOWN; } - public static AffineTransform getTranslateInstance(Point.Factory factory, float mx, float my) { + public static AffineTransform getTranslateInstance(Vertex.Factory factory, float mx, float my) { AffineTransform t = new AffineTransform(factory); t.setToTranslation(mx, my); return t; } - public static AffineTransform getScaleInstance(Point.Factory factory, float scx, float scY) { + public static AffineTransform getScaleInstance(Vertex.Factory factory, float scx, float scY) { AffineTransform t = new AffineTransform(factory); t.setToScale(scx, scY); return t; } - public static AffineTransform getShearInstance(Point.Factory factory, float shx, float shy) { + public static AffineTransform getShearInstance(Vertex.Factory factory, float shx, float shy) { AffineTransform t = new AffineTransform(factory); t.setToShear(shx, shy); return t; } - public static AffineTransform getRotateInstance(Point.Factory factory, float angle) { + public static AffineTransform getRotateInstance(Vertex.Factory factory, float angle) { AffineTransform t = new AffineTransform(factory); t.setToRotation(angle); return t; } - public static AffineTransform getRotateInstance(Point.Factory factory, float angle, float x, float y) { + public static AffineTransform getRotateInstance(Vertex.Factory factory, float angle, float x, float y) { AffineTransform t = new AffineTransform(factory); t.setToRotation(angle, x, y); return t; @@ -354,7 +354,7 @@ public class AffineTransform implements Cloneable, Serializable { /** * Multiply matrix of two AffineTransform objects. - * The first argument's {@link Point.Factory} is being used. + * The first argument's {@link Vertex.Factory} is being used. * * @param t1 - the AffineTransform object is a multiplicand * @param t2 - the AffineTransform object is a multiplier @@ -394,7 +394,7 @@ public class AffineTransform implements Cloneable, Serializable { ); } - public Point transform(Point src, Point dst) { + public Vertex transform(Vertex src, Vertex dst) { if (dst == null) { dst = pointFactory.create(); } @@ -406,12 +406,12 @@ public class AffineTransform implements Cloneable, Serializable { return dst; } - public void transform(Point[] src, int srcOff, Point[] dst, int dstOff, int length) { + public void transform(Vertex[] src, int srcOff, Vertex[] dst, int dstOff, int length) { while (--length >= 0) { - Point srcPoint = src[srcOff++]; + Vertex srcPoint = src[srcOff++]; float x = srcPoint.getX(); float y = srcPoint.getY(); - Point dstPoint = dst[dstOff]; + Vertex dstPoint = dst[dstOff]; if (dstPoint == null) { throw new IllegalArgumentException("dst["+dstOff+"] is null"); } @@ -437,7 +437,7 @@ public class AffineTransform implements Cloneable, Serializable { } } - public Point deltaTransform(Point src, Point dst) { + public Vertex deltaTransform(Vertex src, Vertex dst) { if (dst == null) { dst = pointFactory.create(); } @@ -458,7 +458,7 @@ public class AffineTransform implements Cloneable, Serializable { } } - public Point inverseTransform(Point src, Point dst) throws NoninvertibleTransformException { + public Vertex inverseTransform(Vertex src, Vertex dst) throws NoninvertibleTransformException { float det = getDeterminant(); if (MathFloat.abs(det) < ZERO) { throw new NoninvertibleTransformException(determinantIsZero); diff --git a/src/jogamp/graph/geom/plane/Path2D.java b/src/jogamp/graph/geom/plane/Path2D.java index cfb966ac4..e25ae0e84 100644 --- a/src/jogamp/graph/geom/plane/Path2D.java +++ b/src/jogamp/graph/geom/plane/Path2D.java @@ -22,8 +22,8 @@ package jogamp.graph.geom.plane; import java.util.NoSuchElementException; import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.Point; -import com.jogamp.graph.geom.opengl.Vertex; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; import jogamp.graph.math.plane.Crossing; @@ -300,7 +300,7 @@ public final class Path2D implements Cloneable { } } - public Vertex getCurrentPoint() { + public SVertex getCurrentPoint() { if (typeSize == 0) { return null; } @@ -315,7 +315,7 @@ public final class Path2D implements Cloneable { j -= pointShift[type]; } } - return new Vertex(points[j], points[j + 1]); + return new SVertex(points[j], points[j + 1]); } public void reset() { @@ -391,7 +391,7 @@ public final class Path2D implements Cloneable { return cross == Crossing.CROSSING || isInside(cross); } - public boolean contains(Point p) { + public boolean contains(Vertex p) { return contains(p.getX(), p.getY()); } diff --git a/src/jogamp/graph/math/VectorFloatUtil.java b/src/jogamp/graph/math/VectorFloatUtil.java index 172cacd09..b2b9a8ee8 100755 --- a/src/jogamp/graph/math/VectorFloatUtil.java +++ b/src/jogamp/graph/math/VectorFloatUtil.java @@ -29,7 +29,7 @@ package jogamp.graph.math; import java.util.ArrayList; -import com.jogamp.graph.geom.Point; +import com.jogamp.graph.geom.Vertex; public class VectorFloatUtil { @@ -247,7 +247,7 @@ public class VectorFloatUtil { * @return true if the vertex d is inside the circle defined by the * vertices a, b, c. from paper by Guibas and Stolfi (1985). */ - public static boolean inCircle(Point a, Point b, Point c, Point d){ + public static boolean inCircle(Vertex a, Vertex b, Vertex c, Vertex d){ return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) - (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) + (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) - @@ -261,7 +261,7 @@ public class VectorFloatUtil { * @return compute twice the area of the oriented triangle (a,b,c), the area * is positive if the triangle is oriented counterclockwise. */ - public static float triArea(Point a, Point b, Point c){ + public static float triArea(Vertex a, Vertex b, Vertex c){ return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX()); } @@ -271,7 +271,7 @@ public class VectorFloatUtil { * @param c third vertex * @return true if the points a,b,c are in a ccw order */ - public static boolean ccw(Point a, Point b, Point c){ + public static boolean ccw(Vertex a, Vertex b, Vertex c){ return triArea(a,b,c) > 0; } @@ -279,7 +279,7 @@ public class VectorFloatUtil { * @param vertices * @return positve area if ccw else negative area value */ - public static float area(ArrayList vertices) { + public static float area(ArrayList vertices) { int n = vertices.size(); float area = 0.0f; for (int p = n - 1, q = 0; q < n; p = q++) -- cgit v1.2.3 From 731b4fe3c934d8e68d388025e20a0b0be22bf91d Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Fri, 25 Mar 2011 12:09:43 +0200 Subject: Fix: GPUTextnewtDemo02 showing r2t algo output --- src/demo/GPUTextNewtDemo02.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index b048a3a68..c59368c37 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -118,9 +118,11 @@ class TextNewtWindow { } else if(arg0.getKeyCode() == KeyEvent.VK_6){ textGLListener.size -= 10; + System.err.println("Tex Size: " + textGLListener.size); } else if(arg0.getKeyCode() == KeyEvent.VK_7){ textGLListener.size += 10; + System.err.println("Tex Size: " + textGLListener.size); } } public void keyTyped(KeyEvent arg0) {} @@ -155,10 +157,10 @@ class TextNewtWindow { } float ang = 0; - float zoom = -300; + float zoom = -4000; float xTran = -100; float yTran = 40; - int size = 200; + int size = 190; public void display(GLAutoDrawable drawable) { GL3 gl = drawable.getGL().getGL3(); -- cgit v1.2.3 From c0bcd59a8cfc9296cb4569a08af9c42463e557e1 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Fri, 25 Mar 2011 20:42:37 +0200 Subject: Fix: RenderingDemo with MULTI_PASS doesnt uses MSAA --- src/demo/GPURegionNewtDemo02.java | 3 +-- src/demo/GPUTextNewtDemo01.java | 3 +-- src/demo/GPUTextNewtDemo02.java | 5 +---- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index a4a8e91e6..6a9e98f62 100755 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -37,6 +37,7 @@ import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.HwRegionRenderer; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; @@ -69,8 +70,6 @@ class RegionsNewtWindow { GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); caps.setDoubleBuffered(true); - caps.setSampleBuffers(true); - caps.setNumSamples(4); System.out.println(caps); final GLWindow window = GLWindow.create(caps); window.setPosition(10, 10); diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 0051df72e..3e506f5d1 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -137,7 +137,6 @@ class TextNewtWindow1 { textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); System.out.println("Realised: "+drawable.getChosenGLCapabilities()); - System.out.println("MS: " + gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); } float ang = 0; @@ -155,7 +154,7 @@ class TextNewtWindow1 { textRenderer.translate(xTran, yTran, zoom); textRenderer.rotate(ang, 0, 1, 0); - String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; String text2 = text1.toUpperCase(); Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index c59368c37..b34203014 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -69,8 +69,6 @@ class TextNewtWindow { GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); System.out.println("Requested: "+caps); final GLWindow window = GLWindow.create(caps); @@ -153,7 +151,6 @@ class TextNewtWindow { textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.TWO_PASS); gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); System.out.println("Realised: "+drawable.getChosenGLCapabilities()); - System.out.println("MS: " + gl.glIsEnabled(GL3.GL_MULTISAMPLE)); } float ang = 0; @@ -172,7 +169,7 @@ class TextNewtWindow { textRenderer.translate(xTran, yTran, zoom); textRenderer.rotate(ang, 0, 1, 0); - String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; String text2 = text1.toUpperCase(); Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); -- cgit v1.2.3 From ca5c2da3b3e03e5fb23b1cae1edf336de7e9ab20 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 22:29:46 +0100 Subject: TextDemos: Dump MSAA values, see what which AA style does .. --- src/demo/GPUTextNewtDemo01.java | 15 +++++----- src/demo/GPUTextNewtDemo02.java | 10 ++++--- src/demo/MSAATool.java | 65 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 src/demo/MSAATool.java diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 3e506f5d1..85f94b175 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -29,6 +29,7 @@ package demo; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; @@ -69,7 +70,7 @@ class TextNewtWindow1 { GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); caps.setSampleBuffers(true); // FIXME: sure ? - caps.setNumSamples(4); // FIXME: sure ? + caps.setNumSamples(1); // FIXME: sure ? System.out.println("Requested: "+caps); final GLWindow window = GLWindow.create(caps); @@ -135,10 +136,13 @@ class TextNewtWindow1 { gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); - - System.out.println("Realised: "+drawable.getChosenGLCapabilities()); + textRenderer.setAlpha(1.0f); + textRenderer.setColor(0.0f, 0.0f, 1.0f); + //gl.glSampleCoverage(0.75f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // FIXME: coverage makes it 'funny' .. ie 'hole mask' + MSAATool.dump(drawable); } - + float ang = 0; float zoom = -70; float xTran = -10; @@ -161,9 +165,6 @@ class TextNewtWindow1 { float[] position = new float[]{0,0,0}; try { - textRenderer.setAlpha(1.0f); - textRenderer.setColor(0.0f, 0.0f, 1.0f); - gl.glSampleCoverage(0.75f, false); textRenderer.renderString3D(font, text2, position, 0); } catch (Exception e) { e.printStackTrace(); diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index b34203014..269287232 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -29,6 +29,7 @@ package demo; import javax.media.opengl.GL; import javax.media.opengl.GL2; +import javax.media.opengl.GL2GL3; import javax.media.opengl.GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; @@ -149,8 +150,12 @@ class TextNewtWindow { gl.glEnable(GL3.GL_DEPTH_TEST); textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.TWO_PASS); + textRenderer.setAlpha(1.0f); + textRenderer.setColor(0.0f, 0.0f, 0.0f); + gl.glSampleCoverage(0.75f, false); + gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // FIXME: Does sample coverage make a difference here ? gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); - System.out.println("Realised: "+drawable.getChosenGLCapabilities()); + MSAATool.dump(drawable); } float ang = 0; @@ -176,9 +181,6 @@ class TextNewtWindow { float[] position = new float[]{0,0,0}; try { - textRenderer.setAlpha(1.0f); - textRenderer.setColor(0.0f, 0.0f, 0.0f); - gl.glSampleCoverage(0.75f, false); textRenderer.renderString3D(font, text2, position, size); } catch (Exception e) { e.printStackTrace(); diff --git a/src/demo/MSAATool.java b/src/demo/MSAATool.java new file mode 100644 index 000000000..a31005f08 --- /dev/null +++ b/src/demo/MSAATool.java @@ -0,0 +1,65 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; + +public class MSAATool { + public static void dump(GLAutoDrawable drawable) { + float[] vf = new float[] { 0f }; + byte[] vb = new byte[] { 0 }; + int[] vi = new int[] { 0, 0 }; + + System.out.println("GL MSAA SETUP:"); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + System.out.println(" Caps realised "+caps); + System.out.println(" Caps sample buffers "+caps.getSampleBuffers()+", samples "+caps.getNumSamples()); + + // default TRUE + System.out.println(" GL MULTISAMPLE "+gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE)); + // default FALSE, value 1, invert false + gl.glGetFloatv(GL2GL3.GL_SAMPLE_COVERAGE_VALUE, vf, 0); + gl.glGetBooleanv(GL2GL3.GL_SAMPLE_COVERAGE_INVERT, vb, 0); + System.out.println(" GL SAMPLE_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE) + + ": SAMPLE_COVERAGE_VALUE "+vf[0]+ + ", SAMPLE_COVERAGE_INVERT "+vb[0]); + // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB + gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0); + // samples min 0 + gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1); + System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); + } +} -- cgit v1.2.3 From d1e73ec50d31017bc4d1697a16e53a8cfc631a0e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 22:31:58 +0100 Subject: TextDemo02 multi pass: no MSAA - right --- src/demo/GPUTextNewtDemo02.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 269287232..3867800d1 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -152,8 +152,7 @@ class TextNewtWindow { textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.TWO_PASS); textRenderer.setAlpha(1.0f); textRenderer.setColor(0.0f, 0.0f, 0.0f); - gl.glSampleCoverage(0.75f, false); - gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // FIXME: Does sample coverage make a difference here ? + gl.glDisable(GL.GL_MULTISAMPLE); // this state usually doesn't matter in driver - but document here: no MSAA gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); MSAATool.dump(drawable); } -- cgit v1.2.3 From 3802ffdb0a5bc84978303e342c8729ca3ba819c9 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 22:40:12 +0100 Subject: sample coverage: no diff to lines --- src/demo/GPUTextNewtDemo01.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 85f94b175..f8792987c 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -138,8 +138,9 @@ class TextNewtWindow1 { textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); textRenderer.setAlpha(1.0f); textRenderer.setColor(0.0f, 0.0f, 1.0f); - //gl.glSampleCoverage(0.75f, false); - //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // FIXME: coverage makes it 'funny' .. ie 'hole mask' + //gl.glSampleCoverage(0.95f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); } -- cgit v1.2.3 From a32d0c2b5a584be99f9e18d0c070cda8cfc18864 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 22:57:35 +0100 Subject: TextDemo01 (MSAA): 4 samples --- src/demo/GPUTextNewtDemo01.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index f8792987c..d31920294 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -69,8 +69,8 @@ class TextNewtWindow1 { GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); - caps.setSampleBuffers(true); // FIXME: sure ? - caps.setNumSamples(1); // FIXME: sure ? + caps.setSampleBuffers(true); + caps.setNumSamples(2); // 2 samples is not enough .. System.out.println("Requested: "+caps); final GLWindow window = GLWindow.create(caps); -- cgit v1.2.3 From 0976b895fd595ca29c6854ee4cfd9c402e9d27e6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 22:59:12 +0100 Subject: TextDemo01 (MSAA): 4 samples (duh) --- src/demo/GPUTextNewtDemo01.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index d31920294..ce6943463 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -70,7 +70,7 @@ class TextNewtWindow1 { GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); caps.setSampleBuffers(true); - caps.setNumSamples(2); // 2 samples is not enough .. + caps.setNumSamples(4); // 2 samples is not enough .. System.out.println("Requested: "+caps); final GLWindow window = GLWindow.create(caps); -- cgit v1.2.3 From 28c3731a75da19661f4ed5d6208807d7c4d0fb5a Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Mar 2011 23:15:00 +0100 Subject: WindowTitle: Add r2t/msaa - Region Demos: Dump MSAA --- src/demo/GPURegionNewtDemo01.java | 34 ++++++++++++++++++---------------- src/demo/GPURegionNewtDemo02.java | 11 +++++------ src/demo/GPUTextNewtDemo01.java | 4 ++-- src/demo/GPUTextNewtDemo02.java | 2 +- 4 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java index 76e4bb97b..cde4df683 100755 --- a/src/demo/GPURegionNewtDemo01.java +++ b/src/demo/GPURegionNewtDemo01.java @@ -69,19 +69,18 @@ class RegionNewtWindow { } private void createWindow() { GLProfile.initSingleton(true); - GLProfile glp = GLProfile.getGL2ES2(); - GLCapabilities caps = new GLCapabilities(glp); - caps.setDoubleBuffered(true); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - System.out.println(caps); - final GLWindow window = GLWindow.create(caps); - window.setPosition(10, 10); - window.setSize(500, 500); - - window.setTitle("GPU Curve Region Newt Demo 01"); - regionGLListener = new RegionGLListener(); - window.addGLEventListener(regionGLListener); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); // 2 samples is not enough .. + System.out.println("Requested: " + caps); + final GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(500, 500); + window.setTitle("GPU Curve Region Newt Demo 01 - r2t0 msaa1"); + regionGLListener = new RegionGLListener(); + window.addGLEventListener(regionGLListener); window.setVisible(true); @@ -174,6 +173,12 @@ class RegionNewtWindow { gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); regionRenderer = new HwRegionRenderer(drawable.getContext()); + regionRenderer.setAlpha(1.0f); + regionRenderer.setColor(0.0f, 0.0f, 0.0f); + //gl.glSampleCoverage(0.95f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); + MSAATool.dump(drawable); createTestOutline(); } @@ -193,9 +198,6 @@ class RegionNewtWindow { regionRenderer.rotate(ang, 0, 1, 0); try { - regionRenderer.setAlpha(1.0f); - regionRenderer.setColor(0.0f, 0.0f, 1.0f); - regionRenderer.renderOutlineShape(outlineShape, new float[]{0,0,0}); } catch (Exception e) { e.printStackTrace(); diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index 6a9e98f62..7de9efa43 100755 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -69,13 +69,12 @@ class RegionsNewtWindow { GLProfile.initSingleton(true); GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); - caps.setDoubleBuffered(true); - System.out.println(caps); + System.out.println("Requested: "+caps); final GLWindow window = GLWindow.create(caps); window.setPosition(10, 10); window.setSize(500, 500); - window.setTitle("GPU Curve Region Newt Demo 01"); + window.setTitle("GPU Curve Region Newt Demo 02 - r2t0 msaa0"); regionGLListener = new RegionGLListener(); window.addGLEventListener(regionGLListener); @@ -170,6 +169,9 @@ class RegionsNewtWindow { gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); regionRenderer = new HwRegionRenderer(drawable.getContext()); + regionRenderer.setAlpha(1.0f); + regionRenderer.setColor(0.0f, 0.0f, 0.0f); + MSAATool.dump(drawable); createTestOutline(); } @@ -189,9 +191,6 @@ class RegionsNewtWindow { regionRenderer.rotate(ang, 0, 1, 0); try { - regionRenderer.setAlpha(1.0f); - regionRenderer.setColor(0.0f, 0.0f, 1.0f); - regionRenderer.renderOutlineShapes(outlineShapes, new float[]{0,0,0}); } catch (Exception e) { e.printStackTrace(); diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index ce6943463..25c40b433 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -78,7 +78,7 @@ class TextNewtWindow1 { window.setPosition(10, 10); window.setSize(500, 500); - window.setTitle("GPU Text Newt Demo 01"); + window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); textGLListener = new TextGLListener(); window.addGLEventListener(textGLListener); @@ -137,7 +137,7 @@ class TextNewtWindow1 { gl.glEnable(GL2ES2.GL_DEPTH_TEST); textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); textRenderer.setAlpha(1.0f); - textRenderer.setColor(0.0f, 0.0f, 1.0f); + textRenderer.setColor(0.0f, 0.0f, 0.0f); //gl.glSampleCoverage(0.95f, false); //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 3867800d1..4f5e62b31 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -77,7 +77,7 @@ class TextNewtWindow { window.setPosition(10, 10); window.setSize(1000, 1000); - window.setTitle("GPU Text Newt Demo 02"); + window.setTitle("GPU Text Newt Demo 01 - r2t1 msaa0"); textGLListener = new TextGLListener(); window.addGLEventListener(textGLListener); -- cgit v1.2.3 From 654c2bfbfcfb00b5ffe67e2490cebbfa267049e4 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 26 Mar 2011 12:47:05 +0100 Subject: Common demo gllistener for text; Cleanup HwTextRenderer: Use GL as parameter (matching API), only update data if necessary (uniform), hold data in GLUniform --- src/com/jogamp/graph/curve/OutlineShape.java | 1 - .../jogamp/graph/curve/text/HwTextRenderer.java | 213 ++++++++++---------- src/demo/GPURegionNewtDemo02.java | 1 - src/demo/GPUTextGLListenerBase01.java | 223 +++++++++++++++++++++ src/demo/GPUTextNewtDemo01.java | 146 +++----------- src/demo/GPUTextNewtDemo02.java | 187 ++++------------- src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 59 ++++-- src/jogamp/graph/font/typecast/TypecastFont.java | 3 - 8 files changed, 431 insertions(+), 402 deletions(-) create mode 100644 src/demo/GPUTextGLListenerBase01.java diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index b48804b4d..d7b941282 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -36,7 +36,6 @@ import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Line; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.curve.tess.CDTriangulator2D; diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java index bbe62f158..b16d2e6fd 100644 --- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java +++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java @@ -32,8 +32,6 @@ import java.util.HashMap; import java.util.Iterator; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; @@ -82,37 +80,38 @@ public class HwTextRenderer { return fontFactory; } - private ShaderState st; + private ShaderState st = new ShaderState(); + private PMVMatrix pmvMatrix = new PMVMatrix(); + private GLUniformData mgl_PMVMatrix; /**Sharpness is equivalent to the value of t value of texture coord * on the off-curve vertex. The high value of sharpness will * result in high curvature. */ - private float sharpness = 0.5f; - private float alpha = 1.0f; - private float strength = 1.8f; - private boolean initialized = false; - + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); + + private boolean initialized = false; private int regionType = Region.SINGLE_PASS; - private GLContext context; - private FloatBuffer color = FloatBuffer.allocate(3); + private HashMap strings = new HashMap(); private final Vertex.Factory pointFactory; int win_width = 0; int win_height = 0; - /** Create a Hardware accelerated Text Renderer + /** + * Create a Hardware accelerated Text Renderer. * @param context OpenGL rendering context * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. */ - public HwTextRenderer(GLContext context, Vertex.Factory factory, int type) { + public HwTextRenderer(Vertex.Factory factory, int type) { this.pointFactory = (null != factory) ? factory : SVertex.factory(); - this.context = context; this.regionType = type; - init(context, 0.5f); } public Font createFont(Vertex.Factory factory, String name, int size) { @@ -129,22 +128,22 @@ public class HwTextRenderer { return fontFactory.createFont(factory, families, style, variant, weight, size); } - /** initialize shaders and bindings for GPU based text Rendering, should - * be called only onceangle + /** + * Initialize shaders and bindings for GPU based text Rendering, + * should be called only once. + * Leaves the renderer enables, ie ShaderState on. + * * @param drawable the current drawable * @param shapvalue shaprness around the off-curve vertices * @return true if init succeeded, false otherwise */ - private boolean init(GLContext context, float sharpvalue){ + public boolean init(GL2ES2 gl){ if(initialized){ if(DEBUG) { System.err.println("HWTextRenderer: Already initialized!"); } return true; } - sharpness = sharpvalue; - - GL2ES2 gl = context.getGL().getGL2ES2(); boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && gl.isFunctionAvailable("glBindBuffer") && @@ -161,12 +160,25 @@ public class HwTextRenderer { return false; } - gl.setSwapInterval(1); - gl.glEnable(GL2ES2.GL_BLEND); gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - initShader(gl); + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWTextRenderer: Couldn't link program: "+sp); + } + + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); st.glUseProgram(gl, true); @@ -177,38 +189,41 @@ public class HwTextRenderer { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); pmvMatrix.glLoadIdentity(); - resetMatrix(); - - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { + resetMatrix(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { if(DEBUG){ System.err.println("Error setting PMVMatrix in shader: "+st); } return false; } - if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { + + if(!st.glUniform(gl, mgl_sharpness)) { if(DEBUG){ System.err.println("Error setting sharpness in shader: "+st); } return false; } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + + if(!st.glUniform(gl, mgl_alpha)) { if(DEBUG){ System.err.println("Error setting global alpha in shader: "+st); } return false; - } - if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { + } + + if(!st.glUniform(gl, mgl_color)) { if(DEBUG){ System.err.println("Error setting global color in shader: "+st); } return false; - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + } + + if(!st.glUniform(gl, mgl_strength)) { System.err.println("Error setting antialias strength in shader: "+st); } - st.glUseProgram(gl, false); - if(DEBUG) { System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); } @@ -216,41 +231,75 @@ public class HwTextRenderer { return true; } + public void dispose(GL2ES2 gl) { + st.destroy(gl); + clearCached(); + } + public float getAlpha() { - return alpha; + return mgl_alpha.floatValue(); } - public void setAlpha(float alpha_t) { - alpha = alpha_t; + + public ShaderState getShaderState() { + return st; } - public void setColor(float r, float g, float b){ - color.put(r); - color.put(g); - color.put(b); - color.rewind(); + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } } - public void rotate(float angle, float x, float y, float z){ + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ pmvMatrix.glRotatef(angle, x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } } - public void translate(float x, float y, float z){ + public void translate(GL2ES2 gl, float x, float y, float z){ pmvMatrix.glTranslatef(x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } } - public void resetMatrix(){ + public void resetMatrix(GL2ES2 gl){ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } } + public void updateAllShaderValues(GL2ES2 gl) { + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + st.glUniform(gl, mgl_alpha); + st.glUniform(gl, mgl_color); + st.glUniform(gl, mgl_strength); + } + } + /** - * @param drawable + * @param gl * @param angle * @param ratio * @param near * @param far * @return */ - public boolean reshape(GLAutoDrawable drawable, float angle, int width, int height, float near, float far){ + public boolean reshape(GL2ES2 gl, float angle, int width, int height, float near, float far){ win_width = width; win_height = height; float ratio = (float)width/(float)height; @@ -258,44 +307,12 @@ public class HwTextRenderer { pmvMatrix.glLoadIdentity(); pmvMatrix.gluPerspective(angle, ratio, near, far); - if(null==st) { - if(DEBUG){ - System.err.println("HWTextRenderer: Shader State is null, or not"); - } - return false; - } - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - st.glUseProgram(gl, false); + st.glUniform(gl, mgl_PMVMatrix); + return true; } - private void initShader(GL2ES2 gl) { - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWTextRenderer: Couldn't link program: "+sp); - } - - st = new ShaderState(); - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - } - - private GlyphString createString(Font font, String str) { + private GlyphString createString(GL2ES2 gl, Font font, String str) { AffineTransform affineTransform = new AffineTransform(pointFactory); Path2D[] paths = new Path2D[str.length()]; @@ -304,11 +321,17 @@ public class HwTextRenderer { GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); glyphString.createfromFontPath(paths, affineTransform); - glyphString.generateRegion(context, sharpness, st, regionType); + glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); return glyphString; } + public void enable(GL2ES2 gl, boolean enable) { + if(null != gl) { + st.glUseProgram(gl, enable); + } + } + /** Render the String in 3D space wrt to the font provided at the position provided * the outlines will be generated, if not yet generated * @param font font to be used @@ -317,36 +340,18 @@ public class HwTextRenderer { * @param size texture size for multipass render * @throws Exception if TextRenderer not initialized */ - public void renderString3D(Font font, String str, float[] position, int size) throws Exception{ + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int size) { if(!initialized){ - throw new Exception("HWTextRenderer: not initialized!"); + throw new GLException("HWTextRenderer: not initialized!"); } String fontStrHash = getTextHashCode(font, str); GlyphString glyphString = strings.get(fontStrHash); if(null == glyphString) { - glyphString = createString(font, str); + glyphString = createString(gl, font, str); strings.put(fontStrHash, glyphString); } - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } glyphString.renderString3D(pmvMatrix, win_width, win_height, size); - st.glUseProgram(gl, false); } private String getTextHashCode(Font font, String str){ diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index 7de9efa43..f9d7bb944 100755 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -37,7 +37,6 @@ import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.HwRegionRenderer; import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.Region; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java new file mode 100644 index 000000000..afdec1220 --- /dev/null +++ b/src/demo/GPUTextGLListenerBase01.java @@ -0,0 +1,223 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLPipelineFactory; + +import com.jogamp.graph.curve.text.HwTextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; + +public abstract class GPUTextGLListenerBase01 implements GLEventListener { + Vertex.Factory vfactory; + HwTextRenderer textRenderer; + KeyAction keyAction; + + boolean fontUpdate = true; + int fontSize = 40; + final int fontSizeModulo = 100; + Font font; + + final float[] position = new float[] {0,0,0}; + + float xTran = -10; + float yTran = 10; + float ang = 0f; + float zoom = -70f; + // float zoom = -1000f; + int texSize = 400; // FBO/tex size .. + + boolean doMatrix = true; + boolean debug; + boolean trace; + static final String text1; + static final String text2; + + static { + text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; // \n0123456789"; + text2 = text1.toUpperCase(); + } + + public GPUTextGLListenerBase01(Vertex.Factory vfactory, int mode, boolean debug, boolean trace) { + this.textRenderer = new HwTextRenderer(vfactory, mode); + this.vfactory = vfactory; + this.debug = debug; + this.trace = trace; + } + + public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) { + this.xTran = xtrans; + this.yTran = ytrans; + this.ang = angle; + this.zoom = zoom; + this.texSize = fbosize; + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + } + + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glViewport(xstart, ystart, width, height); + textRenderer.reshape(gl, 45.0f, width, height, 0.1f, 7000.0f); + + dumpMatrix(); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + if(doMatrix) { + textRenderer.resetMatrix(gl); + textRenderer.translate(gl, xTran, yTran, zoom); + textRenderer.rotate(gl, ang, 0, 1, 0); + doMatrix = false; + } + + if(fontUpdate) { + font = textRenderer.createFont(vfactory, "Lucida Sans Regular", fontSize); + fontUpdate = false; + } + textRenderer.renderString3D(gl, font, text2, position, texSize); + } + + public void dispose(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + textRenderer.dispose(gl); + } + + public void fontIncr(int v) { + fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; + fontUpdate = true; + dumpMatrix(); + } + + public void zoom(int v){ + zoom += v; + doMatrix = true; + dumpMatrix(); + } + + public void move(float x, float y){ + xTran += x; + yTran += y; + doMatrix = true; + dumpMatrix(); + } + public void rotate(float delta){ + ang += delta; + ang %= 360.0f; + doMatrix = true; + dumpMatrix(); + } + + void dumpMatrix() { + System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang +" fontSize "+fontSize); + } + + public void attachTo(GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + } + window.addGLEventListener(this); + window.addKeyListener(keyAction); + } + + public void detachFrom(GLWindow window) { + if ( null == keyAction ) { + return; + } + window.removeGLEventListener(this); + window.removeKeyListener(keyAction); + } + + public class KeyAction implements KeyListener { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + zoom(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + zoom(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_3){ + fontIncr(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_4){ + fontIncr(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + texSize -= 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + texSize += 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + rotate(-1); + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + } +} \ No newline at end of file diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 25c40b433..ad1020122 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -27,44 +27,28 @@ */ package demo; -import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GL2GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.text.HwTextRenderer; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.FPSAnimator; public class GPUTextNewtDemo01 { - private static void create(){ - new TextNewtWindow1(); - } + static final boolean DEBUG = false; + static final boolean TRACE = false; + public static void main(String[] args) { - create(); + GPUTextNewtDemo01 test = new GPUTextNewtDemo01(); + test.testMe(); } -} - -class TextNewtWindow1 { - Vertex.Factory pointFactory = SVertex.factory(); TextGLListener textGLListener = null; - public TextNewtWindow1(){ - createWindow(); - } - private void createWindow() { + public void testMe() { GLProfile.initSingleton(true); GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); @@ -80,120 +64,36 @@ class TextNewtWindow1 { window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); textGLListener = new TextGLListener(); - window.addGLEventListener(textGLListener); + textGLListener.attachTo(window); window.setVisible(true); - - window.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - textGLListener.zoomIn(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - textGLListener.zoomOut(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - textGLListener.move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - textGLListener.move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - textGLListener.move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - textGLListener.move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - textGLListener.rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - textGLListener.rotate(-1); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - }); - - FPSAnimator animator = new FPSAnimator(60); + FPSAnimator animator = new FPSAnimator(10); + // Animator animator = new Animator(); animator.add(window); - window.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent arg0) { - System.exit(0); - }; - }); animator.start(); } - private class TextGLListener implements GLEventListener{ - HwTextRenderer textRenderer = null; - - public TextGLListener(){ - + + private class TextGLListener extends GPUTextGLListenerBase01 { + public TextGLListener() { + super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); + setMatrix(-10, 10, 0f, -70, 0); } - + public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + super.init(drawable); + gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.SINGLE_PASS); - textRenderer.setAlpha(1.0f); - textRenderer.setColor(0.0f, 0.0f, 0.0f); + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); //gl.glSampleCoverage(0.95f, false); //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE); //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); } - - float ang = 0; - float zoom = -70; - float xTran = -10; - float yTran = 10; - - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - textRenderer.resetMatrix(); - textRenderer.translate(xTran, yTran, zoom); - textRenderer.rotate(ang, 0, 1, 0); - - String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; - String text2 = text1.toUpperCase(); - - Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); - float[] position = new float[]{0,0,0}; - - try { - textRenderer.renderString3D(font, text2, position, 0); - } catch (Exception e) { - e.printStackTrace(); - } - } - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ - GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.glViewport(xstart, ystart, width, height); - - textRenderer.reshape(drawable, 45.0f, width, height, 0.1f, 7000.0f); - } - - public void zoomIn(){ - zoom++; - } - public void zoomOut(){ - zoom--; - } - public void move(float x, float y){ - xTran += x; - yTran += y; - } - public void rotate(float delta){ - ang+= delta; - ang%=360; - } - public void dispose(GLAutoDrawable arg0) { - textRenderer.clearCached(); - } } } diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 4f5e62b31..c7e7504ab 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -28,188 +28,79 @@ package demo; import javax.media.opengl.GL; -import javax.media.opengl.GL2; -import javax.media.opengl.GL2GL3; import javax.media.opengl.GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.text.HwTextRenderer; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.FPSAnimator; public class GPUTextNewtDemo02 { - private static void create(){ - new TextNewtWindow(); - } - public static void main(String[] args) { - create(); - } -} - -class TextNewtWindow { - Vertex.Factory pointFactory = SVertex.factory(); + /** + * If DEBUG is enabled: + * + * Caused by: javax.media.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer( 0x8D40, 0x1902, 0x8D41, 0x1): GL_INVALID_ENUM ( 1280 0x500), + * at javax.media.opengl.DebugGL4bc.checkGLGetError(DebugGL4bc.java:33961) + * at javax.media.opengl.DebugGL4bc.glFramebufferRenderbuffer(DebugGL4bc.java:33077) + * at jogamp.graph.curve.opengl.VBORegion2PGL3.initFBOTexture(VBORegion2PGL3.java:295) + */ + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GPUTextNewtDemo02 test = new GPUTextNewtDemo02(); + test.testMe(); + } + + GLWindow window; TextGLListener textGLListener = null; - public TextNewtWindow(){ - createWindow(); - } - private void createWindow() { + public void testMe() { GLProfile.initSingleton(true); - GLProfile glp = GLProfile.get(GLProfile.GL3); + GLProfile glp = GLProfile.get(GLProfile.GL3bc); GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); System.out.println("Requested: "+caps); - final GLWindow window = GLWindow.create(caps); + window = GLWindow.create(caps); window.setPosition(10, 10); - window.setSize(1000, 1000); + window.setSize(400, 400); - window.setTitle("GPU Text Newt Demo 01 - r2t1 msaa0"); - textGLListener = new TextGLListener(); - window.addGLEventListener(textGLListener); + window.setTitle("GPU Text Newt Demo 02 - r2t1 msaa0"); + textGLListener = new TextGLListener(); + textGLListener.attachTo(window); window.setVisible(true); - window.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - textGLListener.zoomIn(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - textGLListener.zoomOut(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_3){ - textGLListener.zoomIn(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_4){ - textGLListener.zoomOut(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - textGLListener.move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - textGLListener.move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - textGLListener.move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - textGLListener.move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - textGLListener.rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - textGLListener.rotate(-1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_6){ - textGLListener.size -= 10; - System.err.println("Tex Size: " + textGLListener.size); - } - else if(arg0.getKeyCode() == KeyEvent.VK_7){ - textGLListener.size += 10; - System.err.println("Tex Size: " + textGLListener.size); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - }); - FPSAnimator animator = new FPSAnimator(60); animator.add(window); - window.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent arg0) { - System.exit(0); - }; - }); animator.start(); } - private class TextGLListener implements GLEventListener{ - HwTextRenderer textRenderer = null; - - public TextGLListener(){ - - } - + + private class TextGLListener extends GPUTextGLListenerBase01 { + public TextGLListener() { + super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); + setMatrix(-10, 10, 0f, -1000, window.getWidth()); + } + public void init(GLAutoDrawable drawable) { - GL3 gl = drawable.getGL().getGL3(); + GL3 gl = drawable.getGL().getGL3(); + + super.init(drawable); + gl.setSwapInterval(1); gl.glEnable(GL3.GL_DEPTH_TEST); - - textRenderer = new HwTextRenderer(drawable.getContext(), pointFactory, Region.TWO_PASS); - textRenderer.setAlpha(1.0f); - textRenderer.setColor(0.0f, 0.0f, 0.0f); + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); gl.glDisable(GL.GL_MULTISAMPLE); // this state usually doesn't matter in driver - but document here: no MSAA - gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); + //gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); MSAATool.dump(drawable); } - - float ang = 0; - float zoom = -4000; - float xTran = -100; - float yTran = 40; - int size = 190; - - public void display(GLAutoDrawable drawable) { - GL3 gl = drawable.getGL().getGL3(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - textRenderer.resetMatrix(); - textRenderer.translate(xTran, yTran, zoom); - textRenderer.rotate(ang, 0, 1, 0); - - String text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; - String text2 = text1.toUpperCase(); - - Font font = textRenderer.createFont(pointFactory, "Lucida Sans Regular",40); - float[] position = new float[]{0,0,0}; - - try { - textRenderer.renderString3D(font, text2, position, size); - } catch (Exception e) { - e.printStackTrace(); - } - } - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ - GL3 gl = drawable.getGL().getGL3(); - gl.glViewport(xstart, ystart, width, height); - - textRenderer.reshape(drawable, 45.0f, width , height, 0.1f, 7000.0f); - } - - public void zoomIn(float f){ - zoom+=f; - } - public void zoomOut(float f){ - zoom-=f; - System.err.println("Zoom: " + zoom); - } - public void move(float x, float y){ - xTran += x; - yTran += y; - } - public void rotate(float delta){ - ang+= delta; - ang%=360; - } - - public void dispose(GLAutoDrawable arg0) { - textRenderer.clearCached(); - } } } diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java index 4f2714494..0330accbe 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -64,9 +64,9 @@ public class VBORegion2PGL3 implements Region{ private boolean dirty = false; private AABBox box = null; - private IntBuffer texture = IntBuffer.allocate(1); - private IntBuffer fbo = IntBuffer.allocate(1); - private IntBuffer rbo = IntBuffer.allocate(1); + private int[] texture = { 0 } ; + private int[] fbo = { 0 } ; + private int[] rbo_depth = { 0 } ; private boolean texInitialized = false; private int tex_width_c = 0; @@ -178,9 +178,9 @@ public class VBORegion2PGL3 implements Region{ } gl.glEnable(GL3.GL_TEXTURE_2D); gl.glActiveTexture(GL3.GL_TEXTURE0); - gl.glBindTexture(GL3.GL_TEXTURE_2D, texture.get(0)); + gl.glBindTexture(GL3.GL_TEXTURE_2D, texture[0]); - st.glUniform(gl, new GLUniformData("texture", texture.get(0))); + st.glUniform(gl, new GLUniformData("texture", texture[0])); int loc = gl.glGetUniformLocation(st.shaderProgram().id(), "texture"); gl.glUniform1i(loc, 0); @@ -257,14 +257,27 @@ public class VBORegion2PGL3 implements Region{ private void initFBOTexture(PMVMatrix m, int width, int hight){ tex_height_c = (int)(tex_width_c*box.getHeight()/box.getWidth()); - System.out.println("Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); + // tex_height_c = tex_width_c; + System.out.println("FBO Size: "+tex_height_c+"x"+tex_width_c); + System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); GL3 gl = context.getGL().getGL3(); - gl.glDeleteFramebuffers(1, fbo); - gl.glDeleteTextures(1, texture); + if(fbo[0] > 0) { + gl.glDeleteFramebuffers(1, fbo, 0); + fbo[0] = 0; + } + if(texture[0]>0) { + gl.glDeleteTextures(1, texture, 0); + texture[0] = 0; + } + + gl.glGenFramebuffers(1, fbo, 0); + gl.glGenTextures(1, texture, 0); + gl.glGenRenderbuffers(1,rbo_depth, 0); + System.out.println("FBO: fbo " + fbo[0] + ", tex " + texture[0] + ", depth " + rbo_depth[0]); - gl.glGenTextures(1, texture); - gl.glBindTexture(GL3.GL_TEXTURE_2D, texture.get(0)); + gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); + gl.glBindTexture(GL3.GL_TEXTURE_2D, texture[0]); gl.glTexImage2D(GL3.GL_TEXTURE_2D, 0, GL3.GL_RGBA, tex_width_c, tex_height_c, 0, GL3.GL_RGBA, GL3.GL_UNSIGNED_BYTE, null); @@ -272,16 +285,14 @@ public class VBORegion2PGL3 implements Region{ gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_LINEAR); gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE); gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE); - - gl.glGenRenderbuffers(1,rbo); - gl.glBindRenderbuffer(GL3.GL_RENDERBUFFER, rbo.get(0)); - gl.glRenderbufferStorage(GL3.GL_RENDERBUFFER, GL3.GL_DEPTH_COMPONENT, tex_width_c, tex_height_c); - - gl.glGenFramebuffers(1, fbo); - gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo.get(0)); + gl.glFramebufferTexture2D(GL3.GL_DRAW_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, - GL3.GL_TEXTURE_2D, texture.get(0), 0); - gl.glFramebufferRenderbuffer(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_COMPONENT, GL3.GL_RENDERBUFFER, rbo.get(0)); + GL3.GL_TEXTURE_2D, texture[0], 0); + + // Set up the depth buffer + gl.glBindRenderbuffer(GL3.GL_RENDERBUFFER, rbo_depth[0]); + gl.glRenderbufferStorage(GL3.GL_RENDERBUFFER, GL3.GL_DEPTH_COMPONENT, tex_width_c, tex_height_c); + gl.glFramebufferRenderbuffer(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_COMPONENT, GL3.GL_RENDERBUFFER, rbo_depth[0]); int status = gl.glCheckFramebufferStatus(GL3.GL_FRAMEBUFFER); if(status != GL3.GL_FRAMEBUFFER_COMPLETE){ @@ -290,7 +301,7 @@ public class VBORegion2PGL3 implements Region{ //render texture PMVMatrix tex_matrix = new PMVMatrix(); - gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo.get(0)); + gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); gl.glViewport(0, 0, tex_width_c, tex_height_c); tex_matrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); tex_matrix.glLoadIdentity(); @@ -349,8 +360,12 @@ public class VBORegion2PGL3 implements Region{ public void destroy() { GL3 gl = context.getGL().getGL3(); gl.glDeleteBuffers(numBuffers, vboIds); - gl.glDeleteFramebuffers(1, fbo); - gl.glDeleteTextures(1, texture); + gl.glDeleteFramebuffers(1, fbo, 0); + fbo[0] = 0; + gl.glDeleteTextures(1, texture, 0); + texture[0] = 0; + gl.glDeleteRenderbuffers(1, rbo_depth, 0); + rbo_depth[0] = 0; } public boolean isFlipped() { diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index b44a7d86b..86c9601de 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -34,7 +34,6 @@ import jogamp.graph.font.FontInt; import jogamp.graph.font.JavaFontLoader; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; - import net.java.dev.typecast.ot.OTFont; import net.java.dev.typecast.ot.OTFontCollection; import net.java.dev.typecast.ot.table.CmapFormat; @@ -42,10 +41,8 @@ import net.java.dev.typecast.ot.table.CmapTable; import net.java.dev.typecast.ot.table.ID; import com.jogamp.common.util.IntObjectHashMap; -import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.Vertex; class TypecastFont implements FontInt { static final boolean DEBUG = false; -- cgit v1.2.3 From ae00fd949a08340a1dd291d7f3e5d800feb1af46 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 26 Mar 2011 12:55:39 +0100 Subject: demo: add numbers to rendering text --- src/demo/GPUTextGLListenerBase01.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index afdec1220..8d4232ef9 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -66,7 +66,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { static final String text2; static { - text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz"; // \n0123456789"; + text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; text2 = text1.toUpperCase(); } -- cgit v1.2.3 From a7c95f26e87460b76763f26723bbd9379c9fc4cb Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 26 Mar 2011 19:23:47 +0100 Subject: revert to 2nd pass magic fbo size 190 --- src/demo/GPUTextNewtDemo02.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index c7e7504ab..1fbd253c9 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -85,7 +85,7 @@ public class GPUTextNewtDemo02 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-10, 10, 0f, -1000, window.getWidth()); + setMatrix(-10, 10, 0f, -1000, 190); } public void init(GLAutoDrawable drawable) { -- cgit v1.2.3 From 929fc058c56781763c79015f4dbbf9e14dc808a2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 26 Mar 2011 19:26:41 +0100 Subject: Font: Make font instances size agnostic (remove all size states), size is only a render time parameter. Add missing bounds/width/height queries to TypecastFont --- .../jogamp/graph/curve/text/HwTextRenderer.java | 29 ++--- src/com/jogamp/graph/font/Font.java | 44 ++++--- src/com/jogamp/graph/font/FontFactory.java | 6 +- src/com/jogamp/graph/geom/AABBox.java | 7 +- src/demo/GPUTextGLListenerBase01.java | 33 +++-- src/jogamp/graph/font/FontInt.java | 9 +- src/jogamp/graph/font/typecast/TypecastFont.java | 101 +++++++++++---- .../graph/font/typecast/TypecastFontFactory.java | 11 +- src/jogamp/graph/font/typecast/TypecastGlyph.java | 135 ++++++++------------- .../graph/font/typecast/TypecastMetrics.java | 65 +++++----- .../graph/font/typecast/TypecastRenderer.java | 14 +-- src/net/java/dev/typecast/ot/table/HdmxTable.java | 13 ++ 12 files changed, 245 insertions(+), 222 deletions(-) diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java index b16d2e6fd..f30f42cc5 100644 --- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java +++ b/src/com/jogamp/graph/curve/text/HwTextRenderer.java @@ -114,8 +114,8 @@ public class HwTextRenderer { this.regionType = type; } - public Font createFont(Vertex.Factory factory, String name, int size) { - return fontFactory.createFont(factory, name, size); + public Font createFont(Vertex.Factory factory, String name) { + return fontFactory.createFont(factory, name); } @@ -123,9 +123,8 @@ public class HwTextRenderer { String[] families, String style, String variant, - String weight, - String size) { - return fontFactory.createFont(factory, families, style, variant, weight, size); + String weight) { + return fontFactory.createFont(factory, families, style, variant, weight); } /** @@ -312,11 +311,11 @@ public class HwTextRenderer { return true; } - private GlyphString createString(GL2ES2 gl, Font font, String str) { + private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { AffineTransform affineTransform = new AffineTransform(pointFactory); Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getOutline(str, affineTransform, paths); + ((FontInt)font).getOutline(str, size, affineTransform, paths); GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); glyphString.createfromFontPath(paths, affineTransform); @@ -337,25 +336,27 @@ public class HwTextRenderer { * @param font font to be used * @param str text to be rendered * @param position the lower left corner of the string - * @param size texture size for multipass render + * @param fontSize font size + * @param texSize texture size for multipass render * @throws Exception if TextRenderer not initialized */ - public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int size) { + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { if(!initialized){ throw new GLException("HWTextRenderer: not initialized!"); } - String fontStrHash = getTextHashCode(font, str); + String fontStrHash = getTextHashCode(font, str, fontSize); GlyphString glyphString = strings.get(fontStrHash); if(null == glyphString) { - glyphString = createString(gl, font, str); + glyphString = createString(gl, font, fontSize, str); strings.put(fontStrHash, glyphString); } - glyphString.renderString3D(pmvMatrix, win_width, win_height, size); + glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); } - private String getTextHashCode(Font font, String str){ - return "" + str.hashCode() + font.getSize(); + private String getTextHashCode(Font font, String str, int fontSize) { + // FIXME: use integer hash code + return font.getName() + "." + str.hashCode() + "." + fontSize; } /** Clears the cached string curves diff --git a/src/com/jogamp/graph/font/Font.java b/src/com/jogamp/graph/font/Font.java index 0abaad5b5..fbdf1f474 100644 --- a/src/com/jogamp/graph/font/Font.java +++ b/src/com/jogamp/graph/font/Font.java @@ -29,46 +29,44 @@ package com.jogamp.graph.font; import com.jogamp.graph.geom.AABBox; +/** + * Interface wrapper for font implementation. + * + * TrueType Font Specification: + * http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html + */ + public interface Font { /** - * Metrics for font based on pixel size ! - * - * If no pixelSize is given, this font's static pixelSize is being used. - * - * value = Table.value * fontSize * 1.0f / HeadTable.UnitsPerEm + * Metrics for font */ public interface Metrics { - public float getAscent(); - public float getDescent(); - public float getLineGap(); - public float getScale(); - public float getScaleForPixelSize(float pixelSize); - public AABBox getBBox(); + float getAscent(float pixelSize); + float getDescent(float pixelSize); + float getLineGap(float pixelSize); + float getScale(float pixelSize); + AABBox getBBox(float pixelSize); } /** - * Glyph for font symbols based on pixel size ! - * - * If no pixelSize is given, this font's static pixelSize is being used. + * Glyph for font */ public interface Glyph { public Font getFont(); public char getSymbol(); - public AABBox getBBox(); - public float getAdvance(); - public float getAdvanceForPixelSize(float pixelSize, boolean useFrationalMetrics); + public AABBox getBBox(float pixelSize); + public float getAdvance(float pixelSize, boolean useFrationalMetrics); } public String getName(); - public float getSize(); + public Metrics getMetrics(); public Glyph getGlyph(char symbol); - - public float getStringWidth(String string); - public float getStringHeight(String string); - public AABBox getStringBounds(CharSequence string); - public int getNumGlyphs(); + + public float getStringWidth(String string, float pixelSize); + public float getStringHeight(String string, float pixelSize); + public AABBox getStringBounds(CharSequence string, float pixelSize); } \ No newline at end of file diff --git a/src/com/jogamp/graph/font/FontFactory.java b/src/com/jogamp/graph/font/FontFactory.java index a96dac1b8..b595413ba 100644 --- a/src/com/jogamp/graph/font/FontFactory.java +++ b/src/com/jogamp/graph/font/FontFactory.java @@ -35,10 +35,8 @@ public interface FontFactory { String[] families, String style, String variant, - String weight, - String size); + String weight); Font createFont(Vertex.Factory factory, - String name, - int size); + String name); } \ No newline at end of file diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java index 9199e5253..2e99daa83 100644 --- a/src/com/jogamp/graph/geom/AABBox.java +++ b/src/com/jogamp/graph/geom/AABBox.java @@ -47,6 +47,11 @@ public class AABBox { computeCenter(); } + + public String toString() { + return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+ + center[0]+"/"+center[1]+"/"+center[1]+" ]"; + } public AABBox(float[] low, float[] high) @@ -56,7 +61,7 @@ public class AABBox { computeCenter(); } - + public float[] getHigh() { return high; diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 8d4232ef9..b310f1069 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -43,12 +43,14 @@ import com.jogamp.newt.opengl.GLWindow; public abstract class GPUTextGLListenerBase01 implements GLEventListener { Vertex.Factory vfactory; HwTextRenderer textRenderer; + Font font; + boolean debug; + boolean trace; + KeyAction keyAction; - boolean fontUpdate = true; int fontSize = 40; final int fontSizeModulo = 100; - Font font; final float[] position = new float[] {0,0,0}; @@ -60,8 +62,6 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { int texSize = 400; // FBO/tex size .. boolean doMatrix = true; - boolean debug; - boolean trace; static final String text1; static final String text2; @@ -71,8 +71,9 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { } public GPUTextGLListenerBase01(Vertex.Factory vfactory, int mode, boolean debug, boolean trace) { - this.textRenderer = new HwTextRenderer(vfactory, mode); this.vfactory = vfactory; + this.textRenderer = new HwTextRenderer(vfactory, mode); + this.font = textRenderer.createFont(vfactory, "Lucida Sans Regular"); this.debug = debug; this.trace = trace; } @@ -103,7 +104,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { gl.glViewport(xstart, ystart, width, height); textRenderer.reshape(gl, 45.0f, width, height, 0.1f, 7000.0f); - dumpMatrix(); + dumpMatrix(true); } public void display(GLAutoDrawable drawable) { @@ -119,11 +120,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { doMatrix = false; } - if(fontUpdate) { - font = textRenderer.createFont(vfactory, "Lucida Sans Regular", fontSize); - fontUpdate = false; - } - textRenderer.renderString3D(gl, font, text2, position, texSize); + textRenderer.renderString3D(gl, font, text2, position, fontSize, texSize); } public void dispose(GLAutoDrawable drawable) { @@ -133,31 +130,33 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { public void fontIncr(int v) { fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; - fontUpdate = true; - dumpMatrix(); + dumpMatrix(true); } public void zoom(int v){ zoom += v; doMatrix = true; - dumpMatrix(); + dumpMatrix(false); } public void move(float x, float y){ xTran += x; yTran += y; doMatrix = true; - dumpMatrix(); + dumpMatrix(false); } public void rotate(float delta){ ang += delta; ang %= 360.0f; doMatrix = true; - dumpMatrix(); + dumpMatrix(false); } - void dumpMatrix() { + void dumpMatrix(boolean bbox) { System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang +" fontSize "+fontSize); + if(bbox) { + System.err.println("bbox: "+font.getStringBounds(text2, fontSize)); + } } public void attachTo(GLWindow window) { diff --git a/src/jogamp/graph/font/FontInt.java b/src/jogamp/graph/font/FontInt.java index 5b938bdbf..c18787723 100644 --- a/src/jogamp/graph/font/FontInt.java +++ b/src/jogamp/graph/font/FontInt.java @@ -35,11 +35,10 @@ import com.jogamp.graph.font.Font; public interface FontInt extends Font { public interface Glyph extends Font.Glyph { - public Path2D getPath(); - public Path2D getPathForPixelSize(float pixelSize); + public Path2D getPath(); // unscaled path + public Path2D getPath(float pixelSize); } - public void getOutline(String string, - AffineTransform transform, - Path2D[] result); + public void getOutline(String string, float pixelSize, + AffineTransform transform, Path2D[] result); } diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index 86c9601de..1ac57c100 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -32,12 +32,15 @@ import java.io.IOException; import jogamp.graph.font.FontInt; import jogamp.graph.font.JavaFontLoader; +import jogamp.graph.font.ttf.TTFontGlyph; +import jogamp.graph.font.ttf.TTFont.Metrics; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; import net.java.dev.typecast.ot.OTFont; import net.java.dev.typecast.ot.OTFontCollection; import net.java.dev.typecast.ot.table.CmapFormat; import net.java.dev.typecast.ot.table.CmapTable; +import net.java.dev.typecast.ot.table.HdmxTable; import net.java.dev.typecast.ot.table.ID; import com.jogamp.common.util.IntObjectHashMap; @@ -50,30 +53,28 @@ class TypecastFont implements FontInt { final Vertex.Factory pointFactory; final OTFontCollection fontset; final OTFont font; - final int size; - Metrics metrics; + TypecastMetrics metrics; final CmapFormat cmapFormat; int cmapentries; // final IntIntHashMap char2Code; IntObjectHashMap char2Glyph; - public static TypecastFont create(Vertex.Factory factory, String name, int size) { + public static TypecastFont create(Vertex.Factory factory, String name) { String path = JavaFontLoader.getByName(name); OTFontCollection fontset; try { fontset = OTFontCollection.create(new File(path)); - return new TypecastFont(factory, fontset, size); + return new TypecastFont(factory, fontset); } catch (IOException e) { e.printStackTrace(); } return null; } - public TypecastFont(Vertex.Factory factory, OTFontCollection fontset, int size) { + public TypecastFont(Vertex.Factory factory, OTFontCollection fontset) { this.pointFactory = factory; this.fontset = fontset; this.font = fontset.getFont(0); - this.size = size; CmapTable cmapTable = font.getCmapTable(); CmapFormat _cmapFormat = null; @@ -124,10 +125,6 @@ class TypecastFont implements FontInt { return fontset.getFileName(); } - public float getSize() { - return size; - } - public Metrics getMetrics() { if (metrics == null) { metrics = new TypecastMetrics(this); @@ -146,28 +143,90 @@ class TypecastFont implements FontInt { if(DEBUG) { System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path); } + final HdmxTable hdmx = font.getHdmxTable(); + if (null != hdmx) { + /*if(DEBUG) { + System.err.println("hdmx "+hdmx); + }*/ + for (int i=0; i 0) { + totalHeight -= advanceY; + totalWidth = Math.max(curLineWidth, totalWidth); + } + return new AABBox(0, 0, 0, totalWidth, totalHeight,0); } final public int getNumGlyphs() { diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java index 6179986fe..04559a138 100644 --- a/src/jogamp/graph/font/typecast/TypecastFontFactory.java +++ b/src/jogamp/graph/font/typecast/TypecastFontFactory.java @@ -40,12 +40,12 @@ public class TypecastFontFactory implements FontFactory { Map fonts = new HashMap(); - public Font createFont(Factory factory, String name, int size) { - Font result = fonts.get(name + ":"+size); + public Font createFont(Factory factory, String name) { + Font result = fonts.get(name); if (result == null) { - result = TypecastFont.create(factory, name, size); + result = TypecastFont.create(factory, name); if(result != null) { - fonts.put(name+":"+size, result); + fonts.put(name, result); } } return result; @@ -56,8 +56,7 @@ public class TypecastFontFactory implements FontFactory { String[] families, String style, String variant, - String weight, - String size) { + String weight) { throw new Error("not implemented"); } diff --git a/src/jogamp/graph/font/typecast/TypecastGlyph.java b/src/jogamp/graph/font/typecast/TypecastGlyph.java index 9bb582974..88d865f9c 100644 --- a/src/jogamp/graph/font/typecast/TypecastGlyph.java +++ b/src/jogamp/graph/font/typecast/TypecastGlyph.java @@ -27,6 +27,8 @@ */ package jogamp.graph.font.typecast; +import java.util.HashMap; + import jogamp.graph.font.FontInt; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; @@ -37,93 +39,58 @@ import com.jogamp.graph.geom.AABBox; public class TypecastGlyph implements FontInt.Glyph { public class Advance { - Font font; - float advance; - float advances[]; // in pixels - float sizes[]; - float advanceCached = -1; // in pixels - float sizeCached = -1; + final Font font; + final float advance; + HashMap size2advance = new HashMap(); public Advance(Font font, float advance) { this.font = font; this.advance = advance; - - this.advances = new float[0]; - this.sizes = new float[0]; } - public float getScaleForPixelSize(float pixelSize) + public void reset() { + size2advance.clear(); + } + + public float getScale(float pixelSize) { - return this.font.getMetrics().getScaleForPixelSize(pixelSize); + return this.font.getMetrics().getScale(pixelSize); } public void add(float advance, float size) { - float advancesNew[] = new float[this.advances.length+1]; - float sizesNew[] = new float[this.sizes.length+1]; - - for (int i=0; i 0) { - string = "\n advances: \n"+string; - } return "\nAdvance:"+ "\n advance: "+this.advance+ - string; + "\n advances: \n"+size2advance; } } public class Metrics { AABBox bbox; - AABBox bbox_sized; - Advance advance; + Advance advance; public Metrics(Font font, AABBox bbox, float advance) { @@ -131,9 +98,13 @@ public class TypecastGlyph implements FontInt.Glyph { this.advance = new Advance(font, advance); } - public float getScaleForPixelSize(float pixelSize) + public void reset() { + advance.reset(); + } + + public float getScale(float pixelSize) { - return this.advance.getScaleForPixelSize(pixelSize); + return this.advance.getScale(pixelSize); } public AABBox getBBox() @@ -146,7 +117,7 @@ public class TypecastGlyph implements FontInt.Glyph { this.advance.add(advance, size); } - public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) + public float getAdvance(float size, boolean useFrationalMetrics) { return this.advance.get(size, useFrationalMetrics); } @@ -197,6 +168,11 @@ public class TypecastGlyph implements FontInt.Glyph { this.metrics = new Metrics(this.font, bbox, this.advance); } + public void reset(Path2D path) { + this.path = path; + this.metrics.reset(); + } + public Font getFont() { return this.font; } @@ -221,51 +197,36 @@ public class TypecastGlyph implements FontInt.Glyph { return this.id; } - public float getScaleForPixelSize(float pixelSize) { - return this.metrics.getScaleForPixelSize(pixelSize); + public float getScale(float pixelSize) { + return this.metrics.getScale(pixelSize); } - public AABBox getBBox(float size) { - AABBox newBox = getBBox().clone(); - newBox.scale(size); - return newBox; - } - - public AABBox getBBoxForPixelSize(float pixelSize) { - return getBBox(getScaleForPixelSize(pixelSize)); + public AABBox getBBox(float pixelSize) { + final float size = getScale(pixelSize); + AABBox newBox = getBBox().clone(); + newBox.scale(size); + return newBox; } protected void addAdvance(float advance, float size) { this.metrics.addAdvance(advance, size); } - public float getAdvanceForPixelSize(float size, boolean useFrationalMetrics) { - return this.metrics.getAdvanceForPixelSize(size, useFrationalMetrics); - } - - public float getAdvance() { - return getAdvanceForPixelSize(font.getSize(), false); + public float getAdvance(float pixelSize, boolean useFrationalMetrics) { + return this.metrics.getAdvance(pixelSize, useFrationalMetrics); } public Path2D getPath() { - return getPath(getScaleForPixelSize(font.getSize())); + return this.path; } - private Path2D getPath(float size) - { + public Path2D getPath(float pixelSize) { + final float size = getScale(pixelSize); + if (this.numberSized != size) { - this.numberSized = size; - this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath()); + this.numberSized = size; + this.pathSized = AffineTransform.getScaleInstance(null, size, size).createTransformedShape(getPath()); } return this.pathSized; - } - - public Path2D getPathForPixelSize(float pixelSize) { - return getPath(getScaleForPixelSize(pixelSize)); - } - - public Path2D getNormalPath() { - return this.path; - } - + } } diff --git a/src/jogamp/graph/font/typecast/TypecastMetrics.java b/src/jogamp/graph/font/typecast/TypecastMetrics.java index 541ed90d8..9ca1e3bf7 100644 --- a/src/jogamp/graph/font/typecast/TypecastMetrics.java +++ b/src/jogamp/graph/font/typecast/TypecastMetrics.java @@ -37,51 +37,42 @@ class TypecastMetrics implements Metrics { private final TypecastFont fontImpl; // HeadTable + private final HeadTable headTable; private final float unitsPerEM_Inv; - private final float unitsPerEM_Inv_sized; - private final AABBox bbox_sized; - + private final AABBox bbox; // HheaTable - private final float ascend_sized; - private final float descent_sized; - private final float linegap_sized; + private final HheaTable hheaTable; public TypecastMetrics(TypecastFont fontImpl) { this.fontImpl = fontImpl; - final HeadTable headTable = this.fontImpl.font.getHeadTable(); - unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() ); - unitsPerEM_Inv_sized = this.fontImpl.size * unitsPerEM_Inv; - int maxWidth = headTable.getXMax() - headTable.getXMin(); - int maxHeight = headTable.getYMax() - headTable.getYMin(); - float lowx= headTable.getXMin(); - float lowy = -(headTable.getYMin()+maxHeight); - float highx = lowx + maxWidth; - float highy = lowy + maxHeight; - bbox_sized = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert - bbox_sized.scale(unitsPerEM_Inv_sized); - - final HheaTable hheaTable = this.fontImpl.font.getHheaTable(); - ascend_sized = unitsPerEM_Inv_sized * -hheaTable.getAscender(); // invert - descent_sized = unitsPerEM_Inv_sized * -hheaTable.getDescender(); // invert - linegap_sized = unitsPerEM_Inv_sized * -hheaTable.getLineGap(); // invert + headTable = this.fontImpl.font.getHeadTable(); + hheaTable = this.fontImpl.font.getHheaTable(); + unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() ); + + int maxWidth = headTable.getXMax() - headTable.getXMin(); + int maxHeight = headTable.getYMax() - headTable.getYMin(); + float lowx= headTable.getXMin(); + float lowy = -(headTable.getYMin()+maxHeight); + float highx = lowx + maxWidth; + float highy = lowy + maxHeight; + bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert } - - public final float getAscent() { - return ascend_sized; + + public final float getAscent(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getAscender(); // invert } - public final float getDescent() { - return descent_sized; + public final float getDescent(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getDescender(); // invert } - public final float getLineGap() { - return linegap_sized; + public final float getLineGap(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getLineGap(); // invert } - public final float getScale() { - return unitsPerEM_Inv_sized; - } - public float getScaleForPixelSize(float pixelSize) { - return pixelSize * unitsPerEM_Inv; - } - public final AABBox getBBox() { - return bbox_sized; + public final float getScale(float pixelSize) { + return pixelSize * unitsPerEM_Inv; + } + public final AABBox getBBox(float pixelSize) { + AABBox res = new AABBox(bbox.getLow(), bbox.getHigh()); + res.scale(getScale(pixelSize)); + return res; } } \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java index 74e5cd604..11f1ec028 100644 --- a/src/jogamp/graph/font/typecast/TypecastRenderer.java +++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java @@ -44,16 +44,16 @@ import net.java.dev.typecast.ot.OTGlyph; public class TypecastRenderer { public static void getOutline(Factory factory, TypecastFont font, - String string, AffineTransform transform, Path2D[] p) + String string, float pixelSize, AffineTransform transform, Path2D[] p) { if (string == null) { return; } Font.Metrics metrics = font.getMetrics(); float advanceTotal = 0; - float lineGap = metrics.getLineGap() ; - float ascent = metrics.getAscent() ; - float descent = metrics.getDescent() ; + float lineGap = metrics.getLineGap(pixelSize) ; + float ascent = metrics.getAscent(pixelSize) ; + float descent = metrics.getDescent(pixelSize) ; if (transform == null) { transform = new AffineTransform(factory); } @@ -73,12 +73,12 @@ public class TypecastRenderer { continue; } TypecastGlyph glyph = (TypecastGlyph) font.getGlyph(character); - Path2D gp = glyph.getNormalPath(); - float scale = metrics.getScale(); + Path2D gp = glyph.getPath(); + float scale = metrics.getScale(pixelSize); t.translate(advanceTotal, y); t.scale(scale, scale); p[i].append(gp.iterator(t), false); - advanceTotal += glyph.getAdvanceForPixelSize(font.getSize(), true); + advanceTotal += glyph.getAdvance(pixelSize, true); } } diff --git a/src/net/java/dev/typecast/ot/table/HdmxTable.java b/src/net/java/dev/typecast/ot/table/HdmxTable.java index e47c0a316..68a03c590 100644 --- a/src/net/java/dev/typecast/ot/table/HdmxTable.java +++ b/src/net/java/dev/typecast/ot/table/HdmxTable.java @@ -57,6 +57,11 @@ public class HdmxTable implements Table { public short[] getWidths() { return _widths; } + + public short getWidth(int glyphidx) { + return _widths[glyphidx]; + } + } private DirectoryEntry _de; @@ -80,6 +85,14 @@ public class HdmxTable implements Table { } } + public int getNumberOfRecords() { + return _numRecords; + } + + public DeviceRecord getRecord(int i) { + return _records[i]; + } + public int getType() { return hdmx; } -- cgit v1.2.3 From 915639b05db5ed7cd0ac5b32e10b194d0f54172d Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Sun, 27 Mar 2011 13:14:50 +0300 Subject: Demo refactor variable names --- src/demo/GPUTextGLListenerBase01.java | 20 ++++++++++---------- src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 8d4232ef9..96a06085e 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -45,7 +45,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { HwTextRenderer textRenderer; KeyAction keyAction; - boolean fontUpdate = true; + boolean updateFont = true; int fontSize = 40; final int fontSizeModulo = 100; Font font; @@ -59,7 +59,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { // float zoom = -1000f; int texSize = 400; // FBO/tex size .. - boolean doMatrix = true; + boolean updateMatrix = true; boolean debug; boolean trace; static final String text1; @@ -112,16 +112,16 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - if(doMatrix) { + if(updateMatrix) { textRenderer.resetMatrix(gl); textRenderer.translate(gl, xTran, yTran, zoom); textRenderer.rotate(gl, ang, 0, 1, 0); - doMatrix = false; + updateMatrix = false; } - if(fontUpdate) { + if(updateFont) { font = textRenderer.createFont(vfactory, "Lucida Sans Regular", fontSize); - fontUpdate = false; + updateFont = false; } textRenderer.renderString3D(gl, font, text2, position, texSize); } @@ -133,26 +133,26 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { public void fontIncr(int v) { fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; - fontUpdate = true; + updateFont = true; dumpMatrix(); } public void zoom(int v){ zoom += v; - doMatrix = true; + updateMatrix = true; dumpMatrix(); } public void move(float x, float y){ xTran += x; yTran += y; - doMatrix = true; + updateMatrix = true; dumpMatrix(); } public void rotate(float delta){ ang += delta; ang %= 360.0f; - doMatrix = true; + updateMatrix = true; dumpMatrix(); } diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java index 0330accbe..baca05dc7 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -296,7 +296,7 @@ public class VBORegion2PGL3 implements Region{ int status = gl.glCheckFramebufferStatus(GL3.GL_FRAMEBUFFER); if(status != GL3.GL_FRAMEBUFFER_COMPLETE){ - System.out.println("FRAAAAAAAAAAAAAAME"); + System.err.println("Cant Create R2T pass!"); } //render texture -- cgit v1.2.3 From b3d8f3548b608603b3c7fd1a03c1ebbffb95cb8b Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Sun, 27 Mar 2011 13:19:06 +0300 Subject: MSAATool Split dump to CSAA and MSAA --- src/demo/MSAATool.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/demo/MSAATool.java b/src/demo/MSAATool.java index a31005f08..e357a3239 100644 --- a/src/demo/MSAATool.java +++ b/src/demo/MSAATool.java @@ -46,6 +46,15 @@ public class MSAATool { // default TRUE System.out.println(" GL MULTISAMPLE "+gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); + // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB + gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0); + // samples min 0 + gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1); + System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); + + System.out.println("GL CSAA SETUP:"); + // default FALSE + System.out.println(" GL SAMPLE COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE)); // default FALSE System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE)); // default FALSE @@ -56,10 +65,5 @@ public class MSAATool { System.out.println(" GL SAMPLE_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE) + ": SAMPLE_COVERAGE_VALUE "+vf[0]+ ", SAMPLE_COVERAGE_INVERT "+vb[0]); - // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB - gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0); - // samples min 0 - gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1); - System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); } } -- cgit v1.2.3 From 23646bedac2fe9ff27e35ac167e6872afb84fc50 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Mon, 28 Mar 2011 10:08:12 +0300 Subject: Fix: remove TTF imports --- src/jogamp/graph/font/typecast/TypecastFont.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index 1ac57c100..b95dccf21 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -32,8 +32,6 @@ import java.io.IOException; import jogamp.graph.font.FontInt; import jogamp.graph.font.JavaFontLoader; -import jogamp.graph.font.ttf.TTFontGlyph; -import jogamp.graph.font.ttf.TTFont.Metrics; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; import net.java.dev.typecast.ot.OTFont; -- cgit v1.2.3 From 3bf42d92a3baf5e506f553fc20c71c082c39790e Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Mon, 28 Mar 2011 11:49:57 +0300 Subject: Added print screen to TGA file to be used in junit --- src/demo/GPUTextGLListenerBase01.java | 14 ++++++++++++-- src/demo/GPUTextNewtDemo01.java | 22 ++++++++++++++++++++-- src/demo/GPUTextNewtDemo02.java | 20 +++++++++++++++++++- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index b310f1069..7dffbd7d1 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -27,10 +27,14 @@ */ package demo; +import java.io.File; +import java.io.IOException; + import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; import com.jogamp.graph.curve.text.HwTextRenderer; @@ -39,6 +43,7 @@ import com.jogamp.graph.geom.Vertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.awt.Screenshot; public abstract class GPUTextGLListenerBase01 implements GLEventListener { Vertex.Factory vfactory; @@ -106,7 +111,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { dumpMatrix(true); } - + boolean printScreen = true; public void display(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -175,6 +180,11 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { window.removeKeyListener(keyAction); } + public void printScreen(GLWindow window, String dir, String tech, boolean exportAlpha) throws GLException, IOException{ + String filename = dir + tech + "-" + window.getWidth()+ "x" + window.getHeight() + "-" + texSize+ ".tga"; + Screenshot.writeToTargaFile(new File(filename), window.getWidth(), window.getHeight(), exportAlpha); + } + public class KeyAction implements KeyListener { public void keyPressed(KeyEvent arg0) { if(arg0.getKeyCode() == KeyEvent.VK_1){ @@ -214,7 +224,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { } else if(arg0.getKeyCode() == KeyEvent.VK_9){ rotate(-1); - } + } } public void keyTyped(KeyEvent arg0) {} public void keyReleased(KeyEvent arg0) {} diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index ad1020122..76593278f 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -27,9 +27,12 @@ */ package demo; +import java.io.IOException; + import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; @@ -47,7 +50,7 @@ public class GPUTextNewtDemo01 { } TextGLListener textGLListener = null; - + GLWindow window; public void testMe() { GLProfile.initSingleton(true); GLProfile glp = GLProfile.getGL2ES2(); @@ -57,7 +60,7 @@ public class GPUTextNewtDemo01 { caps.setNumSamples(4); // 2 samples is not enough .. System.out.println("Requested: "+caps); - final GLWindow window = GLWindow.create(caps); + window = GLWindow.create(caps); window.setPosition(10, 10); window.setSize(500, 500); @@ -95,5 +98,20 @@ public class GPUTextNewtDemo01 { //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); } + + public void display(GLAutoDrawable drawable) { + super.display(drawable); + + if(printScreen){ + try { + super.printScreen(window, "./","r2t0-msaa1", false); + printScreen=false; + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } } diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 1fbd253c9..4174da30b 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -27,10 +27,13 @@ */ package demo; +import java.io.IOException; + import javax.media.opengl.GL; import javax.media.opengl.GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; @@ -53,6 +56,7 @@ public class GPUTextNewtDemo02 { public static void main(String[] args) { GPUTextNewtDemo02 test = new GPUTextNewtDemo02(); test.testMe(); + } GLWindow window; @@ -85,7 +89,7 @@ public class GPUTextNewtDemo02 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-10, 10, 0f, -1000, 190); + setMatrix(-10, 10, 0f, -1000, 400); } public void init(GLAutoDrawable drawable) { @@ -102,5 +106,19 @@ public class GPUTextNewtDemo02 { //gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); MSAATool.dump(drawable); } + public void display(GLAutoDrawable drawable) { + super.display(drawable); + + if(printScreen){ + try { + super.printScreen(window, "./","r2t1-msaa0", false); + printScreen=false; + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } } } -- cgit v1.2.3 From 8b288c20da315b24ac65d14475d3133e45007981 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Mon, 28 Mar 2011 14:19:38 +0300 Subject: Testcase for R2T with two sizes --- src/demo/GPUTextGLListenerBase01.java | 7 +- src/demo/GPUTextNewtDemo02.java | 14 -- .../test/junit/graph/TestHwTextRenderer01.java | 153 +++++++++++++++++++++ 3 files changed, 157 insertions(+), 17 deletions(-) create mode 100755 src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 7dffbd7d1..077c32978 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -47,7 +47,7 @@ import com.jogamp.opengl.util.awt.Screenshot; public abstract class GPUTextGLListenerBase01 implements GLEventListener { Vertex.Factory vfactory; - HwTextRenderer textRenderer; + protected HwTextRenderer textRenderer; Font font; boolean debug; boolean trace; @@ -88,7 +88,8 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { this.yTran = ytrans; this.ang = angle; this.zoom = zoom; - this.texSize = fbosize; + this.texSize = fbosize; + doMatrix = true; } public void init(GLAutoDrawable drawable) { @@ -111,7 +112,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { dumpMatrix(true); } - boolean printScreen = true; + protected boolean printScreen = true; public void display(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 4174da30b..bda7fe0e2 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -106,19 +106,5 @@ public class GPUTextNewtDemo02 { //gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); MSAATool.dump(drawable); } - public void display(GLAutoDrawable drawable) { - super.display(drawable); - - if(printScreen){ - try { - super.printScreen(window, "./","r2t1-msaa0", false); - printScreen=false; - } catch (GLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java new file mode 100755 index 000000000..9af39a3f3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java @@ -0,0 +1,153 @@ +package test.com.jogamp.opengl.test.junit.graph; + +import java.io.IOException; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GL; +import javax.media.opengl.GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.FPSAnimator; + +import demo.GPUTextGLListenerBase01; + +public class TestHwTextRenderer01 { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(true); + NativeWindowFactory.initSingleton(true); + } + + static void destroyWindow(Window window) { + if(null!=window) { + window.destroy(); + } + } + + static GLWindow createWindow(String title, GLCapabilities caps, int width, int height, boolean onscreen) { + Assert.assertNotNull(caps); + caps.setOnscreen(onscreen); + + GLWindow window = GLWindow.create(caps); + window.setSize(width, height); + window.setPosition(10, 10); + window.setTitle(title); + Assert.assertNotNull(window); + window.setVisible(true); + //window.setAutoSwapBufferMode(false); + + return window; + } + + @Test + public void testTextRendererR2T01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL3bc); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + + GLWindow window = createWindow("r2t1msaa0", caps, 400,400,true); + TextR2TGLListener textGLListener = new TextR2TGLListener(Region.TWO_PASS); + textGLListener.setTech(-10, 10, 0f, -1000, 400); + textGLListener.attachTo(window); + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + animator.start(); + + window.getAnimator().resume(); + + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } + animator.stop(); + destroyWindow(window); + + Thread.sleep(1000); + } + + @Test + public void testTextRendererR2T02() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL3bc); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + + GLWindow window = createWindow("r2t1msaa0", caps, 400,400,true); + TextR2TGLListener textGLListener = new TextR2TGLListener(Region.TWO_PASS); + textGLListener.setTech(-111, 74, 0, -380, 900); + textGLListener.attachTo(window); + + while(!window.isRealized()){ + + } + + FPSAnimator animator = new FPSAnimator(60); + animator.add(window); + animator.start(); + + window.getAnimator().resume(); + + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } + animator.stop(); + destroyWindow(window); + } + + + private class TextR2TGLListener extends GPUTextGLListenerBase01 { + GLWindow glwindow; + public TextR2TGLListener(int type) { + super(SVertex.factory(), type, false, false); + } + + public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ + setMatrix(xt, yt, angle, zoom, fboSize); + } + + public void init(GLAutoDrawable drawable) { + GL3 gl = drawable.getGL().getGL3(); + super.init(drawable); + gl.setSwapInterval(1); + gl.glEnable(GL3.GL_DEPTH_TEST); + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + gl.glDisable(GL.GL_MULTISAMPLE); + } + public void attachTo(GLWindow window) { + super.attachTo(window); + glwindow = window; + } + + public boolean isPrinted(){ + return !printScreen; + } + + public void display(GLAutoDrawable drawable) { + super.display(drawable); + + try { + if(printScreen){ + printScreen(glwindow, "./", "r2t1msaa0", false); + printScreen = false; + } + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} -- cgit v1.2.3 From b73de5a53e2e81e2acc5f8f5064e2b0b27a9804e Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Mon, 28 Mar 2011 16:46:59 +0300 Subject: Multiple snapshots r2t; Added test initial MSAA --- src/demo/GPUTextGLListenerBase01.java | 3 +- src/demo/GPUTextNewtDemo01.java | 17 ----- .../test/junit/graph/TestHwTextRenderer01.java | 74 +++++++++++++--------- 3 files changed, 44 insertions(+), 50 deletions(-) diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 077c32978..70ddddd0d 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -63,8 +63,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { float yTran = 10; float ang = 0f; float zoom = -70f; - // float zoom = -1000f; - int texSize = 400; // FBO/tex size .. + int texSize = 400; boolean doMatrix = true; static final String text1; diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 76593278f..362627e56 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -27,12 +27,10 @@ */ package demo; -import java.io.IOException; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; @@ -98,20 +96,5 @@ public class GPUTextNewtDemo01 { //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); } - - public void display(GLAutoDrawable drawable) { - super.display(drawable); - - if(printScreen){ - try { - super.printScreen(window, "./","r2t0-msaa1", false); - printScreen=false; - } catch (GLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java index 9af39a3f3..0d48206f9 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java @@ -4,7 +4,7 @@ import java.io.IOException; import javax.media.nativewindow.NativeWindowFactory; import javax.media.opengl.GL; -import javax.media.opengl.GL3; +import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLException; @@ -36,9 +36,8 @@ public class TestHwTextRenderer01 { } } - static GLWindow createWindow(String title, GLCapabilities caps, int width, int height, boolean onscreen) { + static GLWindow createWindow(String title, GLCapabilities caps, int width, int height) { Assert.assertNotNull(caps); - caps.setOnscreen(onscreen); GLWindow window = GLWindow.create(caps); window.setSize(width, height); @@ -46,7 +45,6 @@ public class TestHwTextRenderer01 { window.setTitle(title); Assert.assertNotNull(window); window.setVisible(true); - //window.setAutoSwapBufferMode(false); return window; } @@ -57,58 +55,69 @@ public class TestHwTextRenderer01 { GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); - GLWindow window = createWindow("r2t1msaa0", caps, 400,400,true); - TextR2TGLListener textGLListener = new TextR2TGLListener(Region.TWO_PASS); + GLWindow window = createWindow("r2t1msaa0", caps, 400,400); + TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); textGLListener.setTech(-10, 10, 0f, -1000, 400); textGLListener.attachTo(window); - FPSAnimator animator = new FPSAnimator(60); + FPSAnimator animator = new FPSAnimator(10); animator.add(window); animator.start(); - window.getAnimator().resume(); + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } + textGLListener.resetPrinting(); + textGLListener.setTech(-111, 74, 0, -380, 900); + Thread.sleep(100); while(!textGLListener.isPrinted()){ Thread.sleep(100); } + animator.stop(); destroyWindow(window); Thread.sleep(1000); } - @Test - public void testTextRendererR2T02() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL3bc); + //@Test + public void testTextRendererMSAA01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); + //caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); - GLWindow window = createWindow("r2t1msaa0", caps, 400,400,true); - TextR2TGLListener textGLListener = new TextR2TGLListener(Region.TWO_PASS); - textGLListener.setTech(-111, 74, 0, -380, 900); + GLWindow window = createWindow("r2t0msaa1", caps, 400,0); + TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); + textGLListener.setTech(-10, 10, 0f, -1000, 0); textGLListener.attachTo(window); - - while(!window.isRealized()){ - - } - FPSAnimator animator = new FPSAnimator(60); + FPSAnimator animator = new FPSAnimator(10); animator.add(window); animator.start(); - window.getAnimator().resume(); - while(!textGLListener.isPrinted()){ Thread.sleep(100); } + + //textGLListener.resetPrinting(); + //textGLListener.setTech(-111, 74, 0, -380, 0); + //Thread.sleep(100); + //while(!textGLListener.isPrinted()){ + // Thread.sleep(100); + //} + animator.stop(); - destroyWindow(window); + destroyWindow(window); + + Thread.sleep(1000); } - - - private class TextR2TGLListener extends GPUTextGLListenerBase01 { + + private class TextGLListener extends GPUTextGLListenerBase01 { GLWindow glwindow; - public TextR2TGLListener(int type) { + public TextGLListener(int type) { super(SVertex.factory(), type, false, false); } @@ -117,14 +126,13 @@ public class TestHwTextRenderer01 { } public void init(GLAutoDrawable drawable) { - GL3 gl = drawable.getGL().getGL3(); + GL2ES2 gl = drawable.getGL().getGL2ES2(); super.init(drawable); gl.setSwapInterval(1); - gl.glEnable(GL3.GL_DEPTH_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); textRenderer.init(gl); textRenderer.setAlpha(gl, 1.0f); textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - gl.glDisable(GL.GL_MULTISAMPLE); } public void attachTo(GLWindow window) { super.attachTo(window); @@ -134,13 +142,17 @@ public class TestHwTextRenderer01 { public boolean isPrinted(){ return !printScreen; } + + public void resetPrinting(){ + printScreen = true; + } public void display(GLAutoDrawable drawable) { super.display(drawable); try { if(printScreen){ - printScreen(glwindow, "./", "r2t1msaa0", false); + printScreen(glwindow, "./", glwindow.getTitle(), false); printScreen = false; } } catch (GLException e) { -- cgit v1.2.3 From c0eb49806a35c0618af8a61c99ba783d688fc09d Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Tue, 29 Mar 2011 00:55:33 +0300 Subject: Add debug flag for boundary tri --- src/com/jogamp/graph/curve/tess/CDTriangulator2D.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index 00c97d463..2a1b52b1c 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -177,7 +177,9 @@ public class CDTriangulator2D { } t.setId(maxTriID++); triangles.add(t); - + if(DEBUG){ + System.err.println(t); + } if(hole || holeLike) { v0.setTexCoord(0, -0.1f); v2.setTexCoord(1, -0.1f); -- cgit v1.2.3 From 2f094d97a1cbdf14c25a7ebc1b183e20bdd6c4cd Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Tue, 29 Mar 2011 13:26:01 +0300 Subject: Updated textTextRenderer 3 views each and write to tga file --- src/demo/GPUTextGLListenerBase01.java | 5 ++-- src/demo/GPUTextNewtDemo01.java | 1 - .../test/junit/graph/TestHwTextRenderer01.java | 34 +++++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index f894f4142..1b2dd7e17 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -71,7 +71,8 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { static final String text2; static { - text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + //text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; + text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n#$!%-+="; text2 = text1.toUpperCase(); } @@ -183,7 +184,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { } public void printScreen(GLWindow window, String dir, String tech, boolean exportAlpha) throws GLException, IOException{ - String filename = dir + tech + "-" + window.getWidth()+ "x" + window.getHeight() + "-" + texSize+ ".tga"; + String filename = dir + tech + "-" + window.getWidth()+ "x" + window.getHeight() + "-T" + texSize + "-Z" + Math.abs(zoom) +".tga"; Screenshot.writeToTargaFile(new File(filename), window.getWidth(), window.getHeight(), exportAlpha); } diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 362627e56..7bad55aa5 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -69,7 +69,6 @@ public class GPUTextNewtDemo01 { window.setVisible(true); FPSAnimator animator = new FPSAnimator(10); - // Animator animator = new Animator(); animator.add(window); animator.start(); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java index 0d48206f9..a0b04d69a 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java @@ -69,7 +69,14 @@ public class TestHwTextRenderer01 { } textGLListener.resetPrinting(); - textGLListener.setTech(-111, 74, 0, -380, 900); + textGLListener.setTech(-111, 74, 0, -380, 1100); + Thread.sleep(100); + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } + + textGLListener.resetPrinting(); + textGLListener.setTech(-111, 74, 0, -80, 2500); Thread.sleep(100); while(!textGLListener.isPrinted()){ Thread.sleep(100); @@ -81,15 +88,15 @@ public class TestHwTextRenderer01 { Thread.sleep(1000); } - //@Test + @Test public void testTextRendererMSAA01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL2ES2); GLCapabilities caps = new GLCapabilities(glp); - //caps.setAlphaBits(4); + caps.setAlphaBits(4); caps.setSampleBuffers(true); caps.setNumSamples(4); - GLWindow window = createWindow("r2t0msaa1", caps, 400,0); + GLWindow window = createWindow("r2t0msaa1", caps, 400, 400); TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); textGLListener.setTech(-10, 10, 0f, -1000, 0); textGLListener.attachTo(window); @@ -102,12 +109,19 @@ public class TestHwTextRenderer01 { Thread.sleep(100); } - //textGLListener.resetPrinting(); - //textGLListener.setTech(-111, 74, 0, -380, 0); - //Thread.sleep(100); - //while(!textGLListener.isPrinted()){ - // Thread.sleep(100); - //} + textGLListener.resetPrinting(); + textGLListener.setTech(-111, 74, 0, -380, 0); + Thread.sleep(100); + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } + + textGLListener.resetPrinting(); + textGLListener.setTech(-111, 74, 0, -80, 0); + Thread.sleep(100); + while(!textGLListener.isPrinted()){ + Thread.sleep(100); + } animator.stop(); destroyWindow(window); -- cgit v1.2.3 From 2a3a260aece0060f5aa03d83a177d3f373664324 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 29 Mar 2011 13:09:32 +0200 Subject: Same size for both tests diff technique --- src/demo/GPUTextNewtDemo01.java | 5 +++-- src/demo/GPUTextNewtDemo02.java | 5 +---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 7bad55aa5..a07ead417 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -61,7 +61,7 @@ public class GPUTextNewtDemo01 { window = GLWindow.create(caps); window.setPosition(10, 10); - window.setSize(500, 500); + window.setSize(400, 400); window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); textGLListener = new TextGLListener(); @@ -76,7 +76,8 @@ public class GPUTextNewtDemo01 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); - setMatrix(-10, 10, 0f, -70, 0); + //setMatrix(-10, 10, 0f, -70, 0); + setMatrix(-10, 10, 0f, -100, 400); } public void init(GLAutoDrawable drawable) { diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index bda7fe0e2..012ee9936 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -27,13 +27,10 @@ */ package demo; -import java.io.IOException; - import javax.media.opengl.GL; import javax.media.opengl.GL3; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; @@ -89,7 +86,7 @@ public class GPUTextNewtDemo02 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-10, 10, 0f, -1000, 400); + setMatrix(-10, 10, 0f, -100, 400); } public void init(GLAutoDrawable drawable) { -- cgit v1.2.3 From 4ed4dc3847d8d53a3424011f3d56b00ef246a81e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 29 Mar 2011 14:29:50 +0200 Subject: Refactor / Use font name as file path, if not a java font --- src/com/jogamp/graph/curve/HwTextRenderer.java | 372 ++++++++++++++++++++ .../jogamp/graph/curve/text/HwTextRenderer.java | 373 --------------------- src/demo/GPUTextGLListenerBase01.java | 2 +- src/jogamp/graph/font/typecast/TypecastFont.java | 3 + 4 files changed, 376 insertions(+), 374 deletions(-) create mode 100644 src/com/jogamp/graph/curve/HwTextRenderer.java delete mode 100644 src/com/jogamp/graph/curve/text/HwTextRenderer.java diff --git a/src/com/jogamp/graph/curve/HwTextRenderer.java b/src/com/jogamp/graph/curve/HwTextRenderer.java new file mode 100644 index 000000000..c5f11d522 --- /dev/null +++ b/src/com/jogamp/graph/curve/HwTextRenderer.java @@ -0,0 +1,372 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve; + +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.graph.curve.text.GlyphString; +import jogamp.graph.font.FontInt; +import jogamp.graph.font.typecast.TypecastFontFactory; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + +import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class HwTextRenderer { + protected static final boolean DEBUG = Debug.debug("TextRenderer"); + static final boolean FONTTOOL_CUSTOM = false; + + private static FontFactory fontFactory; + + static { + FontFactory _fontFactory = null; + + if(FONTTOOL_CUSTOM) { + _fontFactory = (FontFactory) ReflectionUtil.createInstance("jogamp.graph.font.ttf.TTFFontFactory", HwTextRenderer.class.getClassLoader()); + if(null!=_fontFactory) { + System.err.println("Using custom font tool"); + } + } + if(null==_fontFactory) { + _fontFactory = new TypecastFontFactory(); + } + fontFactory = _fontFactory; + } + + + public static FontFactory getFontFactory() { + return fontFactory; + } + + private ShaderState st = new ShaderState(); + + private PMVMatrix pmvMatrix = new PMVMatrix(); + private GLUniformData mgl_PMVMatrix; + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); + + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private HashMap strings = new HashMap(); + private final Vertex.Factory pointFactory; + + int win_width = 0; + int win_height = 0; + + /** + * Create a Hardware accelerated Text Renderer. + * @param context OpenGL rendering context + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public HwTextRenderer(Vertex.Factory factory, int type) { + this.pointFactory = (null != factory) ? factory : SVertex.factory(); + this.regionType = type; + } + + public Font createFont(Vertex.Factory factory, String name) { + return fontFactory.createFont(factory, name); + } + + + public Font createFont(Vertex.Factory factory, + String[] families, + String style, + String variant, + String weight) { + return fontFactory.createFont(factory, families, style, variant, weight); + } + + /** + * Initialize shaders and bindings for GPU based text Rendering, + * should be called only once. + * Leaves the renderer enables, ie ShaderState on. + * + * @param drawable the current drawable + * @param shapvalue shaprness around the off-curve vertices + * @return true if init succeeded, false otherwise + */ + public boolean init(GL2ES2 gl){ + if(initialized){ + if(DEBUG) { + System.err.println("HWTextRenderer: Already initialized!"); + } + return true; + } + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, + "../shader", "../shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWTextRenderer: Couldn't link program: "+sp); + } + + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_sharpness)) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_alpha)) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_color)) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_strength)) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + if(DEBUG) { + System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public void dispose(GL2ES2 gl) { + st.destroy(gl); + clearCached(); + } + + public float getAlpha() { + return mgl_alpha.floatValue(); + } + + public ShaderState getShaderState() { + return st; + } + + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } + } + + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + public void translate(GL2ES2 gl, float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void resetMatrix(GL2ES2 gl){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void updateAllShaderValues(GL2ES2 gl) { + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + st.glUniform(gl, mgl_alpha); + st.glUniform(gl, mgl_color); + st.glUniform(gl, mgl_strength); + } + } + + /** + * @param gl + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshape(GL2ES2 gl, float angle, int width, int height, float near, float far){ + win_width = width; + win_height = height; + float ratio = (float)width/(float)height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + st.glUniform(gl, mgl_PMVMatrix); + + return true; + } + + private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { + AffineTransform affineTransform = new AffineTransform(pointFactory); + + Path2D[] paths = new Path2D[str.length()]; + ((FontInt)font).getOutline(str, size, affineTransform, paths); + + GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); + glyphString.createfromFontPath(paths, affineTransform); + + glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); + return glyphString; + } + + + public void enable(GL2ES2 gl, boolean enable) { + if(null != gl) { + st.glUseProgram(gl, enable); + } + } + + /** Render the String in 3D space wrt to the font provided at the position provided + * the outlines will be generated, if not yet generated + * @param font font to be used + * @param str text to be rendered + * @param position the lower left corner of the string + * @param fontSize font size + * @param texSize texture size for multipass render + * @throws Exception if TextRenderer not initialized + */ + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { + if(!initialized){ + throw new GLException("HWTextRenderer: not initialized!"); + } + String fontStrHash = getTextHashCode(font, str, fontSize); + GlyphString glyphString = strings.get(fontStrHash); + if(null == glyphString) { + glyphString = createString(gl, font, fontSize, str); + strings.put(fontStrHash, glyphString); + } + + glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); + } + + private String getTextHashCode(Font font, String str, int fontSize) { + // FIXME: use integer hash code + return font.getName() + "." + str.hashCode() + "." + fontSize; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void clearCached() { + Iterator iterator = strings.values().iterator(); + while(iterator.hasNext()){ + GlyphString glyphString = iterator.next(); + glyphString.destroy(); + } + strings.clear(); + } +} diff --git a/src/com/jogamp/graph/curve/text/HwTextRenderer.java b/src/com/jogamp/graph/curve/text/HwTextRenderer.java deleted file mode 100644 index f30f42cc5..000000000 --- a/src/com/jogamp/graph/curve/text/HwTextRenderer.java +++ /dev/null @@ -1,373 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve.text; - -import java.nio.FloatBuffer; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import jogamp.graph.curve.text.GlyphString; -import jogamp.graph.font.FontInt; -import jogamp.graph.font.typecast.TypecastFontFactory; -import jogamp.graph.geom.plane.AffineTransform; -import jogamp.graph.geom.plane.Path2D; - -import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.opengl.SVertex; -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class HwTextRenderer { - protected static final boolean DEBUG = Debug.debug("TextRenderer"); - static final boolean FONTTOOL_CUSTOM = false; - - private static FontFactory fontFactory; - - static { - FontFactory _fontFactory = null; - - if(FONTTOOL_CUSTOM) { - _fontFactory = (FontFactory) ReflectionUtil.createInstance("jogamp.graph.font.ttf.TTFFontFactory", HwTextRenderer.class.getClassLoader()); - if(null!=_fontFactory) { - System.err.println("Using custom font tool"); - } - } - if(null==_fontFactory) { - _fontFactory = new TypecastFontFactory(); - } - fontFactory = _fontFactory; - } - - - public static FontFactory getFontFactory() { - return fontFactory; - } - - private ShaderState st = new ShaderState(); - - private PMVMatrix pmvMatrix = new PMVMatrix(); - private GLUniformData mgl_PMVMatrix; - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); - private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); - private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); - private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); - - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private HashMap strings = new HashMap(); - private final Vertex.Factory pointFactory; - - int win_width = 0; - int win_height = 0; - - /** - * Create a Hardware accelerated Text Renderer. - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public HwTextRenderer(Vertex.Factory factory, int type) { - this.pointFactory = (null != factory) ? factory : SVertex.factory(); - this.regionType = type; - } - - public Font createFont(Vertex.Factory factory, String name) { - return fontFactory.createFont(factory, name); - } - - - public Font createFont(Vertex.Factory factory, - String[] families, - String style, - String variant, - String weight) { - return fontFactory.createFont(factory, families, style, variant, weight); - } - - /** - * Initialize shaders and bindings for GPU based text Rendering, - * should be called only once. - * Leaves the renderer enables, ie ShaderState on. - * - * @param drawable the current drawable - * @param shapvalue shaprness around the off-curve vertices - * @return true if init succeeded, false otherwise - */ - public boolean init(GL2ES2 gl){ - if(initialized){ - if(DEBUG) { - System.err.println("HWTextRenderer: Already initialized!"); - } - return true; - } - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWTextRenderer: Couldn't link program: "+sp); - } - - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(null); - - mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.glUniform(gl, mgl_PMVMatrix)) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_sharpness)) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_alpha)) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_color)) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_strength)) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - if(DEBUG) { - System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public void dispose(GL2ES2 gl) { - st.destroy(gl); - clearCached(); - } - - public float getAlpha() { - return mgl_alpha.floatValue(); - } - - public ShaderState getShaderState() { - return st; - } - - public void setAlpha(GL2ES2 gl, float alpha_t) { - mgl_alpha.setData(alpha_t); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_alpha); - } - } - - public void setColor(GL2ES2 gl, float r, float g, float b){ - FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); - fb.put(0, r); - fb.put(1, r); - fb.put(2, r); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_color); - } - } - - public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - public void translate(GL2ES2 gl, float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void resetMatrix(GL2ES2 gl){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void updateAllShaderValues(GL2ES2 gl) { - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - st.glUniform(gl, mgl_alpha); - st.glUniform(gl, mgl_color); - st.glUniform(gl, mgl_strength); - } - } - - /** - * @param gl - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshape(GL2ES2 gl, float angle, int width, int height, float near, float far){ - win_width = width; - win_height = height; - float ratio = (float)width/(float)height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - st.glUniform(gl, mgl_PMVMatrix); - - return true; - } - - private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { - AffineTransform affineTransform = new AffineTransform(pointFactory); - - Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getOutline(str, size, affineTransform, paths); - - GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); - glyphString.createfromFontPath(paths, affineTransform); - - glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); - return glyphString; - } - - - public void enable(GL2ES2 gl, boolean enable) { - if(null != gl) { - st.glUseProgram(gl, enable); - } - } - - /** Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated - * @param font font to be used - * @param str text to be rendered - * @param position the lower left corner of the string - * @param fontSize font size - * @param texSize texture size for multipass render - * @throws Exception if TextRenderer not initialized - */ - public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { - if(!initialized){ - throw new GLException("HWTextRenderer: not initialized!"); - } - String fontStrHash = getTextHashCode(font, str, fontSize); - GlyphString glyphString = strings.get(fontStrHash); - if(null == glyphString) { - glyphString = createString(gl, font, fontSize, str); - strings.put(fontStrHash, glyphString); - } - - glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); - } - - private String getTextHashCode(Font font, String str, int fontSize) { - // FIXME: use integer hash code - return font.getName() + "." + str.hashCode() + "." + fontSize; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void clearCached() { - Iterator iterator = strings.values().iterator(); - while(iterator.hasNext()){ - GlyphString glyphString = iterator.next(); - glyphString.destroy(); - } - strings.clear(); - } -} diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 1b2dd7e17..4e3a57fd9 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -37,7 +37,7 @@ import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; -import com.jogamp.graph.curve.text.HwTextRenderer; +import com.jogamp.graph.curve.HwTextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.Vertex; import com.jogamp.newt.event.KeyEvent; diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index b95dccf21..c5e291a55 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -59,6 +59,9 @@ class TypecastFont implements FontInt { public static TypecastFont create(Vertex.Factory factory, String name) { String path = JavaFontLoader.getByName(name); + if(null == path) { + path = name; + } OTFontCollection fontset; try { fontset = OTFontCollection.create(new File(path)); -- cgit v1.2.3 From 5f0293b84d0146d9e750ea7e75caaa101ae3b3c3 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Tue, 29 Mar 2011 15:05:49 +0200 Subject: Refactoring for public: Remove Line ; public/private API cleanup --- src/com/jogamp/graph/curve/OutlineShape.java | 28 +- .../jogamp/graph/curve/tess/CDTriangulator2D.java | 7 +- src/com/jogamp/graph/geom/AABBox.java | 12 +- src/com/jogamp/graph/geom/Line.java | 61 ----- src/com/jogamp/graph/geom/Outline.java | 4 +- src/com/jogamp/graph/geom/opengl/SVertex.java | 4 +- src/com/jogamp/graph/math/VectorUtil.java | 295 +++++++++++++++++++++ src/jogamp/graph/curve/tess/Loop.java | 22 +- src/jogamp/graph/curve/text/GlyphShape.java | 10 +- src/jogamp/graph/math/VectorFloatUtil.java | 293 -------------------- 10 files changed, 323 insertions(+), 413 deletions(-) delete mode 100644 src/com/jogamp/graph/geom/Line.java create mode 100755 src/com/jogamp/graph/math/VectorUtil.java delete mode 100755 src/jogamp/graph/math/VectorFloatUtil.java diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index d7b941282..9373808f1 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -30,12 +30,10 @@ package com.jogamp.graph.curve; import java.util.ArrayList; import java.util.Collections; -import jogamp.graph.math.VectorFloatUtil; - import com.jogamp.graph.geom.Outline; -import com.jogamp.graph.geom.Line; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.math.VectorUtil; import com.jogamp.graph.curve.tess.CDTriangulator2D; @@ -153,7 +151,7 @@ public class OutlineShape { if(!(currentVertex.isOnCurve()) && !(nextVertex.isOnCurve())) { newOutline.addVertex(currentVertex); - float[] newCoords = VectorFloatUtil.mid(currentVertex.getCoord(), nextVertex.getCoord()); + float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), nextVertex.getCoord()); newOutline.addVertex(pointFactory, newCoords, 0, 3, true); } else { @@ -188,28 +186,6 @@ public class OutlineShape { } - /** Generates the lines the define the noncurved - * parts of this graph - * @return arraylist of lines - */ - public ArrayList> getLines(){ - ArrayList> lines = new ArrayList>(); - for(Outline outline:outlines){ - ArrayList outVertices = outline.getVertices(); - int size = outVertices.size(); - for(int i=0; i < size; i++) { - Vertex currentVertex = outVertices.get(i); - if(currentVertex.isOnCurve()) { - Vertex v2 = outVertices.get((i+1)%size); - if(v2.isOnCurve()){ - lines.add(new Line(currentVertex, v2)); - } - } - } - } - return lines; - } - /** Triangluate the graph object * @param sharpness sharpness of the curved regions default = 0.5 */ diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index 2a1b52b1c..0a7cf08d4 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -33,11 +33,12 @@ import java.util.ArrayList; import jogamp.graph.curve.tess.GraphOutline; import jogamp.graph.curve.tess.GraphVertex; import jogamp.graph.curve.tess.Loop; -import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.math.VectorUtil; + import jogamp.opengl.Debug; /** Constrained Delaunay Triangulation @@ -94,7 +95,7 @@ public class CDTriangulator2D { GraphOutline outline = new GraphOutline(polyline); GraphOutline innerPoly = extractBoundaryTriangles(outline, false); vertices.addAll(polyline.getVertices()); - loop = new Loop(innerPoly, VectorFloatUtil.CCW); + loop = new Loop(innerPoly, VectorUtil.CCW); loops.add(loop); } else { @@ -168,7 +169,7 @@ public class CDTriangulator2D { Triangle t= null; boolean holeLike = false; - if(VectorFloatUtil.ccw(v0,v1,v2)){ + if(VectorUtil.ccw(v0,v1,v2)){ t = new Triangle(v0, v1, v2); } else { diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java index 2e99daa83..a2566b91f 100644 --- a/src/com/jogamp/graph/geom/AABBox.java +++ b/src/com/jogamp/graph/geom/AABBox.java @@ -27,7 +27,7 @@ */ package com.jogamp.graph.geom; -import jogamp.graph.math.VectorFloatUtil; +import com.jogamp.graph.math.VectorUtil; /** * Axis Aligned Bounding Box. @@ -186,7 +186,7 @@ public class AABBox { public float getSize(){ - return VectorFloatUtil.computeLength(low, high); + return VectorUtil.computeLength(low, high); } public float[] getCenter() { @@ -211,17 +211,17 @@ public class AABBox { diffH[1] = high[1] - center[1]; diffH[2] = high[2] - center[2]; - diffH = VectorFloatUtil.scale(diffH, size); + diffH = VectorUtil.scale(diffH, size); float[] diffL = new float[3]; diffL[0] = low[0] - center[0]; diffL[1] = low[1] - center[1]; diffL[2] = low[2] - center[2]; - diffL = VectorFloatUtil.scale(diffL, size); + diffL = VectorUtil.scale(diffL, size); - high = VectorFloatUtil.vectorAdd(center, diffH); - low = VectorFloatUtil.vectorAdd(center, diffL); + high = VectorUtil.vectorAdd(center, diffH); + low = VectorUtil.vectorAdd(center, diffL); } public float getX() { diff --git a/src/com/jogamp/graph/geom/Line.java b/src/com/jogamp/graph/geom/Line.java deleted file mode 100644 index 92d1b007f..000000000 --- a/src/com/jogamp/graph/geom/Line.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.geom; - -public class Line { - private T v1; - private T v2; - - public Line(T v1, T v2) { - this.v1 = v1; - this.v2 = v2; - } - - public T getV1() { - return v1; - } - - public void setV1(T v1) { - this.v1 = v1; - } - - public T getV2() { - return v2; - } - - public void setV2(T v2) { - this.v2 = v2; - } - public boolean isEqual(T t1, T t2){ - if((t1 == v1 || t1 == v2) - &&(t2 == v2 || t2 == v1)){ - return true; - } - return false; - } -} diff --git a/src/com/jogamp/graph/geom/Outline.java b/src/com/jogamp/graph/geom/Outline.java index d9bde4177..4e588623e 100644 --- a/src/com/jogamp/graph/geom/Outline.java +++ b/src/com/jogamp/graph/geom/Outline.java @@ -30,8 +30,8 @@ package com.jogamp.graph.geom; import java.util.ArrayList; import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.math.VectorUtil; -import jogamp.graph.math.VectorFloatUtil; /** Define a single continuous stroke by control vertices. @@ -124,7 +124,7 @@ public class Outline implements Comparable>{ if(closed){ T first = vertices.get(0); T last = getLastVertex(); - if(!VectorFloatUtil.checkEquality(first.getCoord(), last.getCoord())){ + if(!VectorUtil.checkEquality(first.getCoord(), last.getCoord())){ @SuppressWarnings("unchecked") T v = (T) first.clone(); vertices.add(v); diff --git a/src/com/jogamp/graph/geom/opengl/SVertex.java b/src/com/jogamp/graph/geom/opengl/SVertex.java index 86b95854d..076ac7456 100644 --- a/src/com/jogamp/graph/geom/opengl/SVertex.java +++ b/src/com/jogamp/graph/geom/opengl/SVertex.java @@ -27,9 +27,9 @@ */ package com.jogamp.graph.geom.opengl; -import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.math.VectorUtil; public class SVertex implements Vertex { private int id = Integer.MAX_VALUE; @@ -151,7 +151,7 @@ public class SVertex implements Vertex { } public int compareTo(Vertex p) { - if(VectorFloatUtil.checkEquality(coord, p.getCoord())) { + if(VectorUtil.checkEquality(coord, p.getCoord())) { return 0; } return -1; diff --git a/src/com/jogamp/graph/math/VectorUtil.java b/src/com/jogamp/graph/math/VectorUtil.java new file mode 100755 index 000000000..cca9a454f --- /dev/null +++ b/src/com/jogamp/graph/math/VectorUtil.java @@ -0,0 +1,295 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.math; + +import java.util.ArrayList; + +import jogamp.graph.math.MathFloat; + +import com.jogamp.graph.geom.Vertex; + +public class VectorUtil { + + public static final int CW = -1; + public static final int CCW = 1; + public static final int COLLINEAR = 0; + + /** compute the dot product of two points + * @param vec1 vector 1 + * @param vec2 vector 2 + * @return the dot product as float + */ + public static float dot(float[] vec1, float[] vec2) + { + return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]); + } + /** Normalize a vector + * @param vector input vector + * @return normalized vector + */ + public static float[] normalize(float[] vector) + { + float[] newVector = new float[3]; + + float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); + if(d> 0.0f) + { + newVector[0] = vector[0]/d; + newVector[1] = vector[1]/d; + newVector[2] = vector[2]/d; + } + return newVector; + } + + /** Scales a vector by param + * @param vector input vector + * @param scale constant to scale by + * @return scaled vector + */ + public static float[] scale(float[] vector, float scale) + { + float[] newVector = new float[3]; + + newVector[0] = vector[0]*scale; + newVector[1] = vector[1]*scale; + newVector[2] = vector[2]*scale; + return newVector; + } + + /** Adds to vectors + * @param v1 vector 1 + * @param v2 vector 2 + * @return v1 + v2 + */ + public static float[] vectorAdd(float[] v1, float[] v2) + { + float[] newVector = new float[3]; + + newVector[0] = v1[0] + v2[0]; + newVector[1] = v1[1] + v2[1]; + newVector[2] = v1[2] + v2[2]; + return newVector; + } + + /** cross product vec1 x vec2 + * @param vec1 vector 1 + * @param vec2 vecttor 2 + * @return the resulting vector + */ + public static float[] cross(float[] vec1, float[] vec2) + { + float[] out = new float[3]; + + out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2]; + out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0]; + out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1]; + + return out; + } + + /** Column Matrix Vector multiplication + * @param colMatrix column matrix (4x4) + * @param vec vector(x,y,z) + * @return result new float[3] + */ + public static float[] colMatrixVectorMult(float[] colMatrix, float[] vec) + { + float[] out = new float[3]; + + out[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12]; + out[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13]; + out[2] = vec[0]*colMatrix[2] + vec[1]*colMatrix[6] + vec[2]*colMatrix[10] + colMatrix[14]; + + return out; + } + + /** Matrix Vector multiplication + * @param rawMatrix column matrix (4x4) + * @param vec vector(x,y,z) + * @return result new float[3] + */ + public static float[] rowMatrixVectorMult(float[] rawMatrix, float[] vec) + { + float[] out = new float[3]; + + out[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3]; + out[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7]; + out[2] = vec[0]*rawMatrix[8] + vec[1]*rawMatrix[9] + vec[2]*rawMatrix[10] + rawMatrix[11]; + + return out; + } + + /** Calculate the midpoint of two values + * @param p1 first value + * @param p2 second vale + * @return midpoint + */ + public static float mid(float p1, float p2) + { + return (p1+p2)/2.0f; + } + /** Calculate the midpoint of two points + * @param p1 first point + * @param p2 second point + * @return midpoint + */ + public static float[] mid(float[] p1, float[] p2) + { + float[] midPoint = new float[3]; + midPoint[0] = (p1[0] + p2[0])/2.0f; + midPoint[1] = (p1[1] + p2[1])/2.0f; + midPoint[2] = (p1[2] + p2[2])/2.0f; + + return midPoint; + } + /** Compute the norm of a vector + * @param vec vector + * @return vorm + */ + public static float norm(float[] vec) + { + return MathFloat.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); + } + /** Compute distance between 2 points + * @param p0 a ref point on the line + * @param vec vector representing the direction of the line + * @param point the point to compute the relative distance of + * @return distance float + */ + public static float computeLength(float[] p0, float[] point) + { + float[] w = new float[]{point[0]-p0[0],point[1]-p0[1],point[2]-p0[2]}; + + float distance = MathFloat.sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]); + + return distance; + } + + /**Check equality of 2 vec3 vectors + * @param v1 vertex 1 + * @param v2 vertex 2 + * @return + */ + public static boolean checkEquality(float[] v1, float[] v2) + { + if(Float.compare(v1[0], v2[0]) == 0 + && Float.compare(v1[1] , v2[1]) == 0 + && Float.compare(v1[2], v2[2]) == 0 ) + return true; + return false; + } + + /** Compute the determinant of 3 vectors + * @param a vector 1 + * @param b vector 2 + * @param c vector 3 + * @return the determinant value + */ + public static float computeDeterminant(float[] a, float[] b, float[] c) + { + float area = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0]; + return area; + } + + /** Check if three vertices are colliniear + * @param v1 vertex 1 + * @param v2 vertex 2 + * @param v3 vertex 3 + * @return true if collinear, false otherwise + */ + public static boolean checkCollinear(float[] v1, float[] v2, float[] v3) + { + return (computeDeterminant(v1, v2, v3) == VectorUtil.COLLINEAR); + } + + /** Compute Vector + * @param v1 vertex 1 + * @param v2 vertex2 2 + * @return Vector V1V2 + */ + public static float[] computeVector(float[] v1, float[] v2) + { + float[] vector = new float[3]; + vector[0] = v2[0] - v1[0]; + vector[1] = v2[1] - v1[1]; + vector[2] = v2[2] - v1[2]; + return vector; + } + + /** Check if vertices in triangle circumcircle + * @param a triangle vertex 1 + * @param b triangle vertex 2 + * @param c triangle vertex 3 + * @param d vertex in question + * @return true if the vertex d is inside the circle defined by the + * vertices a, b, c. from paper by Guibas and Stolfi (1985). + */ + public static boolean inCircle(Vertex a, Vertex b, Vertex c, Vertex d){ + return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) - + (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) + + (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) - + (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0; + } + + /** Computes oriented area of a triangle + * @param a first vertex + * @param b second vertex + * @param c third vertex + * @return compute twice the area of the oriented triangle (a,b,c), the area + * is positive if the triangle is oriented counterclockwise. + */ + public static float triArea(Vertex a, Vertex b, Vertex c){ + return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX()); + } + + /** Check if points are in ccw order + * @param a first vertex + * @param b second vertex + * @param c third vertex + * @return true if the points a,b,c are in a ccw order + */ + public static boolean ccw(Vertex a, Vertex b, Vertex c){ + return triArea(a,b,c) > 0; + } + + /** Computes the area of a list of vertices to check if ccw + * @param vertices + * @return positve area if ccw else negative area value + */ + public static float area(ArrayList vertices) { + int n = vertices.size(); + float area = 0.0f; + for (int p = n - 1, q = 0; q < n; p = q++) + { + float[] pCoord = vertices.get(p).getCoord(); + float[] qCoord = vertices.get(q).getCoord(); + area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1]; + } + return area; + } +} diff --git a/src/jogamp/graph/curve/tess/Loop.java b/src/jogamp/graph/curve/tess/Loop.java index e4553968b..80b96b939 100644 --- a/src/jogamp/graph/curve/tess/Loop.java +++ b/src/jogamp/graph/curve/tess/Loop.java @@ -29,11 +29,11 @@ package jogamp.graph.curve.tess; import java.util.ArrayList; -import jogamp.graph.math.VectorFloatUtil; import com.jogamp.graph.geom.AABBox; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.math.VectorUtil; public class Loop { private HEdge root = null; @@ -103,9 +103,9 @@ public class Loop { if(vertices.size()<3) { throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size()); } - boolean isCCW = VectorFloatUtil.ccw(vertices.get(0).getPoint(), vertices.get(1).getPoint(), + boolean isCCW = VectorUtil.ccw(vertices.get(0).getPoint(), vertices.get(1).getPoint(), vertices.get(2).getPoint()); - boolean invert = isCCW && (direction == VectorFloatUtil.CW); + boolean invert = isCCW && (direction == VectorUtil.CW); HEdge firstEdge = null; HEdge lastEdge = null; @@ -160,7 +160,7 @@ public class Loop { public void addConstraintCurve(GraphOutline polyline) { // GraphOutline outline = new GraphOutline(polyline); /**needed to generate vertex references.*/ - initFromPolyline(polyline, VectorFloatUtil.CW); + initFromPolyline(polyline, VectorUtil.CW); GraphVertex v3 = locateClosestVertex(polyline); HEdge v3Edge = v3.findBoundEdge(); @@ -199,12 +199,12 @@ public class Loop { GraphVertex v = initVertices.get(i); GraphVertex nextV = initVertices.get(i+1); for(GraphVertex cand:vertices){ - float distance = VectorFloatUtil.computeLength(v.getCoord(), cand.getCoord()); + float distance = VectorUtil.computeLength(v.getCoord(), cand.getCoord()); if(distance < minDistance){ for (GraphVertex vert:vertices){ if(vert == v || vert == nextV || vert == cand) continue; - inValid = VectorFloatUtil.inCircle(v.getPoint(), nextV.getPoint(), + inValid = VectorUtil.inCircle(v.getPoint(), nextV.getPoint(), cand.getPoint(), vert.getPoint()); if(inValid){ break; @@ -230,7 +230,7 @@ public class Loop { private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) { HEdge next = root.getNext(); - if(!VectorFloatUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), + if(!VectorUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), edge.getGraphPoint().getPoint())){ return null; } @@ -248,7 +248,7 @@ public class Loop { e = e.getNext(); continue; } - inValid = VectorFloatUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), + inValid = VectorUtil.inCircle(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), cand, e.getGraphPoint().getPoint()); if(inValid){ break; @@ -339,7 +339,7 @@ public class Loop { float[] p0p1 = new float[]{vert1.getX() - vertex.getX(), vert1.getY() - vertex.getY(), vert1.getZ() - vertex.getZ()}; - float dotD1D0 = VectorFloatUtil.dot(prepD1, d0); + float dotD1D0 = VectorUtil.dot(prepD1, d0); if(dotD1D0 == 0){ /** ray parallel to segment */ current = next; @@ -347,8 +347,8 @@ public class Loop { continue; } - float s = VectorFloatUtil.dot(prepD1,p0p1)/dotD1D0; - float t = VectorFloatUtil.dot(prepD0,p0p1)/dotD1D0; + float s = VectorUtil.dot(prepD1,p0p1)/dotD1D0; + float t = VectorUtil.dot(prepD0,p0p1)/dotD1D0; if(s >= 0 && t >= 0 && t<= 1){ hits++; diff --git a/src/jogamp/graph/curve/text/GlyphShape.java b/src/jogamp/graph/curve/text/GlyphShape.java index 78ae7396c..712633f4b 100644 --- a/src/jogamp/graph/curve/text/GlyphShape.java +++ b/src/jogamp/graph/curve/text/GlyphShape.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import jogamp.graph.geom.plane.PathIterator; -import com.jogamp.graph.geom.Line; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; @@ -158,12 +157,5 @@ public class GlyphShape { */ public ArrayList getVertices(){ return shape.getVertices(); - } - - /** Get the list of AA lines defined by this object - * @return arraylist of lines - */ - public ArrayList> getLines(){ - return shape.getLines(); - } + } } diff --git a/src/jogamp/graph/math/VectorFloatUtil.java b/src/jogamp/graph/math/VectorFloatUtil.java deleted file mode 100755 index b2b9a8ee8..000000000 --- a/src/jogamp/graph/math/VectorFloatUtil.java +++ /dev/null @@ -1,293 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.graph.math; - -import java.util.ArrayList; - -import com.jogamp.graph.geom.Vertex; - -public class VectorFloatUtil { - - public static final int CW = -1; - public static final int CCW = 1; - public static final int COLLINEAR = 0; - - /** compute the dot product of two points - * @param vec1 vector 1 - * @param vec2 vector 2 - * @return the dot product as float - */ - public static float dot(float[] vec1, float[] vec2) - { - return (vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2]); - } - /** Normalize a vector - * @param vector input vector - * @return normalized vector - */ - public static float[] normalize(float[] vector) - { - float[] newVector = new float[3]; - - float d = MathFloat.sqrt(vector[0]*vector[0] + vector[1]*vector[1] + vector[2]*vector[2]); - if(d> 0.0f) - { - newVector[0] = vector[0]/d; - newVector[1] = vector[1]/d; - newVector[2] = vector[2]/d; - } - return newVector; - } - - /** Scales a vector by param - * @param vector input vector - * @param scale constant to scale by - * @return scaled vector - */ - public static float[] scale(float[] vector, float scale) - { - float[] newVector = new float[3]; - - newVector[0] = vector[0]*scale; - newVector[1] = vector[1]*scale; - newVector[2] = vector[2]*scale; - return newVector; - } - - /** Adds to vectors - * @param v1 vector 1 - * @param v2 vector 2 - * @return v1 + v2 - */ - public static float[] vectorAdd(float[] v1, float[] v2) - { - float[] newVector = new float[3]; - - newVector[0] = v1[0] + v2[0]; - newVector[1] = v1[1] + v2[1]; - newVector[2] = v1[2] + v2[2]; - return newVector; - } - - /** cross product vec1 x vec2 - * @param vec1 vector 1 - * @param vec2 vecttor 2 - * @return the resulting vector - */ - public static float[] cross(float[] vec1, float[] vec2) - { - float[] out = new float[3]; - - out[0] = vec2[2]*vec1[1] - vec2[1]*vec1[2]; - out[1] = vec2[0]*vec1[2] - vec2[2]*vec1[0]; - out[2] = vec2[1]*vec1[0] - vec2[0]*vec1[1]; - - return out; - } - - /** Column Matrix Vector multiplication - * @param colMatrix column matrix (4x4) - * @param vec vector(x,y,z) - * @return result new float[3] - */ - public static float[] colMatrixVectorMult(float[] colMatrix, float[] vec) - { - float[] out = new float[3]; - - out[0] = vec[0]*colMatrix[0] + vec[1]*colMatrix[4] + vec[2]*colMatrix[8] + colMatrix[12]; - out[1] = vec[0]*colMatrix[1] + vec[1]*colMatrix[5] + vec[2]*colMatrix[9] + colMatrix[13]; - out[2] = vec[0]*colMatrix[2] + vec[1]*colMatrix[6] + vec[2]*colMatrix[10] + colMatrix[14]; - - return out; - } - - /** Matrix Vector multiplication - * @param rawMatrix column matrix (4x4) - * @param vec vector(x,y,z) - * @return result new float[3] - */ - public static float[] rowMatrixVectorMult(float[] rawMatrix, float[] vec) - { - float[] out = new float[3]; - - out[0] = vec[0]*rawMatrix[0] + vec[1]*rawMatrix[1] + vec[2]*rawMatrix[2] + rawMatrix[3]; - out[1] = vec[0]*rawMatrix[4] + vec[1]*rawMatrix[5] + vec[2]*rawMatrix[6] + rawMatrix[7]; - out[2] = vec[0]*rawMatrix[8] + vec[1]*rawMatrix[9] + vec[2]*rawMatrix[10] + rawMatrix[11]; - - return out; - } - - /** Calculate the midpoint of two values - * @param p1 first value - * @param p2 second vale - * @return midpoint - */ - public static float mid(float p1, float p2) - { - return (p1+p2)/2.0f; - } - /** Calculate the midpoint of two points - * @param p1 first point - * @param p2 second point - * @return midpoint - */ - public static float[] mid(float[] p1, float[] p2) - { - float[] midPoint = new float[3]; - midPoint[0] = (p1[0] + p2[0])/2.0f; - midPoint[1] = (p1[1] + p2[1])/2.0f; - midPoint[2] = (p1[2] + p2[2])/2.0f; - - return midPoint; - } - /** Compute the norm of a vector - * @param vec vector - * @return vorm - */ - public static float norm(float[] vec) - { - return MathFloat.sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); - } - /** Compute distance between 2 points - * @param p0 a ref point on the line - * @param vec vector representing the direction of the line - * @param point the point to compute the relative distance of - * @return distance float - */ - public static float computeLength(float[] p0, float[] point) - { - float[] w = new float[]{point[0]-p0[0],point[1]-p0[1],point[2]-p0[2]}; - - float distance = MathFloat.sqrt(w[0]*w[0] + w[1]*w[1] + w[2]*w[2]); - - return distance; - } - - /**Check equality of 2 vec3 vectors - * @param v1 vertex 1 - * @param v2 vertex 2 - * @return - */ - public static boolean checkEquality(float[] v1, float[] v2) - { - if(Float.compare(v1[0], v2[0]) == 0 - && Float.compare(v1[1] , v2[1]) == 0 - && Float.compare(v1[2], v2[2]) == 0 ) - return true; - return false; - } - - /** Compute the determinant of 3 vectors - * @param a vector 1 - * @param b vector 2 - * @param c vector 3 - * @return the determinant value - */ - public static float computeDeterminant(float[] a, float[] b, float[] c) - { - float area = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[0]*b[2]*c[1] - a[1]*b[0]*c[2] - a[2]*b[1]*c[0]; - return area; - } - - /** Check if three vertices are colliniear - * @param v1 vertex 1 - * @param v2 vertex 2 - * @param v3 vertex 3 - * @return true if collinear, false otherwise - */ - public static boolean checkCollinear(float[] v1, float[] v2, float[] v3) - { - return (computeDeterminant(v1, v2, v3) == VectorFloatUtil.COLLINEAR); - } - - /** Compute Vector - * @param v1 vertex 1 - * @param v2 vertex2 2 - * @return Vector V1V2 - */ - public static float[] computeVector(float[] v1, float[] v2) - { - float[] vector = new float[3]; - vector[0] = v2[0] - v1[0]; - vector[1] = v2[1] - v1[1]; - vector[2] = v2[2] - v1[2]; - return vector; - } - - /** Check if vertices in triangle circumcircle - * @param a triangle vertex 1 - * @param b triangle vertex 2 - * @param c triangle vertex 3 - * @param d vertex in question - * @return true if the vertex d is inside the circle defined by the - * vertices a, b, c. from paper by Guibas and Stolfi (1985). - */ - public static boolean inCircle(Vertex a, Vertex b, Vertex c, Vertex d){ - return (a.getX() * a.getX() + a.getY() * a.getY()) * triArea(b, c, d) - - (b.getX() * b.getX() + b.getY() * b.getY()) * triArea(a, c, d) + - (c.getX() * c.getX() + c.getY() * c.getY()) * triArea(a, b, d) - - (d.getX() * d.getX() + d.getY() * d.getY()) * triArea(a, b, c) > 0; - } - - /** Computes oriented area of a triangle - * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return compute twice the area of the oriented triangle (a,b,c), the area - * is positive if the triangle is oriented counterclockwise. - */ - public static float triArea(Vertex a, Vertex b, Vertex c){ - return (b.getX() - a.getX()) * (c.getY() - a.getY()) - (b.getY() - a.getY())*(c.getX() - a.getX()); - } - - /** Check if points are in ccw order - * @param a first vertex - * @param b second vertex - * @param c third vertex - * @return true if the points a,b,c are in a ccw order - */ - public static boolean ccw(Vertex a, Vertex b, Vertex c){ - return triArea(a,b,c) > 0; - } - - /** Computes the area of a list of vertices to check if ccw - * @param vertices - * @return positve area if ccw else negative area value - */ - public static float area(ArrayList vertices) { - int n = vertices.size(); - float area = 0.0f; - for (int p = n - 1, q = 0; q < n; p = q++) - { - float[] pCoord = vertices.get(p).getCoord(); - float[] qCoord = vertices.get(q).getCoord(); - area += pCoord[0] * qCoord[1] - qCoord[0] * pCoord[1]; - } - return area; - } -} -- cgit v1.2.3 From 55356d999638491980a90cb2263b55c5d2e53e91 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 06:59:43 +0200 Subject: Font Refactoring ; Misc Changes ; Demo/Test Update Font Refactoring - Notion of distributed FontSet - FontFactory may produce FontSet and/or a Font by absolute ttf file path - Adding support for free Ubuntu fonts - Remove Vertex.Factory dependency for Font creation - Typecast Impl - Fix CmapTable selection - Fix horizontal spacing of space - Misc Changes - HwTextRenderer - Offer reshape for perspective and orthogonal view - Expose PMVMatrix, allowing user to setup their own view math. Demo Update - Dump font set a-zA-Z... - Dump 'lazy dog ..' text - Action: - s: toogle 'font set' - f: toggle fps - v: toggle v-sync - space: toggle font (ubuntu/java) - formated screenshot filename w/ font name Test Update: - add font set iteration --- src/com/jogamp/graph/curve/HwTextRenderer.java | 72 ++++------ src/com/jogamp/graph/font/Font.java | 10 ++ src/com/jogamp/graph/font/FontFactory.java | 60 ++++++-- src/com/jogamp/graph/font/FontSet.java | 60 ++++++++ src/demo/GPUTextGLListenerBase01.java | 115 +++++++++++++-- src/demo/GPUTextNewtDemo01.java | 12 +- src/demo/GPUTextNewtDemo02.java | 13 +- src/jogamp/graph/font/FontConstructor.java | 34 +++++ src/jogamp/graph/font/FontInt.java | 6 + src/jogamp/graph/font/JavaFontLoader.java | 157 +++++++++++---------- src/jogamp/graph/font/UbuntuFontLoader.java | 115 +++++++++++++++ src/jogamp/graph/font/typecast/TypecastFont.java | 148 +++++++++++-------- .../font/typecast/TypecastFontConstructor.java | 53 +++++++ .../graph/font/typecast/TypecastFontFactory.java | 64 --------- .../graph/font/typecast/TypecastHMetrics.java | 83 +++++++++++ .../graph/font/typecast/TypecastMetrics.java | 78 ---------- .../graph/font/typecast/TypecastRenderer.java | 14 +- src/jogamp/graph/geom/plane/AffineTransform.java | 7 + src/net/java/dev/typecast/ot/table/BaseTable.java | 1 - src/net/java/dev/typecast/ot/table/CvtTable.java | 1 - src/net/java/dev/typecast/ot/table/Os2Table.java | 1 - src/net/java/dev/typecast/ot/table/Program.java | 1 - .../java/dev/typecast/ot/table/TableFactory.java | 1 - .../test/junit/graph/TestHwTextRenderer01.java | 134 ++++++++---------- 24 files changed, 800 insertions(+), 440 deletions(-) create mode 100644 src/com/jogamp/graph/font/FontSet.java create mode 100644 src/jogamp/graph/font/FontConstructor.java create mode 100644 src/jogamp/graph/font/UbuntuFontLoader.java create mode 100644 src/jogamp/graph/font/typecast/TypecastFontConstructor.java delete mode 100644 src/jogamp/graph/font/typecast/TypecastFontFactory.java create mode 100644 src/jogamp/graph/font/typecast/TypecastHMetrics.java delete mode 100644 src/jogamp/graph/font/typecast/TypecastMetrics.java diff --git a/src/com/jogamp/graph/curve/HwTextRenderer.java b/src/com/jogamp/graph/curve/HwTextRenderer.java index c5f11d522..f3a15975a 100644 --- a/src/com/jogamp/graph/curve/HwTextRenderer.java +++ b/src/com/jogamp/graph/curve/HwTextRenderer.java @@ -38,13 +38,10 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc; import jogamp.graph.curve.text.GlyphString; import jogamp.graph.font.FontInt; -import jogamp.graph.font.typecast.TypecastFontFactory; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; -import com.jogamp.common.util.ReflectionUtil; import com.jogamp.graph.font.Font; -import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.opengl.SVertex; import jogamp.opengl.Debug; @@ -57,28 +54,6 @@ public class HwTextRenderer { protected static final boolean DEBUG = Debug.debug("TextRenderer"); static final boolean FONTTOOL_CUSTOM = false; - private static FontFactory fontFactory; - - static { - FontFactory _fontFactory = null; - - if(FONTTOOL_CUSTOM) { - _fontFactory = (FontFactory) ReflectionUtil.createInstance("jogamp.graph.font.ttf.TTFFontFactory", HwTextRenderer.class.getClassLoader()); - if(null!=_fontFactory) { - System.err.println("Using custom font tool"); - } - } - if(null==_fontFactory) { - _fontFactory = new TypecastFontFactory(); - } - fontFactory = _fontFactory; - } - - - public static FontFactory getFontFactory() { - return fontFactory; - } - private ShaderState st = new ShaderState(); private PMVMatrix pmvMatrix = new PMVMatrix(); @@ -113,19 +88,6 @@ public class HwTextRenderer { this.regionType = type; } - public Font createFont(Vertex.Factory factory, String name) { - return fontFactory.createFont(factory, name); - } - - - public Font createFont(Vertex.Factory factory, - String[] families, - String style, - String variant, - String weight) { - return fontFactory.createFont(factory, families, style, variant, weight); - } - /** * Initialize shaders and bindings for GPU based text Rendering, * should be called only once. @@ -162,9 +124,9 @@ public class HwTextRenderer { gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); + "shader", "shader/bin", "curverenderer"); ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, - "../shader", "../shader/bin", "curverenderer"); + "shader", "shader/bin", "curverenderer"); ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -259,6 +221,8 @@ public class HwTextRenderer { } } + public final PMVMatrix matrix() { return pmvMatrix; } + public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ pmvMatrix.glRotatef(angle, x, y, z); if(null != gl && st.inUse()) { @@ -279,7 +243,13 @@ public class HwTextRenderer { st.glUniform(gl, mgl_PMVMatrix); } } - + + public void setMatrix(GL2ES2 gl){ + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + public void updateAllShaderValues(GL2ES2 gl) { if(null != gl && st.inUse()) { st.glUniform(gl, mgl_PMVMatrix); @@ -297,7 +267,7 @@ public class HwTextRenderer { * @param far * @return */ - public boolean reshape(GL2ES2 gl, float angle, int width, int height, float near, float far){ + public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ win_width = width; win_height = height; float ratio = (float)width/(float)height; @@ -305,10 +275,26 @@ public class HwTextRenderer { pmvMatrix.glLoadIdentity(); pmvMatrix.gluPerspective(angle, ratio, near, far); - st.glUniform(gl, mgl_PMVMatrix); + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } return true; } + + public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { + win_width = width; + win_height = height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0, width, 0, height, near, far); + + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { AffineTransform affineTransform = new AffineTransform(pointFactory); diff --git a/src/com/jogamp/graph/font/Font.java b/src/com/jogamp/graph/font/Font.java index fbdf1f474..a4ab527e2 100644 --- a/src/com/jogamp/graph/font/Font.java +++ b/src/com/jogamp/graph/font/Font.java @@ -34,17 +34,27 @@ import com.jogamp.graph.geom.AABBox; * * TrueType Font Specification: * http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html + * + * TrueType Font Table Introduction: + * http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08 */ public interface Font { /** * Metrics for font + * + * Depending on the font's direction, horizontal or vertical, + * the following tables shall be used: + * + * Vertical http://developer.apple.com/fonts/TTRefMan/RM06/Chap6vhea.html + * Horizontal http://developer.apple.com/fonts/TTRefMan/RM06/Chap6hhea.html */ public interface Metrics { float getAscent(float pixelSize); float getDescent(float pixelSize); float getLineGap(float pixelSize); + float getMaxExtend(float pixelSize); float getScale(float pixelSize); AABBox getBBox(float pixelSize); } diff --git a/src/com/jogamp/graph/font/FontFactory.java b/src/com/jogamp/graph/font/FontFactory.java index b595413ba..1752a693c 100644 --- a/src/com/jogamp/graph/font/FontFactory.java +++ b/src/com/jogamp/graph/font/FontFactory.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -27,16 +27,54 @@ */ package com.jogamp.graph.font; -import com.jogamp.graph.geom.Vertex; +import java.security.AccessController; -public interface FontFactory { +import com.jogamp.common.util.ReflectionUtil; - Font createFont(Vertex.Factory factory, - String[] families, - String style, - String variant, - String weight); +import jogamp.graph.font.FontConstructor; +import jogamp.graph.font.JavaFontLoader; +import jogamp.graph.font.UbuntuFontLoader; +import jogamp.opengl.Debug; - Font createFont(Vertex.Factory factory, - String name); -} \ No newline at end of file +public class FontFactory { + /** Ubuntu is the default font family */ + public static final int UBUNTU = 0; + + /** Java fonts are optional */ + public static final int JAVA = 1; + + private static final FontConstructor fontConstr; + + static { + /** + * For example: + * "jogamp.graph.font.typecast.TypecastFontFactory" (default) + * "jogamp.graph.font.ttf.TTFFontImpl" + */ + String fontImplName = Debug.getProperty("FontImpl", true, AccessController.getContext()); + if(null == fontImplName) { + fontImplName = "jogamp.graph.font.typecast.TypecastFontConstructor"; + } + fontConstr = (FontConstructor) ReflectionUtil.createInstance(fontImplName, FontFactory.class.getClassLoader()); + } + + public static final FontConstructor getFontConstr() { return fontConstr; } + + public static final FontSet getDefault() { + return get(UBUNTU); + } + + public static final FontSet get(int font) { + switch (font) { + case JAVA: + return JavaFontLoader.get(); + default: + return UbuntuFontLoader.get(); + } + } + + public static final Font get(String path) { + return fontConstr.create(path); + } + +} diff --git a/src/com/jogamp/graph/font/FontSet.java b/src/com/jogamp/graph/font/FontSet.java new file mode 100644 index 000000000..0cee81124 --- /dev/null +++ b/src/com/jogamp/graph/font/FontSet.java @@ -0,0 +1,60 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.font; + + +public interface FontSet { + + /** Font family REGULAR **/ + public static final int FAMILY_REGULAR = 0; + + /** Font family LIGHT **/ + public static final int FAMILY_LIGHT = 1; + + /** Font family MEDIUM **/ + public static final int FAMILY_MEDIUM = 2; + + /** Font family CONDENSED **/ + public static final int FAMILY_CONDENSED = 3; + + /** Font family MONO **/ + public static final int FAMILY_MONOSPACED = 4; + + /** SERIF style/family bit flag. Fallback to Sans Serif. */ + public static final int STYLE_SERIF = 1 << 1; + + /** BOLD style bit flag */ + public static final int STYLE_BOLD = 1 << 2; + + /** ITALIC style bit flag */ + public static final int STYLE_ITALIC = 1 << 3; + + Font getDefault(); + + Font get(int family, int stylebits); +} diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 4e3a57fd9..eee1efbdb 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -29,31 +29,52 @@ package demo; import java.io.File; import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLRunnable; import com.jogamp.graph.curve.HwTextRenderer; import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.Vertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.awt.Screenshot; +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 3/4: font +/- + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - s: toogle draw 'font set' + * - f: toggle draw fps + * - v: toggle v-sync + * - space: toggle font (ubuntu/java) + */ public abstract class GPUTextGLListenerBase01 implements GLEventListener { Vertex.Factory vfactory; - protected HwTextRenderer textRenderer; + protected HwTextRenderer textRenderer; + int fontSet = FontFactory.UBUNTU; Font font; boolean debug; boolean trace; KeyAction keyAction; + volatile GLAutoDrawable autoDrawable = null; + boolean drawFontSet = true; + boolean drawFPS = true; boolean updateFont = true; int fontSize = 40; final int fontSizeModulo = 100; @@ -71,15 +92,15 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { static final String text2; static { - //text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n0123456789"; - text1 = "abcdef\nghijklmn\nopqrstuv\nwxyz\n#$!%-+="; - text2 = text1.toUpperCase(); + text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; + text2 = "The quick brown fox jumps over the lazy dog"; } public GPUTextGLListenerBase01(Vertex.Factory vfactory, int mode, boolean debug, boolean trace) { + // this.font = FontFactory.get(FontFactory.JAVA).getDefault(); + this.font = FontFactory.get(fontSet).getDefault(); this.vfactory = vfactory; this.textRenderer = new HwTextRenderer(vfactory, mode); - this.font = textRenderer.createFont(vfactory, "Lucida Sans Regular"); this.debug = debug; this.trace = trace; } @@ -94,8 +115,8 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { } public void init(GLAutoDrawable drawable) { + autoDrawable = drawable; GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(debug) { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); } @@ -109,7 +130,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glViewport(xstart, ystart, width, height); - textRenderer.reshape(gl, 45.0f, width, height, 0.1f, 7000.0f); + textRenderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f); dumpMatrix(true); } @@ -120,9 +141,34 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - if(updateMatrix) { - textRenderer.resetMatrix(gl); - textRenderer.translate(gl, xTran, yTran, zoom); + if(drawFPS || drawFontSet || updateMatrix) { + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + final GLAnimatorControl animator = drawable.getAnimator(); + final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFrames()>10; + + if(_drawFPS || drawFontSet) { + textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f); + } + if(_drawFPS) { + final float fps = ( animator.getTotalFrames() * 1000.0f ) / (float) animator.getDuration() ; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + textRenderer.resetMatrix(null); + textRenderer.translate(gl, 0, 0, -6000); + textRenderer.renderString3D(gl, font, fpsS.substring(0, fpsSp+2), position, fontSize, texSize); + } + if(drawFontSet) { + textRenderer.resetMatrix(null); + textRenderer.translate(gl, 0, height-50, -6000); + textRenderer.renderString3D(gl, font, text1, position, fontSize, texSize); + } + if(_drawFPS || drawFontSet) { + textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f); + } + + textRenderer.resetMatrix(null); + textRenderer.translate(null, xTran, yTran, zoom); textRenderer.rotate(gl, ang, 0, 1, 0); updateMatrix = false; } @@ -131,6 +177,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { } public void dispose(GLAutoDrawable drawable) { + autoDrawable = null; GL2ES2 gl = drawable.getGL().getGL2ES2(); textRenderer.dispose(gl); } @@ -147,6 +194,16 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { dumpMatrix(false); } + public void nextFontSet() { + fontSet = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; + font = FontFactory.get(fontSet).getDefault(); + } + + public void setFontSet(int set, int family, int stylebits) { + fontSet = set; + font = FontFactory.get(fontSet).get(family, stylebits); + } + public void move(float x, float y){ xTran += x; yTran += y; @@ -183,9 +240,13 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { window.removeKeyListener(keyAction); } - public void printScreen(GLWindow window, String dir, String tech, boolean exportAlpha) throws GLException, IOException{ - String filename = dir + tech + "-" + window.getWidth()+ "x" + window.getHeight() + "-T" + texSize + "-Z" + Math.abs(zoom) +".tga"; - Screenshot.writeToTargaFile(new File(filename), window.getWidth(), window.getHeight(), exportAlpha); + public void printScreen(String dir, String tech, int width, int height, boolean exportAlpha) throws GLException, IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf("-%03dx%03d-Z%04d-T%04d-%s", width, height, (int)Math.abs(zoom), texSize, font.getName()); + + String filename = dir + tech + sw +".tga"; + Screenshot.writeToTargaFile(new File(filename), width, height, exportAlpha); } public class KeyAction implements KeyListener { @@ -228,6 +289,34 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { else if(arg0.getKeyCode() == KeyEvent.VK_9){ rotate(-1); } + else if(arg0.getKeyChar() == 's') { + drawFontSet = !drawFontSet; + System.err.println("Draw font set: "+drawFontSet); + } + else if(arg0.getKeyChar() == 'f'){ + drawFPS = !drawFPS; + System.err.println("Draw FPS: "+drawFPS); + } + else if(arg0.getKeyChar() == 'v') { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + public void run(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + int i = gl.getSwapInterval(); + i = i==0 ? 1 : 0; + gl.setSwapInterval(i); + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetCounter(); + } + System.err.println("Swap Interval: "+i); + } + }); + } + } + else if(arg0.getKeyChar() == ' ') { + nextFontSet(); + } } public void keyTyped(KeyEvent arg0) {} public void keyReleased(KeyEvent arg0) {} diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index a07ead417..934eba1ba 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -36,7 +36,7 @@ import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.Animator; public class GPUTextNewtDemo01 { static final boolean DEBUG = false; @@ -61,14 +61,16 @@ public class GPUTextNewtDemo01 { window = GLWindow.create(caps); window.setPosition(10, 10); - window.setSize(400, 400); + window.setSize(800, 400); window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); textGLListener = new TextGLListener(); textGLListener.attachTo(window); + window.enablePerfLog(true); window.setVisible(true); - FPSAnimator animator = new FPSAnimator(10); + // FPSAnimator animator = new FPSAnimator(10); + Animator animator = new Animator(); animator.add(window); animator.start(); } @@ -76,8 +78,10 @@ public class GPUTextNewtDemo01 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); + // FBO size unrelated with 1 pass //setMatrix(-10, 10, 0f, -70, 0); - setMatrix(-10, 10, 0f, -100, 400); + // setMatrix(-80, -30, 0f, -100, 0); + setMatrix(-400, -30, 0f, -500, 0); } public void init(GLAutoDrawable drawable) { diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index 012ee9936..b46053f1d 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -36,7 +36,7 @@ import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.Animator; public class GPUTextNewtDemo02 { /** @@ -70,15 +70,17 @@ public class GPUTextNewtDemo02 { window = GLWindow.create(caps); window.setPosition(10, 10); - window.setSize(400, 400); + window.setSize(800, 400); window.setTitle("GPU Text Newt Demo 02 - r2t1 msaa0"); textGLListener = new TextGLListener(); textGLListener.attachTo(window); + window.enablePerfLog(true); window.setVisible(true); - FPSAnimator animator = new FPSAnimator(60); + // FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); animator.add(window); animator.start(); } @@ -86,7 +88,10 @@ public class GPUTextNewtDemo02 { private class TextGLListener extends GPUTextGLListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-10, 10, 0f, -100, 400); + // FIXME: Rami will fix FBO size !! + // setMatrix(-10, 10, 0f, -100, 400); + // setMatrix(-80, -30, 0f, -100, window.getWidth()*3); + setMatrix(-400, -30, 0f, -500, window.getWidth()*3); } public void init(GLAutoDrawable drawable) { diff --git a/src/jogamp/graph/font/FontConstructor.java b/src/jogamp/graph/font/FontConstructor.java new file mode 100644 index 000000000..a382d292e --- /dev/null +++ b/src/jogamp/graph/font/FontConstructor.java @@ -0,0 +1,34 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font; + +import com.jogamp.graph.font.Font; + +public interface FontConstructor { + Font create(String name); +} diff --git a/src/jogamp/graph/font/FontInt.java b/src/jogamp/graph/font/FontInt.java index c18787723..4d9390da2 100644 --- a/src/jogamp/graph/font/FontInt.java +++ b/src/jogamp/graph/font/FontInt.java @@ -35,6 +35,12 @@ import com.jogamp.graph.font.Font; public interface FontInt extends Font { public interface Glyph extends Font.Glyph { + // reserved special glyph IDs + // http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#ba57949e + public static final int ID_UNKNOWN = 0; + public static final int ID_CR = 2; + public static final int ID_SPACE = 3; + public Path2D getPath(); // unscaled path public Path2D getPath(float pixelSize); } diff --git a/src/jogamp/graph/font/JavaFontLoader.java b/src/jogamp/graph/font/JavaFontLoader.java index f6954944d..6769a691a 100644 --- a/src/jogamp/graph/font/JavaFontLoader.java +++ b/src/jogamp/graph/font/JavaFontLoader.java @@ -27,85 +27,92 @@ */ package jogamp.graph.font; -public class JavaFontLoader { +import com.jogamp.common.util.IntObjectHashMap; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontSet; +import com.jogamp.graph.font.FontFactory; - static String javaFontPath; - static - { - javaFontPath = System.getProperty("java.home") + "/lib/fonts/"; - } +public class JavaFontLoader implements FontSet { + + final static FontSet fontLoader = new JavaFontLoader(); - public static final int MAX_BITMAP_FONT_SIZE = 120; + public static FontSet get() { + return fontLoader; + } + + final static String availableFontFileNames[] = + { + /* 00 */ "LucidaBrightRegular.ttf", + /* 01 */ "LucidaBrightItalic.ttf", + /* 02 */ "LucidaBrightDemiBold.ttf", + /* 03 */ "LucidaBrightDemiItalic.ttf", + /* 04 */ "LucidaSansRegular.ttf", + /* 05 */ "LucidaSansDemiBold.ttf", + /* 06 */ "LucidaTypewriterRegular.ttf", + /* 07 */ "LucidaTypewriterBold.ttf", + }; + + final String javaFontPath; + + private JavaFontLoader() { + javaFontPath = System.getProperty("java.home") + "/lib/fonts/"; + } - public static final int MONOSPACED = 1; - public static final int SERIF = 2; - public static final int SANSERIF = 3; - public static final int CURSIVE = 4; - public static final int FANTASY = 5; - - final static String availableJavaFontNames[] = - { - "Lucida Bright Regular", - "Lucida Bright Italic", - "Lucida Bright Demibold", - "Lucida Bright Demibold Italic", - "Lucida Sans Regular", - "Lucida Sans Demibold", - "Lucida Sans Typewriter Regular", - "Lucida Sans Typewriter Bold", - }; - static public String[] getAvailableNames() - { - return availableJavaFontNames; - } - - final static String availableJavaFontFileNames[] = - { - "LucidaBrightRegular.ttf", - "LucidaBrightItalic.ttf", - "LucidaBrightDemiBold.ttf", - "LucidaBrightDemiItalic.ttf", - "LucidaSansRegular.ttf", - "LucidaSansDemiBold.ttf", - "LucidaTypewriterRegular.ttf", - "LucidaTypewriterBold.ttf", - }; + static final IntObjectHashMap fontMap = new IntObjectHashMap(); + + public Font getDefault() { + return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular + } + + public Font get(int family, int style) { + Font font = (Font)fontMap.get( ( family << 8 ) | style ); + if (font != null) { + return font; + } - static public String get(int type) - { - String font = null; - - switch (type) - { - case MONOSPACED: - font = getByName("Lucida Sans Typewriter Regular"); - break; - case SERIF: - font = getByName("Lucida Bright Regular"); - break; - case SANSERIF: - font = getByName("Lucida Sans Regular"); - break; - case CURSIVE: - font = getByName("Lucida Bright Regular"); - break; - case FANTASY: - font = getByName("Lucida Sans Regular"); - break; - } + // 1st process Sans Serif (2 fonts) + if( 0 == ( style & STYLE_SERIF ) ) { + if( 0 != ( style & STYLE_BOLD ) ) { + font = abspath(availableFontFileNames[5]); + } else { + font = abspath(availableFontFileNames[4]); + } + return font; + } + + // Serif Fonts .. + switch (family) { + case FAMILY_LIGHT: + case FAMILY_MEDIUM: + case FAMILY_CONDENSED: + case FAMILY_REGULAR: + if( 0 != ( style & STYLE_BOLD ) ) { + if( 0 != ( style & STYLE_ITALIC ) ) { + font = abspath(availableFontFileNames[3]); + } else { + font = abspath(availableFontFileNames[2]); + } + } else if( 0 != ( style & STYLE_ITALIC ) ) { + font = abspath(availableFontFileNames[1]); + } else { + font = abspath(availableFontFileNames[0]); + } + break; + + case FAMILY_MONOSPACED: + if( 0 != ( style & STYLE_BOLD ) ) { + font = abspath(availableFontFileNames[7]); + } else { + font = abspath(availableFontFileNames[6]); + } + break; + } - return font; - } + return font; + } + + Font abspath(String fname) { + return FontFactory.getFontConstr().create(javaFontPath+fname); + } - static public String getByName(String name) - { - for (int i=0; i pointFactory; final OTFontCollection fontset; final OTFont font; - TypecastMetrics metrics; + TypecastHMetrics metrics; final CmapFormat cmapFormat; int cmapentries; - // final IntIntHashMap char2Code; IntObjectHashMap char2Glyph; - public static TypecastFont create(Vertex.Factory factory, String name) { - String path = JavaFontLoader.getByName(name); - if(null == path) { - path = name; - } - OTFontCollection fontset; - try { - fontset = OTFontCollection.create(new File(path)); - return new TypecastFont(factory, fontset); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public TypecastFont(Vertex.Factory factory, OTFontCollection fontset) { - this.pointFactory = factory; + public TypecastFont(OTFontCollection fontset) { this.fontset = fontset; this.font = fontset.getFont(0); + // FIXME: Generic attempt to find the best CmapTable, + // which is assumed to be the one with the most entries (stupid 'eh?) CmapTable cmapTable = font.getCmapTable(); - CmapFormat _cmapFormat = null; - /* - if(null == _cmapFormat) { - _cmapFormat = cmapTable.getCmapFormat(ID.platformMacintosh, ID.encodingASCII); - } */ - if(null == _cmapFormat) { - // default unicode - _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingUnicode); - } - if(null == _cmapFormat) { - // maybe a symbol font ? - _cmapFormat = cmapTable.getCmapFormat(ID.platformMicrosoft, ID.encodingSymbol); - } - if(null == _cmapFormat) { - throw new RuntimeException("Cannot find a suitable cmap table for font "+font); + CmapFormat[] _cmapFormatP = { null, null, null, null }; + int platform = -1; + int platformLength = -1; + int encoding = -1; + for(int i=0; i platformLength ) { + platformLength = cf.getLength() ; + platform = pidx; + encoding = cmapIdxEntry.getEncodingId(); + } + } } - cmapFormat = _cmapFormat; + if(0 <= platform) { + cmapFormat = _cmapFormatP[platform]; + if(DEBUG) { + System.err.println("Selected CmapFormat: platform " + platform + + ", encoding "+encoding + ": "+cmapFormat); + } + } else { + CmapFormat _cmapFormat = null; + /*if(null == _cmapFormat) { + platform = ID.platformMacintosh; + encoding = ID.encodingASCII; + _cmapFormat = cmapTable.getCmapFormat(platform, encoding); + } */ + if(null == _cmapFormat) { + // default unicode + platform = ID.platformMicrosoft; + encoding = ID.encodingUnicode; + _cmapFormat = cmapTable.getCmapFormat((short)platform, (short)encoding); + } + if(null == _cmapFormat) { + // maybe a symbol font ? + platform = ID.platformMicrosoft; + encoding = ID.encodingSymbol; + _cmapFormat = cmapTable.getCmapFormat((short)platform, (short)encoding); + } + if(null == _cmapFormat) { + throw new RuntimeException("Cannot find a suitable cmap table for font "+font); + } + cmapFormat = _cmapFormat; + if(DEBUG) { + System.err.println("Selected CmapFormat (2): platform " + platform + ", encoding "+encoding + ": "+cmapFormat); + } + } cmapentries = 0; for (int i = 0; i < cmapFormat.getRangeCount(); ++i) { @@ -104,21 +122,18 @@ class TypecastFont implements FontInt { if(DEBUG) { System.err.println("num glyphs: "+font.getNumGlyphs()); System.err.println("num cmap entries: "+cmapentries); - } - - /* - char2Code = new IntIntHashMap(cmapentries + cmapentries/4); - for (int i = 0; i < cmapFormat.getRangeCount(); ++i) { - CmapFormat.Range range = cmapFormat.getRange(i); - for (int j = range.getStartCode(); j <= range.getEndCode(); ++j) { - final int code = cmapFormat.mapCharCode(j); - char2Code.put(j, code); - if(code < 50) { - System.err.println(" char: " + (int)j + " ( " + (char)j +" ) -> " + code); - } + System.err.println("num cmap ranges: "+cmapFormat.getRangeCount()); + + for (int i = 0; i < cmapFormat.getRangeCount(); ++i) { + CmapFormat.Range range = cmapFormat.getRange(i); + for (int j = range.getStartCode(); j <= range.getEndCode(); ++j) { + final int code = cmapFormat.mapCharCode(j); + if(code < 15) { + System.err.println(" char: " + (int)j + " ( " + (char)j +" ) -> " + code); + } + } } } - */ char2Glyph = new IntObjectHashMap(cmapentries + cmapentries/4); } @@ -128,7 +143,7 @@ class TypecastFont implements FontInt { public Metrics getMetrics() { if (metrics == null) { - metrics = new TypecastMetrics(this); + metrics = new TypecastHMetrics(this); } return metrics; } @@ -137,15 +152,30 @@ class TypecastFont implements FontInt { TypecastGlyph result = (TypecastGlyph) char2Glyph.get(symbol); if (null == result) { // final short code = (short) char2Code.get(symbol); - final short code = (short) cmapFormat.mapCharCode(symbol); + short code = (short) cmapFormat.mapCharCode(symbol); + if(0 == code && 0 != symbol) { + // reserved special glyph IDs by convention + switch(symbol) { + case ' ': code = Glyph.ID_SPACE; break; + case '\n': code = Glyph.ID_CR; break; + default: code = Glyph.ID_UNKNOWN; + } + } + net.java.dev.typecast.ot.OTGlyph glyph = font.getGlyph(code); - final Path2D path = TypecastRenderer.buildPath(glyph); + if(null == glyph) { + glyph = font.getGlyph(Glyph.ID_UNKNOWN); + } + if(null == glyph) { + throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+code); + } + Path2D path = TypecastRenderer.buildPath(glyph); result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), path); if(DEBUG) { System.err.println("New glyph: " + (int)symbol + " ( " + (char)symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + path); } final HdmxTable hdmx = font.getHdmxTable(); - if (null != hdmx) { + if (null!= result && null != hdmx) { /*if(DEBUG) { System.err.println("hdmx "+hdmx); }*/ @@ -164,7 +194,7 @@ class TypecastFont implements FontInt { } public void getOutline(String string, float pixelSize, AffineTransform transform, Path2D[] result) { - TypecastRenderer.getOutline(pointFactory, this, string, pixelSize, transform, result); + TypecastRenderer.getOutline(this, string, pixelSize, transform, result); } public float getStringWidth(String string, float pixelSize) { diff --git a/src/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogamp/graph/font/typecast/TypecastFontConstructor.java new file mode 100644 index 000000000..5fb9d32f7 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastFontConstructor.java @@ -0,0 +1,53 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import java.io.File; +import java.io.IOException; + +import jogamp.graph.font.FontConstructor; + +import net.java.dev.typecast.ot.OTFontCollection; + +import com.jogamp.graph.font.Font; + + +public class TypecastFontConstructor implements FontConstructor { + + public Font create(String path) { + OTFontCollection fontset; + try { + fontset = OTFontCollection.create(new File(path)); + return new TypecastFont(fontset); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastFontFactory.java b/src/jogamp/graph/font/typecast/TypecastFontFactory.java deleted file mode 100644 index 04559a138..000000000 --- a/src/jogamp/graph/font/typecast/TypecastFontFactory.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.graph.font.typecast; - -import java.util.HashMap; -import java.util.Map; - -import com.jogamp.graph.font.Font; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Vertex.Factory; -import com.jogamp.graph.geom.Vertex; - - -public class TypecastFontFactory implements FontFactory { - - Map fonts = new HashMap(); - - public Font createFont(Factory factory, String name) { - Font result = fonts.get(name); - if (result == null) { - result = TypecastFont.create(factory, name); - if(result != null) { - fonts.put(name, result); - } - } - return result; - } - - - public Font createFont(Factory factory, - String[] families, - String style, - String variant, - String weight) { - throw new Error("not implemented"); - } - - -} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastHMetrics.java b/src/jogamp/graph/font/typecast/TypecastHMetrics.java new file mode 100644 index 000000000..cd8595498 --- /dev/null +++ b/src/jogamp/graph/font/typecast/TypecastHMetrics.java @@ -0,0 +1,83 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.font.typecast; + +import net.java.dev.typecast.ot.table.HeadTable; +import net.java.dev.typecast.ot.table.HheaTable; +import com.jogamp.graph.font.Font.Metrics; +import com.jogamp.graph.geom.AABBox; + +class TypecastHMetrics implements Metrics { + private final TypecastFont fontImpl; + + // HeadTable + private final HeadTable headTable; + private final float unitsPerEM_Inv; + private final AABBox bbox; + // HheaTable + private final HheaTable hheaTable; + // VheaTable (for horizontal fonts) + // private final VheaTable vheaTable; + + public TypecastHMetrics(TypecastFont fontImpl) { + this.fontImpl = fontImpl; + headTable = this.fontImpl.font.getHeadTable(); + hheaTable = this.fontImpl.font.getHheaTable(); + // vheaTable = this.fontImpl.font.getVheaTable(); + unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() ); + + int maxWidth = headTable.getXMax() - headTable.getXMin(); + int maxHeight = headTable.getYMax() - headTable.getYMin(); + float lowx= headTable.getXMin(); + float lowy = -(headTable.getYMin()+maxHeight); + float highx = lowx + maxWidth; + float highy = lowy + maxHeight; + bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert + } + + public final float getAscent(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getAscender(); // invert + } + public final float getDescent(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getDescender(); // invert + } + public final float getLineGap(float pixelSize) { + return getScale(pixelSize) * -hheaTable.getLineGap(); // invert + } + public final float getMaxExtend(float pixelSize) { + return getScale(pixelSize) * hheaTable.getXMaxExtent(); + } + public final float getScale(float pixelSize) { + return pixelSize * unitsPerEM_Inv; + } + public final AABBox getBBox(float pixelSize) { + AABBox res = new AABBox(bbox.getLow(), bbox.getHigh()); + res.scale(getScale(pixelSize)); + return res; + } +} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastMetrics.java b/src/jogamp/graph/font/typecast/TypecastMetrics.java deleted file mode 100644 index 9ca1e3bf7..000000000 --- a/src/jogamp/graph/font/typecast/TypecastMetrics.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.graph.font.typecast; - -import net.java.dev.typecast.ot.table.HeadTable; -import net.java.dev.typecast.ot.table.HheaTable; - -import com.jogamp.graph.font.Font.Metrics; -import com.jogamp.graph.geom.AABBox; - -class TypecastMetrics implements Metrics { - private final TypecastFont fontImpl; - - // HeadTable - private final HeadTable headTable; - private final float unitsPerEM_Inv; - private final AABBox bbox; - // HheaTable - private final HheaTable hheaTable; - - public TypecastMetrics(TypecastFont fontImpl) { - this.fontImpl = fontImpl; - headTable = this.fontImpl.font.getHeadTable(); - hheaTable = this.fontImpl.font.getHheaTable(); - unitsPerEM_Inv = 1.0f / ( (float) headTable.getUnitsPerEm() ); - - int maxWidth = headTable.getXMax() - headTable.getXMin(); - int maxHeight = headTable.getYMax() - headTable.getYMin(); - float lowx= headTable.getXMin(); - float lowy = -(headTable.getYMin()+maxHeight); - float highx = lowx + maxWidth; - float highy = lowy + maxHeight; - bbox = new AABBox(lowx, lowy, 0, highx, highy, 0); // invert - } - - public final float getAscent(float pixelSize) { - return getScale(pixelSize) * -hheaTable.getAscender(); // invert - } - public final float getDescent(float pixelSize) { - return getScale(pixelSize) * -hheaTable.getDescender(); // invert - } - public final float getLineGap(float pixelSize) { - return getScale(pixelSize) * -hheaTable.getLineGap(); // invert - } - public final float getScale(float pixelSize) { - return pixelSize * unitsPerEM_Inv; - } - public final AABBox getBBox(float pixelSize) { - AABBox res = new AABBox(bbox.getLow(), bbox.getHigh()); - res.scale(getScale(pixelSize)); - return res; - } -} \ No newline at end of file diff --git a/src/jogamp/graph/font/typecast/TypecastRenderer.java b/src/jogamp/graph/font/typecast/TypecastRenderer.java index 11f1ec028..410f5b73a 100644 --- a/src/jogamp/graph/font/typecast/TypecastRenderer.java +++ b/src/jogamp/graph/font/typecast/TypecastRenderer.java @@ -31,9 +31,6 @@ import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.Vertex.Factory; - import net.java.dev.typecast.ot.Point; import net.java.dev.typecast.ot.OTGlyph; @@ -43,7 +40,7 @@ import net.java.dev.typecast.ot.OTGlyph; */ public class TypecastRenderer { - public static void getOutline(Factory factory, TypecastFont font, + public static void getOutline(TypecastFont font, String string, float pixelSize, AffineTransform transform, Path2D[] p) { if (string == null) { @@ -55,9 +52,9 @@ public class TypecastRenderer { float ascent = metrics.getAscent(pixelSize) ; float descent = metrics.getDescent(pixelSize) ; if (transform == null) { - transform = new AffineTransform(factory); + transform = new AffineTransform(); } - AffineTransform t = new AffineTransform(factory); + AffineTransform t = new AffineTransform(); float advanceY = lineGap - descent + ascent; float y = 0; @@ -71,7 +68,10 @@ public class TypecastRenderer { y -= advanceY; advanceTotal = 0; continue; - } + } else if (character == ' ') { + advanceTotal += font.font.getHmtxTable().getAdvanceWidth(TypecastGlyph.ID_SPACE) * metrics.getScale(pixelSize); + continue; + } TypecastGlyph glyph = (TypecastGlyph) font.getGlyph(character); Path2D gp = glyph.getPath(); float scale = metrics.getScale(pixelSize); diff --git a/src/jogamp/graph/geom/plane/AffineTransform.java b/src/jogamp/graph/geom/plane/AffineTransform.java index de13ff9de..2ba9f8d06 100644 --- a/src/jogamp/graph/geom/plane/AffineTransform.java +++ b/src/jogamp/graph/geom/plane/AffineTransform.java @@ -72,6 +72,13 @@ public class AffineTransform implements Cloneable, Serializable { */ transient int type; + public AffineTransform() { + pointFactory = null; + type = TYPE_IDENTITY; + m00 = m11 = 1.0f; + m10 = m01 = m02 = m12 = 0.0f; + } + public AffineTransform(Factory factory) { pointFactory = factory; type = TYPE_IDENTITY; diff --git a/src/net/java/dev/typecast/ot/table/BaseTable.java b/src/net/java/dev/typecast/ot/table/BaseTable.java index 7e6c37a5e..f92de718f 100644 --- a/src/net/java/dev/typecast/ot/table/BaseTable.java +++ b/src/net/java/dev/typecast/ot/table/BaseTable.java @@ -24,7 +24,6 @@ import java.io.ByteArrayInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; -import net.java.dev.typecast.ot.Fixed; /** * Baseline Table diff --git a/src/net/java/dev/typecast/ot/table/CvtTable.java b/src/net/java/dev/typecast/ot/table/CvtTable.java index 6035c6378..44dc0af41 100644 --- a/src/net/java/dev/typecast/ot/table/CvtTable.java +++ b/src/net/java/dev/typecast/ot/table/CvtTable.java @@ -8,7 +8,6 @@ package net.java.dev.typecast.ot.table; -import java.io.ByteArrayInputStream; import java.io.DataInput; import java.io.IOException; diff --git a/src/net/java/dev/typecast/ot/table/Os2Table.java b/src/net/java/dev/typecast/ot/table/Os2Table.java index bb3b60101..9ec599724 100644 --- a/src/net/java/dev/typecast/ot/table/Os2Table.java +++ b/src/net/java/dev/typecast/ot/table/Os2Table.java @@ -52,7 +52,6 @@ package net.java.dev.typecast.ot.table; import java.io.DataInput; import java.io.IOException; -import net.java.dev.typecast.ot.Fixed; /** * @version $Id: Os2Table.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ diff --git a/src/net/java/dev/typecast/ot/table/Program.java b/src/net/java/dev/typecast/ot/table/Program.java index 6fd02a469..d4dd094e2 100644 --- a/src/net/java/dev/typecast/ot/table/Program.java +++ b/src/net/java/dev/typecast/ot/table/Program.java @@ -10,7 +10,6 @@ package net.java.dev.typecast.ot.table; import java.io.DataInput; import java.io.IOException; -import java.io.ByteArrayInputStream; /** * @version $Id: Program.java,v 1.1.1.1 2004-12-05 23:14:57 davidsch Exp $ diff --git a/src/net/java/dev/typecast/ot/table/TableFactory.java b/src/net/java/dev/typecast/ot/table/TableFactory.java index 632abcf44..28a7a4a97 100644 --- a/src/net/java/dev/typecast/ot/table/TableFactory.java +++ b/src/net/java/dev/typecast/ot/table/TableFactory.java @@ -51,7 +51,6 @@ package net.java.dev.typecast.ot.table; import java.io.DataInputStream; -import java.io.InputStream; import java.io.IOException; import net.java.dev.typecast.ot.OTFont; import net.java.dev.typecast.ot.OTFontCollection; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java index a0b04d69a..7f5ee9d98 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java @@ -7,6 +7,7 @@ import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -15,10 +16,9 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.Window; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; import demo.GPUTextGLListenerBase01; @@ -30,13 +30,13 @@ public class TestHwTextRenderer01 { NativeWindowFactory.initSingleton(true); } - static void destroyWindow(Window window) { + static void destroyWindow(GLWindow window) { if(null!=window) { window.destroy(); } } - static GLWindow createWindow(String title, GLCapabilities caps, int width, int height) { + static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { Assert.assertNotNull(caps); GLWindow window = GLWindow.create(caps); @@ -53,88 +53,83 @@ public class TestHwTextRenderer01 { public void testTextRendererR2T01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL3bc); GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); caps.setAlphaBits(4); - GLWindow window = createWindow("r2t1msaa0", caps, 400,400); + GLWindow window = createWindow("r2t1-msaa0", caps, 800,400); TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); - textGLListener.setTech(-10, 10, 0f, -1000, 400); - textGLListener.attachTo(window); - - FPSAnimator animator = new FPSAnimator(10); - animator.add(window); - animator.start(); - - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } + textGLListener.attachTo(window); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 400); + window.display(); - textGLListener.resetPrinting(); - textGLListener.setTech(-111, 74, 0, -380, 1100); - Thread.sleep(100); - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } - - textGLListener.resetPrinting(); - textGLListener.setTech(-111, 74, 0, -80, 2500); - Thread.sleep(100); - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } + textGLListener.setTech(-400, -30, 0, -380, 1100); + window.display(); - animator.stop(); + textGLListener.setTech(-400, -20, 0, -80, 2500); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 400); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 1100); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 2500); + window.display(); + destroyWindow(window); - - Thread.sleep(1000); } @Test public void testTextRendererMSAA01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL2ES2); GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); caps.setAlphaBits(4); caps.setSampleBuffers(true); caps.setNumSamples(4); - GLWindow window = createWindow("r2t0msaa1", caps, 400, 400); + GLWindow window = createWindow("r2t0-msaa1", caps, 800, 400); TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); - textGLListener.setTech(-10, 10, 0f, -1000, 0); - textGLListener.attachTo(window); - - FPSAnimator animator = new FPSAnimator(10); - animator.add(window); - animator.start(); - - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } - - textGLListener.resetPrinting(); - textGLListener.setTech(-111, 74, 0, -380, 0); - Thread.sleep(100); - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } - - textGLListener.resetPrinting(); - textGLListener.setTech(-111, 74, 0, -80, 0); - Thread.sleep(100); - while(!textGLListener.isPrinted()){ - Thread.sleep(100); - } - - animator.stop(); + textGLListener.attachTo(window); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + destroyWindow(window); - - Thread.sleep(1000); } private class TextGLListener extends GPUTextGLListenerBase01 { - GLWindow glwindow; + String winTitle; + public TextGLListener(int type) { super(SVertex.factory(), type, false, false); } + public void attachTo(GLWindow window) { + super.attachTo(window); + winTitle = window.getTitle(); + } public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ setMatrix(xt, yt, angle, zoom, fboSize); } @@ -148,27 +143,12 @@ public class TestHwTextRenderer01 { textRenderer.setAlpha(gl, 1.0f); textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); } - public void attachTo(GLWindow window) { - super.attachTo(window); - glwindow = window; - } - - public boolean isPrinted(){ - return !printScreen; - } - public void resetPrinting(){ - printScreen = true; - } - public void display(GLAutoDrawable drawable) { super.display(drawable); try { - if(printScreen){ - printScreen(glwindow, "./", glwindow.getTitle(), false); - printScreen = false; - } + printScreen("./", winTitle, drawable.getWidth(), drawable.getHeight(), false); } catch (GLException e) { e.printStackTrace(); } catch (IOException e) { -- cgit v1.2.3 From dbcd775a7763ca131280a8341775fdfa50c4f909 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 07:12:28 +0200 Subject: Import: Ubuntu Font Family 0.71.2, http://font.ubuntu.com/ - Ubuntu Font License, Version 1.0 http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt --- LICENSE.txt | 22 +++ .../graph/font/fonts/ubuntu/CONTRIBUTING.txt | 21 ++ src/jogamp/graph/font/fonts/ubuntu/FONTLOG.txt | 211 +++++++++++++++++++++ src/jogamp/graph/font/fonts/ubuntu/LICENCE-FAQ.txt | 177 +++++++++++++++++ src/jogamp/graph/font/fonts/ubuntu/LICENCE.txt | 96 ++++++++++ src/jogamp/graph/font/fonts/ubuntu/README.txt | 15 ++ src/jogamp/graph/font/fonts/ubuntu/TRADEMARKS.txt | 4 + src/jogamp/graph/font/fonts/ubuntu/Ubuntu-B.ttf | Bin 0 -> 339320 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-BI.ttf | Bin 0 -> 362784 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-L.ttf | Bin 0 -> 421172 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-LI.ttf | Bin 0 -> 415424 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-M.ttf | Bin 0 -> 346940 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-MI.ttf | Bin 0 -> 372728 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf | Bin 0 -> 359668 bytes src/jogamp/graph/font/fonts/ubuntu/Ubuntu-RI.ttf | Bin 0 -> 389744 bytes src/jogamp/graph/font/fonts/ubuntu/copyright.txt | 5 + 16 files changed, 551 insertions(+) create mode 100644 src/jogamp/graph/font/fonts/ubuntu/CONTRIBUTING.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/FONTLOG.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/LICENCE-FAQ.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/LICENCE.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/README.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/TRADEMARKS.txt create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-B.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-BI.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-L.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-LI.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-M.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-MI.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/Ubuntu-RI.ttf create mode 100644 src/jogamp/graph/font/fonts/ubuntu/copyright.txt diff --git a/LICENSE.txt b/LICENSE.txt index 3326fd124..4b5accb41 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -88,3 +88,25 @@ Files: ++++ +L.4) The JOGL source tree contains fonts from Ubuntu + which is covered by the UBUNTU FONT LICENCE Version 1.0 + +Ubunut Font Family +================== + +The Ubuntu Font Family are libre fonts funded by Canonical Ltd on behalf of the Ubuntu project. + + + +Copyright 2010 Canonical Ltd. +Licensed under the Ubuntu Font Licence 1.0 + +Author: Canonical Ltd., Dalton Maag + +UBUNTU FONT LICENCE +Version 1.0 +http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt + +Files: + src/jogamp/graph/font/fonts/ubuntu/ + diff --git a/src/jogamp/graph/font/fonts/ubuntu/CONTRIBUTING.txt b/src/jogamp/graph/font/fonts/ubuntu/CONTRIBUTING.txt new file mode 100644 index 000000000..15bdc0c0b --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/CONTRIBUTING.txt @@ -0,0 +1,21 @@ +The Ubuntu Font Family is very long-term endeavour, and the first time +that a professionally-designed font has been funded specifically with +the intent of being an on-going community expanded project: + + http://font.ubuntu.com/ + +Development of the Ubuntu Font Family is undertaken on Launchpad: + + http://launchpad.net/ubuntu-font-family/ + +and this is where milestones, bug management and releases are handled. + +Contributions are welcomed. Your work will be used on millions of +computers every single day! Following the initial bootstrapping of +Latin, Cyrillic, Greek, Arabic and Hebrew expansion will be undertaken +by font designers from the font design and Ubuntu communities. + +To ensure that the Ubuntu Font Family can be re-licensed to future +widely-used libre font licences, copyright assignment is being required: + + https://launchpad.net/~uff-contributors diff --git a/src/jogamp/graph/font/fonts/ubuntu/FONTLOG.txt b/src/jogamp/graph/font/fonts/ubuntu/FONTLOG.txt new file mode 100644 index 000000000..cf0e4c111 --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/FONTLOG.txt @@ -0,0 +1,211 @@ +This is the FONTLOG file for the Ubuntu Font Family and attempts to follow +the recommendations at: http://scripts.sil.org/OFL-FAQ_web#43cecb44 + + +Overview + +The new Ubuntu Font Family was started to enable the personality of +Ubuntu to be seen and felt in every menu, button and dialog. +The typeface is sans-serif, uses OpenType features and is manually +hinted for clarity on desktop and mobile computing screens. + +The scope of the Ubuntu Font Family includes all the languages used by +the various Ubuntu users around the world in tune with Ubuntu's +philosophy which states that every user should be able to use their +software in the language of their choice. So the Ubuntu Font Family +project will be extended to cover many more written languages. + + +History + +The Ubuntu Font Family has been creating during 2010. As of December 2010 +coverage is provided for Latin, Cyrillic and Greek across Regular, Italic, +Bold and Bold-Italic. + + +ChangeLog + +2010-03-08 (Paul Sladen) Ubuntu Font Family version 0.71.2 + + * (Production) Adjust Medium WeightClass to 500 (Md, MdIt) (LP: #730912) + +2010-03-07 (Paul Sladen) Ubuntu Font Family version 0.71.1 + + * (Design) Add Capitalised version of glyphs and kern. (Lt, LtIt, + Md, MdIt) DM (LP: #677446) + * (Design) Re-space and tighen Regular and Italic by amount specified + by Mark Shuttleworth (minus 4 FUnits). (Rg, It) (LP: #677149) + * (Design) Design: Latin (U+0192) made straight more like l/c f with + tail (LP: #670768) + * (Design) (U+01B3) should have hook on right, as the lowercase + (U+01B4) (LP: #681026) + * (Design) Tail of Light Italic germandbls, longs and lowercase 'f' + to match Italic/BoldItalic (LP: #623925) + * (Production) Update feature (Lt, LtIt, Md, MdIt). DM + (LP: #676538, #676539) + * (Production) Remove Bulgarian locl feature for Italics. (LP: #708578) + * (Production) Update Description information with new string: + "The Ubuntu Font Family are libre fonts funded by Canonical Ltd + on behalf of the Ubuntu project. The font design work and + technical implementation is being undertaken by Dalton Maag. The + typeface is sans-serif, uses OpenType features and is manually + hinted for clarity on desktop and mobile computing screens. The + scope of the Ubuntu Font Family includes all the languages used + by the various Ubuntu users around the world in tune with + Ubuntu's philosophy which states that every user should be able + to use their software in the language of their choice. The + project is ongoing, and we expect the family will be extended to + cover many written languages in the coming years." + (Rg, It, Bd, BdIt, Lt, LtIt, Md, MdIt) (LP: #690590) + * (Production) Pixel per em indicator added at U+F000 (Lt, LtIt, Md, + MdIt) (LP: #615787) + * (Production) Version number indicator added at U+EFFD (Lt, LtIt, Md, + MdIt) (LP: #640623) + * (Production) fstype bit set to 0 - Editable (Lt, LtIt, Md, MdIt) + (LP: #648406) + * (Production) Localisation of name table has been removed because + of problems with Mac OS/X interpretation of localisation. DM + (LP: #730785) + * (Hinting) Regular '?' dot non-circular (has incorrect control + value). (LP: #654336) + * (Hinting) Too much space after latin capital 'G' in 13pt + regular. Now reduced. (LP: #683437) + * (Hinting) Balance Indian Rupee at 18,19pt (LP: #662177) + * (Hinting) Make Regular '£' less ambiguous at 13-15 ppm (LP: #685562) + * (Hinting) Regular capital 'W' made symmetrical at 31 ppem (LP: #686168) + +2010-12-14 (Paul Sladen) Ubuntu Font Family version 0.70.1 + + Packaging, rebuilt from '2010-12-08 UbuntuFontsSourceFiles_070.zip': + * (Midstream) Fstype bit != 0 (LP: #648406) + * (Midstream) Add unit test to validate fstype bits (LP: #648406) + * (Midstream) Add unit test to validate licence + +2010-12-14 (Paul Sladen) Ubuntu Font Family version 0.70 + + Release notes 0.70: + * (Design) Add Capitalised version of glyphs and kern. (Rg, It, Bd, + BdIt) DM (LP: #676538, #677446) + * (Design) Give acute and grave a slight upright move to more match + the Hungarian double acute angle. (Rg, It, Bd, BdIt) (LP: #656647) + * (Design) Shift Bold Italic accent glyphs to be consistent with the + Italic. (BdIt only) DM (LP: #677449) + * (Design) Check spacing and kerning of dcaron, lcaron and + tcaron. (Rg, It, Bd, BdIt) (LP: #664722) + * (Design) Add positive kerning to () {} [] to open out the + combinations so they are less like a closed box. (Rg, It, Bd, + BdIt) (LP: #671228) + * (Design) Change design of acute.asc and check highest points (Bd + and BdIt only) DM + * (Production) Update feature. DM (LP: #676538, #676539) + * (Production) Remove Romanian locl feature. (Rg, It, Bd, BdIt) + (LP: #635615) + * (Production) Update Copyright information with new + strings. "Copyright 2010 Canonical Ltd. Licensed under the Ubuntu + Font Licence 1.0" Trademark string "Ubuntu and Canonical are + registered trademarks of Canonical Ltd." (Rg, It, Bd, BdIt) DM + (LP: #677450) + * (Design) Check aligning of hyphen, math signs em, en, check braces + and other brackets. 16/11 (LP: #676465) + * (Production) Pixel per em indicator added at U+F000 (Rg, It, Bd, + BdIt) (LP: #615787) + * (Production) Version number indicator added at U+EFFD (Rg, It, Bd, + BdIt) (LP: #640623) + * (Production) fstype bit set to 0 - Editable (Rg, It, Bd, BdIt) + (LP: #648406) + +2010-10-05 (Paul Sladen) Ubuntu Font Family version 0.69 + + [Dalton Maag] + * Italic, + - Hinting on lowercase Italic l amended 19ppm (LP: #632451) + - Hinting on lowercase Italic u amended 12ppm (LP: #626376) + + * Regular, Italic, Bold, BoldItalic + - New Rupee Sign added @ U+20B9 (LP: #645987) + - Ubuntu Roundel added @ U+E0FF (LP: #651606) + + [Paul Sladen] + * All + - Removed "!ubu" GSUB.calt ligature for U+E0FF (LP: #651606) + + +Acknowledgements + +If you make modifications be sure to add your name (N), email (E), +web-address (if you have one) (W) and description (D). This list is in +alphabetical order. + +N: Amélie Bonet +W: http://ameliebonet.com/ +D: Type design with Dalton Maag, particularly Ubuntu Mono + +N: Ron Carpenter +N: Vincent Connare +N: Lukas Paltram +W: http://www.daltonmaag.com/ +D: Type design and engineering with Dalton Maag + +N: Dave Crossland +E: dave@understandingfonts.com +W: http://understandingfonts.com/ +D: Documentation and libre licensing guidance + +N: Iain Farrell +W: http://www.flickr.com/photos/iain +D: Ubuntu Font Family delivery for the Ubuntu UX team + +N: Shiraaz Gabru +W: http://www.daltonmaag.com/ +D: Ubuntu Font Family project management at Dalton Maag + +N: Marcus Haslam +W: http://design.canonical.com/author/marcus-haslam/ +D: Creative inspiration + +N: Ben Laenen +D: Inspiration behind the pixels-per-em (PPEM) readout debugging glyph at U+F000 + (for this font the concept was re-implemented from scratch by Dalton-Maag) + +N: Bruno Maag +W: http://www.daltonmaag.com/ +D: Stylistic direction of the Ubuntu Font Family, as head of Dalton Maag + +N: Ivanka Majic +W: http://www.ivankamajic.com/ +D: Guiding the UX team and Cyrillic feedback + +N: David Marshall +N: Malcolm Wooden +W: http://www.daltonmaag.com/ +D: Font Engineering and technical direction + +N: Rodrigo Rivas +D: Indian Rupee Sign glyph + +N: Mark Shuttleworth +E: mark@ubuntu.com +W: http://www.markshuttleworth.com/ +D: Executive quality-control and funding + +N: Paul Sladen +E: ubuntu@paul.sladen.org +W: http://www.paul.sladen.org/ +D: Bug triaging, packaging + +N: Nicolas Spalinger +W: http://planet.open-fonts.org +D: Continuous guidance on libre/open font licensing, best practises in source + tree layout, release and packaging (pkg-fonts Debian team) + +N: Kenneth Wimer +D: Initial PPA packaging + +* Canonical Ltd is the primary commercial sponsor of the Ubuntu and + Kubuntu operating systems +* Dalton Maag are a custom type foundry headed by Bruno Maag + +For further documentation, information on contributors, source code +downloads and those involved with the Ubuntu Font Family, visit: + + http://font.ubuntu.com/ diff --git a/src/jogamp/graph/font/fonts/ubuntu/LICENCE-FAQ.txt b/src/jogamp/graph/font/fonts/ubuntu/LICENCE-FAQ.txt new file mode 100644 index 000000000..776a25edf --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/LICENCE-FAQ.txt @@ -0,0 +1,177 @@ + Ubuntu Font Family Licensing FAQ + + Stylistic Foundations + + The Ubuntu Font Family is the first time that a libre typeface has been + designed professionally and explicitly with the intent of developing a + public and long-term community-based development process. + + When developing an open project, it is generally necessary to have firm + foundations: a font needs to maintain harmony within itself even across + many type designers and writing systems. For the [1]Ubuntu Font Family, + the process has been guided with the type foundry Dalton Maag setting + the project up with firm stylistic foundation covering several + left-to-right scripts: Latin, Greek and Cyrillic; and right-to-left + scripts: Arabic and Hebrew (due in 2011). + + With this starting point the community will, under the supervision of + [2]Canonical and [3]Dalton Maag, be able to build on the existing font + sources to expand their character coverage. Ultimately everybody will + be able to use the Ubuntu Font Family in their own written languages + across the whole of Unicode (and this will take some time!). + + Licensing + + The licence chosen by any free software project is one of the + foundational decisions that sets out how derivatives and contributions + can occur, and in turn what kind of community will form around the + project. + + Using a licence that is compatible with other popular licences is a + powerful constraint because of the [4]network effects: the freedom to + share improvements between projects allows free software to reach + high-quality over time. Licence-proliferation leads to many + incompatible licences, undermining the network effect, the freedom to + share and ultimately making the libre movement that Ubuntu is a part of + less effective. For all kinds of software, writing a new licence is not + to be taken lightly and is a choice that needs to be thoroughly + justified if this path is taken. + + Today it is not clear to Canonical what the best licence for a font + project like the Ubuntu Font Family is: one that starts life designed + by professionals and continues with the full range of community + development, from highly commercial work in new directions to curious + beginners' experimental contributions. The fast and steady pace of the + Ubuntu release cycle means that an interim libre licence has been + necessary to enable the consideration of the font family as part of + Ubuntu 10.10 operating system release. + + Before taking any decision on licensing, Canonical as sponsor and + backer of the project has reviewed the many existing licenses used for + libre/open fonts and engaged the stewards of the most popular licenses + in detailed discussions. The current interim licence is the first step + in progressing the state-of-the-art in licensing for libre/open font + development. + + The public discussion must now involve everyone in the (comparatively + new) area of the libre/open font community; including font users, + software freedom advocates, open source supporters and existing libre + font developers. Most importantly, the minds and wishes of professional + type designers considering entering the free software business + community must be taken on board. + + Conversations and discussion has taken place, privately, with + individuals from the following groups (generally speaking personally on + behalf of themselves, rather than their affiliations): + * [5]SIL International + * [6]Open Font Library + * [7]Software Freedom Law Center + * [8]Google Font API + + Document embedding + + One issue highlighted early on in the survey of existing font licences + is that of document embedding. Almost all font licences, both free and + unfree, permit embedding a font into a document to a certain degree. + Embedding a font with other works that make up a document creates a + "combined work" and copyleft would normally require the whole document + to be distributed under the terms of the font licence. As beautiful as + the font might be, such a licence makes a font too restrictive for + useful general purpose digital publishing. + + The situation is not entirely unique to fonts and is encountered also + with tools such as GNU Bison: a vanilla GNU GPL licence would require + anything generated with Bison to be made available under the terms of + the GPL as well. To avoid this, Bison is [9]published with an + additional permission to the GPL which allows the output of Bison to be + made available under any licence. + + The conflict between licensing of fonts and licensing of documents, is + addressed in two popular libre font licences, the SIL OFL and GNU GPL: + * [10]SIL Open Font Licence: When OFL fonts are embedded in a + document, the OFL's terms do not apply to that document. (See + [11]OFL-FAQ for details. + * [12]GPL Font Exception: The situation is resolved by granting an + additional permission to allow documents to not be covered by the + GPL. (The exception is being reviewed). + + The Ubuntu Font Family must also resolve this conflict, ensuring that + if the font is embedded and then extracted it is once again clearly + under the terms of its libre licence. + + Long-term licensing + + Those individuals involved, especially from Ubuntu and Canonical, are + interested in finding a long-term libre licence that finds broad favour + across the whole libre/open font community. The deliberation during the + past months has been on how to licence the Ubuntu Font Family in the + short-term, while knowingly encouraging everyone to pursue a long-term + goal. + * [13]Copyright assignment will be required so that the Ubuntu Font + Family's licensing can be progressively expanded to one (or more) + licences, as best practice continues to evolve within the + libre/open font community. + * Canonical will support and fund legal work on libre font licensing. + It is recognised that the cost and time commitments required are + likely to be significant. We invite other capable parties to join + in supporting this activity. + + The GPL version 3 (GPLv3) will be used for Ubuntu Font Family build + scripts and the CC-BY-SA for associated documentation and non-font + content: all items which do not end up embedded in general works and + documents. + +Ubuntu Font Licence + + For the short-term only, the initial licence is the [14]Ubuntu Font + License (UFL). This is loosely inspired from the work on the SIL + OFL 1.1, and seeks to clarify the issues that arose during discussions + and legal review, from the perspective of the backers, Canonical Ltd. + Those already using established licensing models such as the GPL, OFL + or Creative Commons licensing should have no worries about continuing + to use them. The Ubuntu Font Licence (UFL) and the SIL Open Font + Licence (SIL OFL) are not identical and should not be confused with + each other. Please read the terms precisely. The UFL is only intended + as an interim license, and the overriding aim is to support the + creation of a more suitable and generic libre font licence. As soon as + such a licence is developed, the Ubuntu Font Family will migrate to + it—made possible by copyright assignment in the interium. Between the + OFL 1.1, and the UFL 1.0, the following changes are made to produce the + Ubuntu Font Licence: + * Clarification: + + 1. Document embedding (see [15]embedding section above). + 2. Apply at point of distribution, instead of receipt + 3. Author vs. copyright holder disambiguation (type designers are + authors, with the copyright holder normally being the funder) + 4. Define "Propagate" (for internationalisation, similar to the GPLv3) + 5. Define "Substantially Changed" + 6. Trademarks are explicitly not transferred + 7. Refine renaming requirement + + Streamlining: + 8. Remove "not to be sold separately" clause + 9. Remove "Reserved Font Name(s)" declaration + + A visual demonstration of how these points were implemented can be + found in the accompanying coloured diff between SIL OFL 1.1 and the + Ubuntu Font Licence 1.0: [16]ofl-1.1-ufl-1.0.diff.html + +References + + 1. http://font.ubuntu.com/ + 2. http://www.canonical.com/ + 3. http://www.daltonmaag.com/ + 4. http://en.wikipedia.org/wiki/Network_effect + 5. http://scripts.sil.org/ + 6. http://openfontlibrary.org/ + 7. http://www.softwarefreedom.org/ + 8. http://code.google.com/webfonts + 9. http://www.gnu.org/licenses/gpl-faq.html#CanIUseGPLToolsForNF + 10. http://scripts.sil.org/OFL_web + 11. http://scripts.sil.org/OFL-FAQ_web + 12. http://www.gnu.org/licenses/gpl-faq.html#FontException + 13. https://launchpad.net/~uff-contributors + 14. http://font.ubuntu.com/ufl/ubuntu-font-licence-1.0.txt + 15. http://font.ubuntu.com/ufl/FAQ.html#embedding + 16. http://font.ubuntu.com/ufl/ofl-1.1-ufl-1.0.diff.html diff --git a/src/jogamp/graph/font/fonts/ubuntu/LICENCE.txt b/src/jogamp/graph/font/fonts/ubuntu/LICENCE.txt new file mode 100644 index 000000000..ae78a8f94 --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/LICENCE.txt @@ -0,0 +1,96 @@ +------------------------------- +UBUNTU FONT LICENCE Version 1.0 +------------------------------- + +PREAMBLE +This licence allows the licensed fonts to be used, studied, modified and +redistributed freely. The fonts, including any derivative works, can be +bundled, embedded, and redistributed provided the terms of this licence +are met. The fonts and derivatives, however, cannot be released under +any other licence. The requirement for fonts to remain under this +licence does not require any document created using the fonts or their +derivatives to be published under this licence, as long as the primary +purpose of the document is not to be a vehicle for the distribution of +the fonts. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this licence and clearly marked as such. This may +include source files, build scripts and documentation. + +"Original Version" refers to the collection of Font Software components +as received under this licence. + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to +a new environment. + +"Copyright Holder(s)" refers to all individuals and companies who have a +copyright ownership of the Font Software. + +"Substantially Changed" refers to Modified Versions which can be easily +identified as dissimilar to the Font Software by users of the Font +Software comparing the Original Version with the Modified Version. + +To "Propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification and with or without charging +a redistribution fee), making available to the public, and in some +countries other activities as well. + +PERMISSION & CONDITIONS +This licence does not grant any rights under trademark law and all such +rights are reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Font Software, to propagate the Font Software, subject to +the below conditions: + +1) Each copy of the Font Software must contain the above copyright +notice and this licence. These can be included either as stand-alone +text files, human-readable headers or in the appropriate machine- +readable metadata fields within text or binary files as long as those +fields can be easily viewed by the user. + +2) The font name complies with the following: +(a) The Original Version must retain its name, unmodified. +(b) Modified Versions which are Substantially Changed must be renamed to +avoid use of the name of the Original Version or similar names entirely. +(c) Modified Versions which are not Substantially Changed must be +renamed to both (i) retain the name of the Original Version and (ii) add +additional naming elements to distinguish the Modified Version from the +Original Version. The name of such Modified Versions must be the name of +the Original Version, with "derivative X" where X represents the name of +the new work, appended to that name. + +3) The name(s) of the Copyright Holder(s) and any contributor to the +Font Software shall not be used to promote, endorse or advertise any +Modified Version, except (i) as required by this licence, (ii) to +acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with +their explicit written permission. + +4) The Font Software, modified or unmodified, in part or in whole, must +be distributed entirely under this licence, and must not be distributed +under any other licence. The requirement for fonts to remain under this +licence does not affect any document created using the Font Software, +except any version of the Font Software extracted from a document +created using the Font Software may only be distributed under this +licence. + +TERMINATION +This licence becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER +DEALINGS IN THE FONT SOFTWARE. diff --git a/src/jogamp/graph/font/fonts/ubuntu/README.txt b/src/jogamp/graph/font/fonts/ubuntu/README.txt new file mode 100644 index 000000000..292d4ade6 --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/README.txt @@ -0,0 +1,15 @@ + ---------------------- + Ubuntu Font Family + ====================== + +The Ubuntu Font Family are a set of matching new libre/open fonts in +development during 2010--2011. The development is being funded by +Canonical Ltd on behalf the wider Free Software community and the +Ubuntu project. The technical font design work and implementation is +being undertaken by Dalton Maag. + +Both the final font Truetype/OpenType files and the design files used +to produce the font family are distributed under an open licence and +you are expressly encouraged to experiment, modify, share and improve. + + http://font.ubuntu.com/ diff --git a/src/jogamp/graph/font/fonts/ubuntu/TRADEMARKS.txt b/src/jogamp/graph/font/fonts/ubuntu/TRADEMARKS.txt new file mode 100644 index 000000000..d34265bc8 --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/TRADEMARKS.txt @@ -0,0 +1,4 @@ +Ubuntu and Canonical are registered trademarks of Canonical Ltd. + +The licence accompanying these works does not grant any rights +under trademark law and all such rights are reserved. diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-B.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-B.ttf new file mode 100644 index 000000000..7639344e7 Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-B.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-BI.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-BI.ttf new file mode 100644 index 000000000..337b8a88b Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-BI.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-L.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-L.ttf new file mode 100644 index 000000000..c3b0fa46d Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-L.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-LI.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-LI.ttf new file mode 100644 index 000000000..d65e8eab3 Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-LI.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-M.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-M.ttf new file mode 100644 index 000000000..387ef03fc Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-M.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-MI.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-MI.ttf new file mode 100644 index 000000000..5b92fcb5d Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-MI.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf new file mode 100644 index 000000000..a46446440 Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-R.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-RI.ttf b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-RI.ttf new file mode 100644 index 000000000..0e0955918 Binary files /dev/null and b/src/jogamp/graph/font/fonts/ubuntu/Ubuntu-RI.ttf differ diff --git a/src/jogamp/graph/font/fonts/ubuntu/copyright.txt b/src/jogamp/graph/font/fonts/ubuntu/copyright.txt new file mode 100644 index 000000000..3a45d712e --- /dev/null +++ b/src/jogamp/graph/font/fonts/ubuntu/copyright.txt @@ -0,0 +1,5 @@ +Copyright 2010 Canonical Ltd. + +This Font Software is licensed under the Ubuntu Font Licence, Version +1.0. https://launchpad.net/ubuntu-font-licence + -- cgit v1.2.3 From 4644863fbf6e8223b7843c63f9c5466f34fc8eeb Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 07:26:56 +0200 Subject: Relocate Hw*Renderer -> opengl subpackage --- src/com/jogamp/graph/curve/HwRegionRenderer.java | 385 -------------------- src/com/jogamp/graph/curve/HwTextRenderer.java | 358 ------------------- .../graph/curve/opengl/HwRegionRenderer.java | 388 +++++++++++++++++++++ .../jogamp/graph/curve/opengl/HwTextRenderer.java | 353 +++++++++++++++++++ .../graph/curve/opengl/shader/curverenderer.fp | 99 ++++++ .../graph/curve/opengl/shader/curverenderer.vp | 13 + src/com/jogamp/graph/curve/shader/curverenderer.fp | 99 ------ src/com/jogamp/graph/curve/shader/curverenderer.vp | 13 - src/demo/GPURegionNewtDemo01.java | 2 +- src/demo/GPURegionNewtDemo02.java | 2 +- src/demo/GPUTextGLListenerBase01.java | 2 +- 11 files changed, 856 insertions(+), 858 deletions(-) delete mode 100755 src/com/jogamp/graph/curve/HwRegionRenderer.java delete mode 100644 src/com/jogamp/graph/curve/HwTextRenderer.java create mode 100755 src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java create mode 100644 src/com/jogamp/graph/curve/opengl/HwTextRenderer.java create mode 100644 src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp create mode 100644 src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp delete mode 100644 src/com/jogamp/graph/curve/shader/curverenderer.fp delete mode 100644 src/com/jogamp/graph/curve/shader/curverenderer.vp diff --git a/src/com/jogamp/graph/curve/HwRegionRenderer.java b/src/com/jogamp/graph/curve/HwRegionRenderer.java deleted file mode 100755 index 2caa6bb7e..000000000 --- a/src/com/jogamp/graph/curve/HwRegionRenderer.java +++ /dev/null @@ -1,385 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve; - -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.Vertex; - -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class HwRegionRenderer { - protected static final boolean DEBUG = Debug.debug("RegionRenderer"); - - private ShaderState st; - private PMVMatrix pmvMatrix = new PMVMatrix(); - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private float sharpness = 0.5f; - private float alpha = 1.0f; - private float strength = 3.0f; - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private GLContext context; - private FloatBuffer color = FloatBuffer.allocate(3); - private HashMap regions = new HashMap(); - - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public HwRegionRenderer(GLContext context) { - this.context = context; - init(context, 0.5f); - } - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param type region type (single or multipass) - */ - public HwRegionRenderer(GLContext context, int type) { - this.context = context; - this.regionType = type; - init(context, 0.5f); - } - - private boolean init(GLContext context, float sharpvalue){ - if(initialized){ - if(DEBUG) { - System.err.println("HWRegionRenderer: Already initialized!"); - } - return true; - } - sharpness = sharpvalue; - - GL2ES2 gl = context.getGL().getGL2ES2(); - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.setSwapInterval(1); - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - initShader(gl); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(); - - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - st.glUseProgram(gl, false); - - if(DEBUG) { - System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public float getAlpha() { - return alpha; - } - public void setAlpha(float alpha_t) { - alpha = alpha_t; - } - - public void setColor(float r, float g, float b){ - color.put(r); - color.put(g); - color.put(b); - color.rewind(); - } - - public void rotate(float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - } - public void translate(float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - } - - public void resetMatrix(){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - } - - /** - * @param drawable - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null==st) { - if(DEBUG){ - System.err.println("HWRegionRenderer: Shader State is null, or not"); - } - return false; - } - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - st.glUseProgram(gl, false); - return true; - } - - private void initShader(GL2ES2 gl) { - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwRegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwRegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); - } - - st = new ShaderState(); - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - } - - private Region createRegion(OutlineShape outlineShape) { - Region region = RegionFactory.create(context, st, regionType); - - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); - ArrayList vertices = (ArrayList) outlineShape.getVertices(); - region.addVertices(vertices); - region.addTriangles(triangles); - - region.update(); - return region; - } - - private Region createRegion(OutlineShape[] outlineShapes) { - Region region = RegionFactory.create(context, st, regionType); - - int numVertices = region.getNumVertices(); - - for(OutlineShape outlineShape:outlineShapes){ - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = outlineShape.triangulate(sharpness); - region.addTriangles(triangles); - - ArrayList vertices = outlineShape.getVertices(); - for(Vertex vert:vertices){ - vert.setId(numVertices++); - } - region.addVertices(vertices); - } - - region.update(); - return region; - } - - - /** Render outline in 3D space at the position provided - * the triangles of the shapes will be generated, if not yet generated - * @param outlineShape the OutlineShape to Render. - * @param position the initial translation of the outlineShape. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - int hashCode = getHashCode(outlineShape); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShape); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - /** Render a list of Outline shapes combined in one region - * at the position provided the triangles of the - * shapes will be generated, if not yet generated - * @param outlineShapes the list of OutlineShapes to Render. - * @param position the initial translation of the outlineShapes. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - - int hashCode = getHashCode(outlineShapes); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShapes); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - private int getHashCode(OutlineShape outlineShape){ - return outlineShape.hashCode(); - } - - private int getHashCode(OutlineShape[] outlineShapes){ - int hashcode = 0; - for(OutlineShape outlineShape:outlineShapes){ - hashcode += getHashCode(outlineShape); - } - return hashcode; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void clearCached() { - Iterator iterator = regions.values().iterator(); - while(iterator.hasNext()){ - Region region = iterator.next(); - region.destroy(); - } - regions.clear(); - } -} diff --git a/src/com/jogamp/graph/curve/HwTextRenderer.java b/src/com/jogamp/graph/curve/HwTextRenderer.java deleted file mode 100644 index f3a15975a..000000000 --- a/src/com/jogamp/graph/curve/HwTextRenderer.java +++ /dev/null @@ -1,358 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve; - -import java.nio.FloatBuffer; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import jogamp.graph.curve.text.GlyphString; -import jogamp.graph.font.FontInt; -import jogamp.graph.geom.plane.AffineTransform; -import jogamp.graph.geom.plane.Path2D; - -import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.opengl.SVertex; -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class HwTextRenderer { - protected static final boolean DEBUG = Debug.debug("TextRenderer"); - static final boolean FONTTOOL_CUSTOM = false; - - private ShaderState st = new ShaderState(); - - private PMVMatrix pmvMatrix = new PMVMatrix(); - private GLUniformData mgl_PMVMatrix; - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); - private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); - private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); - private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); - - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private HashMap strings = new HashMap(); - private final Vertex.Factory pointFactory; - - int win_width = 0; - int win_height = 0; - - /** - * Create a Hardware accelerated Text Renderer. - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public HwTextRenderer(Vertex.Factory factory, int type) { - this.pointFactory = (null != factory) ? factory : SVertex.factory(); - this.regionType = type; - } - - /** - * Initialize shaders and bindings for GPU based text Rendering, - * should be called only once. - * Leaves the renderer enables, ie ShaderState on. - * - * @param drawable the current drawable - * @param shapvalue shaprness around the off-curve vertices - * @return true if init succeeded, false otherwise - */ - public boolean init(GL2ES2 gl){ - if(initialized){ - if(DEBUG) { - System.err.println("HWTextRenderer: Already initialized!"); - } - return true; - } - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWTextRenderer: Couldn't link program: "+sp); - } - - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(null); - - mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.glUniform(gl, mgl_PMVMatrix)) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_sharpness)) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_alpha)) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_color)) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_strength)) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - if(DEBUG) { - System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public void dispose(GL2ES2 gl) { - st.destroy(gl); - clearCached(); - } - - public float getAlpha() { - return mgl_alpha.floatValue(); - } - - public ShaderState getShaderState() { - return st; - } - - public void setAlpha(GL2ES2 gl, float alpha_t) { - mgl_alpha.setData(alpha_t); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_alpha); - } - } - - public void setColor(GL2ES2 gl, float r, float g, float b){ - FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); - fb.put(0, r); - fb.put(1, r); - fb.put(2, r); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_color); - } - } - - public final PMVMatrix matrix() { return pmvMatrix; } - - public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - public void translate(GL2ES2 gl, float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void resetMatrix(GL2ES2 gl){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void setMatrix(GL2ES2 gl){ - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void updateAllShaderValues(GL2ES2 gl) { - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - st.glUniform(gl, mgl_alpha); - st.glUniform(gl, mgl_color); - st.glUniform(gl, mgl_strength); - } - } - - /** - * @param gl - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ - win_width = width; - win_height = height; - float ratio = (float)width/(float)height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } - - public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { - win_width = width; - win_height = height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glOrthof(0, width, 0, height, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } - - private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { - AffineTransform affineTransform = new AffineTransform(pointFactory); - - Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getOutline(str, size, affineTransform, paths); - - GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); - glyphString.createfromFontPath(paths, affineTransform); - - glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); - return glyphString; - } - - - public void enable(GL2ES2 gl, boolean enable) { - if(null != gl) { - st.glUseProgram(gl, enable); - } - } - - /** Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated - * @param font font to be used - * @param str text to be rendered - * @param position the lower left corner of the string - * @param fontSize font size - * @param texSize texture size for multipass render - * @throws Exception if TextRenderer not initialized - */ - public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { - if(!initialized){ - throw new GLException("HWTextRenderer: not initialized!"); - } - String fontStrHash = getTextHashCode(font, str, fontSize); - GlyphString glyphString = strings.get(fontStrHash); - if(null == glyphString) { - glyphString = createString(gl, font, fontSize, str); - strings.put(fontStrHash, glyphString); - } - - glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); - } - - private String getTextHashCode(Font font, String str, int fontSize) { - // FIXME: use integer hash code - return font.getName() + "." + str.hashCode() + "." + fontSize; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void clearCached() { - Iterator iterator = strings.values().iterator(); - while(iterator.hasNext()){ - GlyphString glyphString = iterator.next(); - glyphString.destroy(); - } - strings.clear(); - } -} diff --git a/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java b/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java new file mode 100755 index 000000000..9fa67a0be --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java @@ -0,0 +1,388 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.RegionFactory; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex; + +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class HwRegionRenderer { + protected static final boolean DEBUG = Debug.debug("RegionRenderer"); + + private ShaderState st; + private PMVMatrix pmvMatrix = new PMVMatrix(); + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private float sharpness = 0.5f; + private float alpha = 1.0f; + private float strength = 3.0f; + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private GLContext context; + private FloatBuffer color = FloatBuffer.allocate(3); + private HashMap regions = new HashMap(); + + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public HwRegionRenderer(GLContext context) { + this.context = context; + init(context, 0.5f); + } + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param type region type (single or multipass) + */ + public HwRegionRenderer(GLContext context, int type) { + this.context = context; + this.regionType = type; + init(context, 0.5f); + } + + private boolean init(GLContext context, float sharpvalue){ + if(initialized){ + if(DEBUG) { + System.err.println("HWRegionRenderer: Already initialized!"); + } + return true; + } + sharpness = sharpvalue; + + GL2ES2 gl = context.getGL().getGL2ES2(); + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.setSwapInterval(1); + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + initShader(gl); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + st.glUseProgram(gl, false); + + if(DEBUG) { + System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public float getAlpha() { + return alpha; + } + public void setAlpha(float alpha_t) { + alpha = alpha_t; + } + + public void setColor(float r, float g, float b){ + color.put(r); + color.put(g); + color.put(b); + color.rewind(); + } + + public void rotate(float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + } + public void translate(float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + } + + public void resetMatrix(){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + } + + /** + * @param drawable + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null==st) { + if(DEBUG){ + System.err.println("HWRegionRenderer: Shader State is null, or not"); + } + return false; + } + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + st.glUseProgram(gl, false); + return true; + } + + private void initShader(GL2ES2 gl) { + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwRegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwRegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); + } + + st = new ShaderState(); + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + } + + private Region createRegion(OutlineShape outlineShape) { + Region region = RegionFactory.create(context, st, regionType); + + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList vertices = (ArrayList) outlineShape.getVertices(); + region.addVertices(vertices); + region.addTriangles(triangles); + + region.update(); + return region; + } + + private Region createRegion(OutlineShape[] outlineShapes) { + Region region = RegionFactory.create(context, st, regionType); + + int numVertices = region.getNumVertices(); + + for(OutlineShape outlineShape:outlineShapes){ + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = outlineShape.triangulate(sharpness); + region.addTriangles(triangles); + + ArrayList vertices = outlineShape.getVertices(); + for(Vertex vert:vertices){ + vert.setId(numVertices++); + } + region.addVertices(vertices); + } + + region.update(); + return region; + } + + + /** Render outline in 3D space at the position provided + * the triangles of the shapes will be generated, if not yet generated + * @param outlineShape the OutlineShape to Render. + * @param position the initial translation of the outlineShape. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + int hashCode = getHashCode(outlineShape); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShape); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + /** Render a list of Outline shapes combined in one region + * at the position provided the triangles of the + * shapes will be generated, if not yet generated + * @param outlineShapes the list of OutlineShapes to Render. + * @param position the initial translation of the outlineShapes. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + + int hashCode = getHashCode(outlineShapes); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShapes); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + private int getHashCode(OutlineShape outlineShape){ + return outlineShape.hashCode(); + } + + private int getHashCode(OutlineShape[] outlineShapes){ + int hashcode = 0; + for(OutlineShape outlineShape:outlineShapes){ + hashcode += getHashCode(outlineShape); + } + return hashcode; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void clearCached() { + Iterator iterator = regions.values().iterator(); + while(iterator.hasNext()){ + Region region = iterator.next(); + region.destroy(); + } + regions.clear(); + } +} diff --git a/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java b/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java new file mode 100644 index 000000000..f9a104ad0 --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java @@ -0,0 +1,353 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.graph.curve.text.GlyphString; +import jogamp.graph.font.FontInt; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class HwTextRenderer { + protected static final boolean DEBUG = Debug.debug("TextRenderer"); + static final boolean FONTTOOL_CUSTOM = false; + + private ShaderState st = new ShaderState(); + + private PMVMatrix pmvMatrix = new PMVMatrix(); + private GLUniformData mgl_PMVMatrix; + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); + + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private HashMap strings = new HashMap(); + private final Vertex.Factory pointFactory; + + int win_width = 0; + int win_height = 0; + + /** + * Create a Hardware accelerated Text Renderer. + * @param context OpenGL rendering context + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public HwTextRenderer(Vertex.Factory factory, int type) { + this.pointFactory = (null != factory) ? factory : SVertex.factory(); + this.regionType = type; + } + + /** + * Initialize shaders and bindings for GPU based text Rendering, + * should be called only once. + * Leaves the renderer enables, ie ShaderState on. + * + * @param drawable the current drawable + * @param shapvalue shaprness around the off-curve vertices + * @return true if init succeeded, false otherwise + */ + public boolean init(GL2ES2 gl){ + if(initialized){ + if(DEBUG) { + System.err.println("HWTextRenderer: Already initialized!"); + } + return true; + } + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, + "shader", "shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, + "shader", "shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWTextRenderer: Couldn't link program: "+sp); + } + + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_sharpness)) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_alpha)) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_color)) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_strength)) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + if(DEBUG) { + System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public void dispose(GL2ES2 gl) { + st.destroy(gl); + flushCash(); + } + + public float getAlpha() { + return mgl_alpha.floatValue(); + } + + public ShaderState getShaderState() { + return st; + } + + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } + } + + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + public final PMVMatrix matrix() { return pmvMatrix; } + + public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + public void translate(GL2ES2 gl, float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void resetMatrix(GL2ES2 gl){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void setMatrix(GL2ES2 gl){ + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void updateAllShaderValues(GL2ES2 gl) { + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + st.glUniform(gl, mgl_alpha); + st.glUniform(gl, mgl_color); + st.glUniform(gl, mgl_strength); + } + } + + /** + * @param gl + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ + win_width = width; + win_height = height; + float ratio = (float)width/(float)height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + + public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { + win_width = width; + win_height = height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0, width, 0, height, near, far); + + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + + private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { + AffineTransform affineTransform = new AffineTransform(pointFactory); + + Path2D[] paths = new Path2D[str.length()]; + ((FontInt)font).getOutline(str, size, affineTransform, paths); + + GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); + glyphString.createfromFontPath(paths, affineTransform); + + glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); + return glyphString; + } + + + /** Render the String in 3D space wrt to the font provided at the position provided + * the outlines will be generated, if not yet generated + * @param font font to be used + * @param str text to be rendered + * @param position the lower left corner of the string + * @param fontSize font size + * @param texSize texture size for multipass render + * @throws Exception if TextRenderer not initialized + */ + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { + if(!initialized){ + throw new GLException("HWTextRenderer: not initialized!"); + } + String fontStrHash = getTextHashCode(font, str, fontSize); + GlyphString glyphString = strings.get(fontStrHash); + if(null == glyphString) { + glyphString = createString(gl, font, fontSize, str); + strings.put(fontStrHash, glyphString); + } + + glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); + } + + private String getTextHashCode(Font font, String str, int fontSize) { + // FIXME: use integer hash code + return font.getName() + "." + str.hashCode() + "." + fontSize; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void flushCash() { + Iterator iterator = strings.values().iterator(); + while(iterator.hasNext()){ + GlyphString glyphString = iterator.next(); + glyphString.destroy(); + } + strings.clear(); + } +} diff --git a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp new file mode 100644 index 000000000..2b3a0ce1d --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp @@ -0,0 +1,99 @@ +//#version 100 + +uniform float p1y; +uniform float g_alpha; +uniform vec3 g_color; +uniform float a_strength; + +varying vec2 v_texCoord; + +vec3 b_color = vec3(0.0, 0.0, 0.0); + +uniform sampler2D texture; +vec4 weights = vec4(0.075, 0.06, 0.045, 0.025); + +void main (void) +{ + vec2 rtex = vec2(abs(v_texCoord.x),abs(v_texCoord.y)); + vec3 c = g_color; + + float alpha = 0.0; + + if((v_texCoord.x == 0.0) && (v_texCoord.y == 0.0)){ + alpha = g_alpha; + } + else if((v_texCoord.x >= 5.0)){ + vec2 dfx = dFdx(v_texCoord); + vec2 dfy = dFdy(v_texCoord); + + vec2 size = 1.0/textureSize(texture,0); //version 130 + rtex -= 5.0; + vec4 t = texture2D(texture, rtex)* 0.18; + + t += texture2D(texture, rtex + size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex + size*(vec2(0, 1)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(0, 1)))*weights.x; + + t += texture2D(texture, rtex + 2.0*size*(vec2(1, 0))) *weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(1, 0)))*weights.y; + t += texture2D(texture, rtex + 2.0*size*(vec2(0, 1)))*weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(0, 1)))*weights.y; + + t += texture2D(texture, rtex + 3.0*size*(vec2(1, 0))) *weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(1, 0)))*weights.z; + t += texture2D(texture, rtex + 3.0*size*(vec2(0, 1)))*weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(0, 1)))*weights.z; + + t += texture2D(texture, rtex + 4.0*size*(vec2(1, 0))) *weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(1, 0)))*weights.w; + t += texture2D(texture, rtex + 4.0*size*(vec2(0, 1)))*weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(0, 1)))*weights.w; + + if(t.w == 0.0){ + discard; + } + + c = t.xyz; + alpha = g_alpha* t.w; + } + /////////////////////////////////////////////////////////// + else if ((v_texCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)){ + vec2 dtx = dFdx(rtex); + vec2 dty = dFdy(rtex); + + rtex.y -= 0.1; + if(rtex.y < 0.0) { + if(v_texCoord.y < 0.0) + discard; + else{ + rtex.y = 0.0; + } + } + + vec2 f = vec2((dtx.y - 2.0*p1y*dtx.x + 4.0*p1y*rtex.x*dtx.x), (dty.y - 2.0*p1y*dty.x + 4.0*p1y*rtex.x*dty.x)); + + float position = rtex.y - ((2.0 * rtex.x * p1y) * (1.0 - rtex.x)); + float d = position/(length(f)); + + float a = (0.5 - d * sign(v_texCoord.y)); + + + if (a >= 1.0) { + alpha = g_alpha; + // c = vec3(1.0,1.0,1.0); + } + else if (a <= 0.0) { + alpha = 0.0;//discard; + // c = vec3(0.0,0.0,0.0); + + } + else { + alpha = g_alpha*a; + // c = vec3(a,a,a); + mix(b_color,g_color, a); + } + } + + gl_FragColor = vec4(c, alpha); +} diff --git a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp new file mode 100644 index 000000000..bc9ecb41e --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp @@ -0,0 +1,13 @@ +//#version 100 + +uniform mat4 mgl_PMVMatrix[2]; +attribute vec4 v_position; +attribute vec2 texCoord; + +varying vec2 v_texCoord; + +void main(void) +{ + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * v_position; + v_texCoord = texCoord.st; +} \ No newline at end of file diff --git a/src/com/jogamp/graph/curve/shader/curverenderer.fp b/src/com/jogamp/graph/curve/shader/curverenderer.fp deleted file mode 100644 index 2b3a0ce1d..000000000 --- a/src/com/jogamp/graph/curve/shader/curverenderer.fp +++ /dev/null @@ -1,99 +0,0 @@ -//#version 100 - -uniform float p1y; -uniform float g_alpha; -uniform vec3 g_color; -uniform float a_strength; - -varying vec2 v_texCoord; - -vec3 b_color = vec3(0.0, 0.0, 0.0); - -uniform sampler2D texture; -vec4 weights = vec4(0.075, 0.06, 0.045, 0.025); - -void main (void) -{ - vec2 rtex = vec2(abs(v_texCoord.x),abs(v_texCoord.y)); - vec3 c = g_color; - - float alpha = 0.0; - - if((v_texCoord.x == 0.0) && (v_texCoord.y == 0.0)){ - alpha = g_alpha; - } - else if((v_texCoord.x >= 5.0)){ - vec2 dfx = dFdx(v_texCoord); - vec2 dfy = dFdy(v_texCoord); - - vec2 size = 1.0/textureSize(texture,0); //version 130 - rtex -= 5.0; - vec4 t = texture2D(texture, rtex)* 0.18; - - t += texture2D(texture, rtex + size*(vec2(1, 0)))*weights.x; - t += texture2D(texture, rtex - size*(vec2(1, 0)))*weights.x; - t += texture2D(texture, rtex + size*(vec2(0, 1)))*weights.x; - t += texture2D(texture, rtex - size*(vec2(0, 1)))*weights.x; - - t += texture2D(texture, rtex + 2.0*size*(vec2(1, 0))) *weights.y; - t += texture2D(texture, rtex - 2.0*size*(vec2(1, 0)))*weights.y; - t += texture2D(texture, rtex + 2.0*size*(vec2(0, 1)))*weights.y; - t += texture2D(texture, rtex - 2.0*size*(vec2(0, 1)))*weights.y; - - t += texture2D(texture, rtex + 3.0*size*(vec2(1, 0))) *weights.z; - t += texture2D(texture, rtex - 3.0*size*(vec2(1, 0)))*weights.z; - t += texture2D(texture, rtex + 3.0*size*(vec2(0, 1)))*weights.z; - t += texture2D(texture, rtex - 3.0*size*(vec2(0, 1)))*weights.z; - - t += texture2D(texture, rtex + 4.0*size*(vec2(1, 0))) *weights.w; - t += texture2D(texture, rtex - 4.0*size*(vec2(1, 0)))*weights.w; - t += texture2D(texture, rtex + 4.0*size*(vec2(0, 1)))*weights.w; - t += texture2D(texture, rtex - 4.0*size*(vec2(0, 1)))*weights.w; - - if(t.w == 0.0){ - discard; - } - - c = t.xyz; - alpha = g_alpha* t.w; - } - /////////////////////////////////////////////////////////// - else if ((v_texCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)){ - vec2 dtx = dFdx(rtex); - vec2 dty = dFdy(rtex); - - rtex.y -= 0.1; - if(rtex.y < 0.0) { - if(v_texCoord.y < 0.0) - discard; - else{ - rtex.y = 0.0; - } - } - - vec2 f = vec2((dtx.y - 2.0*p1y*dtx.x + 4.0*p1y*rtex.x*dtx.x), (dty.y - 2.0*p1y*dty.x + 4.0*p1y*rtex.x*dty.x)); - - float position = rtex.y - ((2.0 * rtex.x * p1y) * (1.0 - rtex.x)); - float d = position/(length(f)); - - float a = (0.5 - d * sign(v_texCoord.y)); - - - if (a >= 1.0) { - alpha = g_alpha; - // c = vec3(1.0,1.0,1.0); - } - else if (a <= 0.0) { - alpha = 0.0;//discard; - // c = vec3(0.0,0.0,0.0); - - } - else { - alpha = g_alpha*a; - // c = vec3(a,a,a); - mix(b_color,g_color, a); - } - } - - gl_FragColor = vec4(c, alpha); -} diff --git a/src/com/jogamp/graph/curve/shader/curverenderer.vp b/src/com/jogamp/graph/curve/shader/curverenderer.vp deleted file mode 100644 index bc9ecb41e..000000000 --- a/src/com/jogamp/graph/curve/shader/curverenderer.vp +++ /dev/null @@ -1,13 +0,0 @@ -//#version 100 - -uniform mat4 mgl_PMVMatrix[2]; -attribute vec4 v_position; -attribute vec2 texCoord; - -varying vec2 v_texCoord; - -void main(void) -{ - gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * v_position; - v_texCoord = texCoord.st; -} \ No newline at end of file diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java index cde4df683..e2e47709e 100755 --- a/src/demo/GPURegionNewtDemo01.java +++ b/src/demo/GPURegionNewtDemo01.java @@ -35,8 +35,8 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; -import com.jogamp.graph.curve.HwRegionRenderer; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.HwRegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index f9d7bb944..0d9ad3f63 100755 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -35,8 +35,8 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; -import com.jogamp.graph.curve.HwRegionRenderer; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.HwRegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index eee1efbdb..25805d530 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -41,7 +41,7 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLRunnable; -import com.jogamp.graph.curve.HwTextRenderer; +import com.jogamp.graph.curve.opengl.HwTextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.Vertex; -- cgit v1.2.3 From e952e7dbac7a6b746b8465aa63423f1aa138ca27 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 07:28:56 +0200 Subject: Renamed Hw*Renderer -> *Renderer --- .../graph/curve/opengl/HwRegionRenderer.java | 388 --------------------- .../jogamp/graph/curve/opengl/HwTextRenderer.java | 353 ------------------- .../jogamp/graph/curve/opengl/RegionRenderer.java | 388 +++++++++++++++++++++ .../jogamp/graph/curve/opengl/TextRenderer.java | 353 +++++++++++++++++++ src/demo/GPURegionNewtDemo01.java | 6 +- src/demo/GPURegionNewtDemo02.java | 6 +- src/demo/GPUTextGLListenerBase01.java | 6 +- .../test/junit/graph/TestHwTextRenderer01.java | 159 --------- .../test/junit/graph/TestTextRenderer01.java | 159 +++++++++ 9 files changed, 909 insertions(+), 909 deletions(-) delete mode 100755 src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java delete mode 100644 src/com/jogamp/graph/curve/opengl/HwTextRenderer.java create mode 100755 src/com/jogamp/graph/curve/opengl/RegionRenderer.java create mode 100644 src/com/jogamp/graph/curve/opengl/TextRenderer.java delete mode 100755 src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java create mode 100755 src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java diff --git a/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java b/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java deleted file mode 100755 index 9fa67a0be..000000000 --- a/src/com/jogamp/graph/curve/opengl/HwRegionRenderer.java +++ /dev/null @@ -1,388 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve.opengl; - -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.RegionFactory; -import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.Vertex; - -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class HwRegionRenderer { - protected static final boolean DEBUG = Debug.debug("RegionRenderer"); - - private ShaderState st; - private PMVMatrix pmvMatrix = new PMVMatrix(); - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private float sharpness = 0.5f; - private float alpha = 1.0f; - private float strength = 3.0f; - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private GLContext context; - private FloatBuffer color = FloatBuffer.allocate(3); - private HashMap regions = new HashMap(); - - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public HwRegionRenderer(GLContext context) { - this.context = context; - init(context, 0.5f); - } - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param type region type (single or multipass) - */ - public HwRegionRenderer(GLContext context, int type) { - this.context = context; - this.regionType = type; - init(context, 0.5f); - } - - private boolean init(GLContext context, float sharpvalue){ - if(initialized){ - if(DEBUG) { - System.err.println("HWRegionRenderer: Already initialized!"); - } - return true; - } - sharpness = sharpvalue; - - GL2ES2 gl = context.getGL().getGL2ES2(); - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.setSwapInterval(1); - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - initShader(gl); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(); - - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - st.glUseProgram(gl, false); - - if(DEBUG) { - System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public float getAlpha() { - return alpha; - } - public void setAlpha(float alpha_t) { - alpha = alpha_t; - } - - public void setColor(float r, float g, float b){ - color.put(r); - color.put(g); - color.put(b); - color.rewind(); - } - - public void rotate(float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - } - public void translate(float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - } - - public void resetMatrix(){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - } - - /** - * @param drawable - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null==st) { - if(DEBUG){ - System.err.println("HWRegionRenderer: Shader State is null, or not"); - } - return false; - } - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - st.glUseProgram(gl, false); - return true; - } - - private void initShader(GL2ES2 gl) { - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwRegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwRegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); - } - - st = new ShaderState(); - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - } - - private Region createRegion(OutlineShape outlineShape) { - Region region = RegionFactory.create(context, st, regionType); - - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); - ArrayList vertices = (ArrayList) outlineShape.getVertices(); - region.addVertices(vertices); - region.addTriangles(triangles); - - region.update(); - return region; - } - - private Region createRegion(OutlineShape[] outlineShapes) { - Region region = RegionFactory.create(context, st, regionType); - - int numVertices = region.getNumVertices(); - - for(OutlineShape outlineShape:outlineShapes){ - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = outlineShape.triangulate(sharpness); - region.addTriangles(triangles); - - ArrayList vertices = outlineShape.getVertices(); - for(Vertex vert:vertices){ - vert.setId(numVertices++); - } - region.addVertices(vertices); - } - - region.update(); - return region; - } - - - /** Render outline in 3D space at the position provided - * the triangles of the shapes will be generated, if not yet generated - * @param outlineShape the OutlineShape to Render. - * @param position the initial translation of the outlineShape. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - int hashCode = getHashCode(outlineShape); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShape); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - /** Render a list of Outline shapes combined in one region - * at the position provided the triangles of the - * shapes will be generated, if not yet generated - * @param outlineShapes the list of OutlineShapes to Render. - * @param position the initial translation of the outlineShapes. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - - int hashCode = getHashCode(outlineShapes); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShapes); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - private int getHashCode(OutlineShape outlineShape){ - return outlineShape.hashCode(); - } - - private int getHashCode(OutlineShape[] outlineShapes){ - int hashcode = 0; - for(OutlineShape outlineShape:outlineShapes){ - hashcode += getHashCode(outlineShape); - } - return hashcode; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void clearCached() { - Iterator iterator = regions.values().iterator(); - while(iterator.hasNext()){ - Region region = iterator.next(); - region.destroy(); - } - regions.clear(); - } -} diff --git a/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java b/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java deleted file mode 100644 index f9a104ad0..000000000 --- a/src/com/jogamp/graph/curve/opengl/HwTextRenderer.java +++ /dev/null @@ -1,353 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve.opengl; - -import java.nio.FloatBuffer; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import jogamp.graph.curve.text.GlyphString; -import jogamp.graph.font.FontInt; -import jogamp.graph.geom.plane.AffineTransform; -import jogamp.graph.geom.plane.Path2D; - -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.opengl.SVertex; -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class HwTextRenderer { - protected static final boolean DEBUG = Debug.debug("TextRenderer"); - static final boolean FONTTOOL_CUSTOM = false; - - private ShaderState st = new ShaderState(); - - private PMVMatrix pmvMatrix = new PMVMatrix(); - private GLUniformData mgl_PMVMatrix; - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); - private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); - private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); - private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); - - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private HashMap strings = new HashMap(); - private final Vertex.Factory pointFactory; - - int win_width = 0; - int win_height = 0; - - /** - * Create a Hardware accelerated Text Renderer. - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public HwTextRenderer(Vertex.Factory factory, int type) { - this.pointFactory = (null != factory) ? factory : SVertex.factory(); - this.regionType = type; - } - - /** - * Initialize shaders and bindings for GPU based text Rendering, - * should be called only once. - * Leaves the renderer enables, ie ShaderState on. - * - * @param drawable the current drawable - * @param shapvalue shaprness around the off-curve vertices - * @return true if init succeeded, false otherwise - */ - public boolean init(GL2ES2 gl){ - if(initialized){ - if(DEBUG) { - System.err.println("HWTextRenderer: Already initialized!"); - } - return true; - } - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, HwTextRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, HwTextRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWTextRenderer: Couldn't link program: "+sp); - } - - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(null); - - mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.glUniform(gl, mgl_PMVMatrix)) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_sharpness)) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_alpha)) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_color)) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_strength)) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - if(DEBUG) { - System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public void dispose(GL2ES2 gl) { - st.destroy(gl); - flushCash(); - } - - public float getAlpha() { - return mgl_alpha.floatValue(); - } - - public ShaderState getShaderState() { - return st; - } - - public void setAlpha(GL2ES2 gl, float alpha_t) { - mgl_alpha.setData(alpha_t); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_alpha); - } - } - - public void setColor(GL2ES2 gl, float r, float g, float b){ - FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); - fb.put(0, r); - fb.put(1, r); - fb.put(2, r); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_color); - } - } - - public final PMVMatrix matrix() { return pmvMatrix; } - - public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - public void translate(GL2ES2 gl, float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void resetMatrix(GL2ES2 gl){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void setMatrix(GL2ES2 gl){ - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void updateAllShaderValues(GL2ES2 gl) { - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - st.glUniform(gl, mgl_alpha); - st.glUniform(gl, mgl_color); - st.glUniform(gl, mgl_strength); - } - } - - /** - * @param gl - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ - win_width = width; - win_height = height; - float ratio = (float)width/(float)height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } - - public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { - win_width = width; - win_height = height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glOrthof(0, width, 0, height, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } - - private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { - AffineTransform affineTransform = new AffineTransform(pointFactory); - - Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getOutline(str, size, affineTransform, paths); - - GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); - glyphString.createfromFontPath(paths, affineTransform); - - glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); - return glyphString; - } - - - /** Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated - * @param font font to be used - * @param str text to be rendered - * @param position the lower left corner of the string - * @param fontSize font size - * @param texSize texture size for multipass render - * @throws Exception if TextRenderer not initialized - */ - public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { - if(!initialized){ - throw new GLException("HWTextRenderer: not initialized!"); - } - String fontStrHash = getTextHashCode(font, str, fontSize); - GlyphString glyphString = strings.get(fontStrHash); - if(null == glyphString) { - glyphString = createString(gl, font, fontSize, str); - strings.put(fontStrHash, glyphString); - } - - glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); - } - - private String getTextHashCode(Font font, String str, int fontSize) { - // FIXME: use integer hash code - return font.getName() + "." + str.hashCode() + "." + fontSize; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void flushCash() { - Iterator iterator = strings.values().iterator(); - while(iterator.hasNext()){ - GlyphString glyphString = iterator.next(); - glyphString.destroy(); - } - strings.clear(); - } -} diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java new file mode 100755 index 000000000..e75ca25cd --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -0,0 +1,388 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.RegionFactory; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex; + +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class RegionRenderer { + protected static final boolean DEBUG = Debug.debug("RegionRenderer"); + + private ShaderState st; + private PMVMatrix pmvMatrix = new PMVMatrix(); + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private float sharpness = 0.5f; + private float alpha = 1.0f; + private float strength = 3.0f; + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private GLContext context; + private FloatBuffer color = FloatBuffer.allocate(3); + private HashMap regions = new HashMap(); + + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public RegionRenderer(GLContext context) { + this.context = context; + init(context, 0.5f); + } + /** Create a Hardware accelerated Region Renderer + * @param context OpenGL rendering context + * @param type region type (single or multipass) + */ + public RegionRenderer(GLContext context, int type) { + this.context = context; + this.regionType = type; + init(context, 0.5f); + } + + private boolean init(GLContext context, float sharpvalue){ + if(initialized){ + if(DEBUG) { + System.err.println("HWRegionRenderer: Already initialized!"); + } + return true; + } + sharpness = sharpvalue; + + GL2ES2 gl = context.getGL().getGL2ES2(); + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.setSwapInterval(1); + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + initShader(gl); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + st.glUseProgram(gl, false); + + if(DEBUG) { + System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public float getAlpha() { + return alpha; + } + public void setAlpha(float alpha_t) { + alpha = alpha_t; + } + + public void setColor(float r, float g, float b){ + color.put(r); + color.put(g); + color.put(b); + color.rewind(); + } + + public void rotate(float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + } + public void translate(float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + } + + public void resetMatrix(){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + } + + /** + * @param drawable + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null==st) { + if(DEBUG){ + System.err.println("HWRegionRenderer: Shader State is null, or not"); + } + return false; + } + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + st.glUseProgram(gl, false); + return true; + } + + private void initShader(GL2ES2 gl) { + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RegionRenderer.class, + "shader", "shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); + } + + st = new ShaderState(); + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + } + + private Region createRegion(OutlineShape outlineShape) { + Region region = RegionFactory.create(context, st, regionType); + + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList vertices = (ArrayList) outlineShape.getVertices(); + region.addVertices(vertices); + region.addTriangles(triangles); + + region.update(); + return region; + } + + private Region createRegion(OutlineShape[] outlineShapes) { + Region region = RegionFactory.create(context, st, regionType); + + int numVertices = region.getNumVertices(); + + for(OutlineShape outlineShape:outlineShapes){ + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = outlineShape.triangulate(sharpness); + region.addTriangles(triangles); + + ArrayList vertices = outlineShape.getVertices(); + for(Vertex vert:vertices){ + vert.setId(numVertices++); + } + region.addVertices(vertices); + } + + region.update(); + return region; + } + + + /** Render outline in 3D space at the position provided + * the triangles of the shapes will be generated, if not yet generated + * @param outlineShape the OutlineShape to Render. + * @param position the initial translation of the outlineShape. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + int hashCode = getHashCode(outlineShape); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShape); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + /** Render a list of Outline shapes combined in one region + * at the position provided the triangles of the + * shapes will be generated, if not yet generated + * @param outlineShapes the list of OutlineShapes to Render. + * @param position the initial translation of the outlineShapes. + * @throws Exception if HwRegionRenderer not initialized + */ + public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ + if(!initialized){ + throw new Exception("HWRegionRenderer: not initialized!"); + } + + int hashCode = getHashCode(outlineShapes); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(outlineShapes); + regions.put(hashCode, region); + } + + GL2ES2 gl = context.getGL().getGL2ES2(); + st.glUseProgram(gl, true); + GLUniformData ud = st.getUniform("mgl_PMVMatrix"); + if(null!=ud) { + st.glUniform(gl, ud); + } + if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { + System.err.println("Error setting global alpha in shader: "+st); + } + GLUniformData gcolorUD = st.getUniform("g_color"); + if(null!=gcolorUD) { + st.glUniform(gl, gcolorUD); + } + if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { + System.err.println("Error setting antialias strength in shader: "+st); + } + region.render(null, 0, 0, 0); + st.glUseProgram(gl, false); + } + + private int getHashCode(OutlineShape outlineShape){ + return outlineShape.hashCode(); + } + + private int getHashCode(OutlineShape[] outlineShapes){ + int hashcode = 0; + for(OutlineShape outlineShape:outlineShapes){ + hashcode += getHashCode(outlineShape); + } + return hashcode; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void clearCached() { + Iterator iterator = regions.values().iterator(); + while(iterator.hasNext()){ + Region region = iterator.next(); + region.destroy(); + } + regions.clear(); + } +} diff --git a/src/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/com/jogamp/graph/curve/opengl/TextRenderer.java new file mode 100644 index 000000000..703f82373 --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -0,0 +1,353 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.graph.curve.text.GlyphString; +import jogamp.graph.font.FontInt; +import jogamp.graph.geom.plane.AffineTransform; +import jogamp.graph.geom.plane.Path2D; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; +import jogamp.opengl.Debug; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class TextRenderer { + protected static final boolean DEBUG = Debug.debug("TextRenderer"); + static final boolean FONTTOOL_CUSTOM = false; + + private ShaderState st = new ShaderState(); + + private PMVMatrix pmvMatrix = new PMVMatrix(); + private GLUniformData mgl_PMVMatrix; + + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); + + private boolean initialized = false; + + private int regionType = Region.SINGLE_PASS; + + private HashMap strings = new HashMap(); + private final Vertex.Factory pointFactory; + + int win_width = 0; + int win_height = 0; + + /** + * Create a Hardware accelerated Text Renderer. + * @param context OpenGL rendering context + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public TextRenderer(Vertex.Factory factory, int type) { + this.pointFactory = (null != factory) ? factory : SVertex.factory(); + this.regionType = type; + } + + /** + * Initialize shaders and bindings for GPU based text Rendering, + * should be called only once. + * Leaves the renderer enables, ie ShaderState on. + * + * @param drawable the current drawable + * @param shapvalue shaprness around the off-curve vertices + * @return true if init succeeded, false otherwise + */ + public boolean init(GL2ES2 gl){ + if(initialized){ + if(DEBUG) { + System.err.println("HWTextRenderer: Already initialized!"); + } + return true; + } + + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, TextRenderer.class, + "shader", "shader/bin", "curverenderer"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, TextRenderer.class, + "shader", "shader/bin", "curverenderer"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("HWTextRenderer: Couldn't link program: "+sp); + } + + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetMatrix(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_sharpness)) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_alpha)) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_color)) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_strength)) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + if(DEBUG) { + System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); + } + initialized = true; + return true; + } + + public void dispose(GL2ES2 gl) { + st.destroy(gl); + flushCash(); + } + + public float getAlpha() { + return mgl_alpha.floatValue(); + } + + public ShaderState getShaderState() { + return st; + } + + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } + } + + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + public final PMVMatrix matrix() { return pmvMatrix; } + + public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ + pmvMatrix.glRotatef(angle, x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + public void translate(GL2ES2 gl, float x, float y, float z){ + pmvMatrix.glTranslatef(x, y, z); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void resetMatrix(GL2ES2 gl){ + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void setMatrix(GL2ES2 gl){ + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void updateAllShaderValues(GL2ES2 gl) { + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + st.glUniform(gl, mgl_alpha); + st.glUniform(gl, mgl_color); + st.glUniform(gl, mgl_strength); + } + } + + /** + * @param gl + * @param angle + * @param ratio + * @param near + * @param far + * @return + */ + public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ + win_width = width; + win_height = height; + float ratio = (float)width/(float)height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + + public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { + win_width = width; + win_height = height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0, width, 0, height, near, far); + + if(null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + + private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { + AffineTransform affineTransform = new AffineTransform(pointFactory); + + Path2D[] paths = new Path2D[str.length()]; + ((FontInt)font).getOutline(str, size, affineTransform, paths); + + GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); + glyphString.createfromFontPath(paths, affineTransform); + + glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); + return glyphString; + } + + + /** Render the String in 3D space wrt to the font provided at the position provided + * the outlines will be generated, if not yet generated + * @param font font to be used + * @param str text to be rendered + * @param position the lower left corner of the string + * @param fontSize font size + * @param texSize texture size for multipass render + * @throws Exception if TextRenderer not initialized + */ + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { + if(!initialized){ + throw new GLException("HWTextRenderer: not initialized!"); + } + String fontStrHash = getTextHashCode(font, str, fontSize); + GlyphString glyphString = strings.get(fontStrHash); + if(null == glyphString) { + glyphString = createString(gl, font, fontSize, str); + strings.put(fontStrHash, glyphString); + } + + glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); + } + + private String getTextHashCode(Font font, String str, int fontSize) { + // FIXME: use integer hash code + return font.getName() + "." + str.hashCode() + "." + fontSize; + } + + /** Clears the cached string curves + * and destorys underlying buffers + */ + public void flushCash() { + Iterator iterator = strings.values().iterator(); + while(iterator.hasNext()){ + GlyphString glyphString = iterator.next(); + glyphString.destroy(); + } + strings.clear(); + } +} diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java index e2e47709e..d58d4148d 100755 --- a/src/demo/GPURegionNewtDemo01.java +++ b/src/demo/GPURegionNewtDemo01.java @@ -36,7 +36,7 @@ import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.opengl.HwRegionRenderer; +import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; @@ -125,7 +125,7 @@ class RegionNewtWindow { animator.start(); } private class RegionGLListener implements GLEventListener{ - HwRegionRenderer regionRenderer = null; + RegionRenderer regionRenderer = null; OutlineShape outlineShape = null; @@ -172,7 +172,7 @@ class RegionNewtWindow { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer = new HwRegionRenderer(drawable.getContext()); + regionRenderer = new RegionRenderer(drawable.getContext()); regionRenderer.setAlpha(1.0f); regionRenderer.setColor(0.0f, 0.0f, 0.0f); //gl.glSampleCoverage(0.95f, false); diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index 0d9ad3f63..19889ac6e 100755 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -36,7 +36,7 @@ import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.opengl.HwRegionRenderer; +import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.event.KeyListener; @@ -120,7 +120,7 @@ class RegionsNewtWindow { animator.start(); } private class RegionGLListener implements GLEventListener{ - HwRegionRenderer regionRenderer = null; + RegionRenderer regionRenderer = null; OutlineShape[] outlineShapes = new OutlineShape[2]; @@ -167,7 +167,7 @@ class RegionsNewtWindow { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer = new HwRegionRenderer(drawable.getContext()); + regionRenderer = new RegionRenderer(drawable.getContext()); regionRenderer.setAlpha(1.0f); regionRenderer.setColor(0.0f, 0.0f, 0.0f); MSAATool.dump(drawable); diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java index 25805d530..238a733ce 100644 --- a/src/demo/GPUTextGLListenerBase01.java +++ b/src/demo/GPUTextGLListenerBase01.java @@ -41,7 +41,7 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLPipelineFactory; import javax.media.opengl.GLRunnable; -import com.jogamp.graph.curve.opengl.HwTextRenderer; +import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.Vertex; @@ -64,7 +64,7 @@ import com.jogamp.opengl.util.awt.Screenshot; */ public abstract class GPUTextGLListenerBase01 implements GLEventListener { Vertex.Factory vfactory; - protected HwTextRenderer textRenderer; + protected TextRenderer textRenderer; int fontSet = FontFactory.UBUNTU; Font font; boolean debug; @@ -100,7 +100,7 @@ public abstract class GPUTextGLListenerBase01 implements GLEventListener { // this.font = FontFactory.get(FontFactory.JAVA).getDefault(); this.font = FontFactory.get(fontSet).getDefault(); this.vfactory = vfactory; - this.textRenderer = new HwTextRenderer(vfactory, mode); + this.textRenderer = new TextRenderer(vfactory, mode); this.debug = debug; this.trace = trace; } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java deleted file mode 100755 index 7f5ee9d98..000000000 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestHwTextRenderer01.java +++ /dev/null @@ -1,159 +0,0 @@ -package test.com.jogamp.opengl.test.junit.graph; - -import java.io.IOException; - -import javax.media.nativewindow.NativeWindowFactory; -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLException; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; - -import demo.GPUTextGLListenerBase01; - -public class TestHwTextRenderer01 { - - @BeforeClass - public static void initClass() { - GLProfile.initSingleton(true); - NativeWindowFactory.initSingleton(true); - } - - static void destroyWindow(GLWindow window) { - if(null!=window) { - window.destroy(); - } - } - - static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { - Assert.assertNotNull(caps); - - GLWindow window = GLWindow.create(caps); - window.setSize(width, height); - window.setPosition(10, 10); - window.setTitle(title); - Assert.assertNotNull(window); - window.setVisible(true); - - return window; - } - - @Test - public void testTextRendererR2T01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL3bc); - GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); - caps.setAlphaBits(4); - - GLWindow window = createWindow("r2t1-msaa0", caps, 800,400); - TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); - textGLListener.attachTo(window); - - textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 400); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 1100); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 2500); - window.display(); - - textGLListener.setFontSet(FontFactory.JAVA, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 400); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 1100); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 2500); - window.display(); - - destroyWindow(window); - } - - @Test - public void testTextRendererMSAA01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL2ES2); - GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); - caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - - GLWindow window = createWindow("r2t0-msaa1", caps, 800, 400); - TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); - textGLListener.attachTo(window); - - textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 0); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 0); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 0); - window.display(); - - textGLListener.setFontSet(FontFactory.JAVA, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 0); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 0); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 0); - window.display(); - - destroyWindow(window); - } - - private class TextGLListener extends GPUTextGLListenerBase01 { - String winTitle; - - public TextGLListener(int type) { - super(SVertex.factory(), type, false, false); - } - - public void attachTo(GLWindow window) { - super.attachTo(window); - winTitle = window.getTitle(); - } - public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ - setMatrix(xt, yt, angle, zoom, fboSize); - } - - public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - super.init(drawable); - gl.setSwapInterval(1); - gl.glEnable(GL.GL_DEPTH_TEST); - textRenderer.init(gl); - textRenderer.setAlpha(gl, 1.0f); - textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - } - - public void display(GLAutoDrawable drawable) { - super.display(drawable); - - try { - printScreen("./", winTitle, drawable.getWidth(), drawable.getHeight(), false); - } catch (GLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java new file mode 100755 index 000000000..501bdbb75 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java @@ -0,0 +1,159 @@ +package test.com.jogamp.opengl.test.junit.graph; + +import java.io.IOException; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.newt.opengl.GLWindow; + +import demo.GPUTextGLListenerBase01; + +public class TestTextRenderer01 { + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(true); + NativeWindowFactory.initSingleton(true); + } + + static void destroyWindow(GLWindow window) { + if(null!=window) { + window.destroy(); + } + } + + static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { + Assert.assertNotNull(caps); + + GLWindow window = GLWindow.create(caps); + window.setSize(width, height); + window.setPosition(10, 10); + window.setTitle(title); + Assert.assertNotNull(window); + window.setVisible(true); + + return window; + } + + @Test + public void testTextRendererR2T01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL3bc); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + caps.setAlphaBits(4); + + GLWindow window = createWindow("r2t1-msaa0", caps, 800,400); + TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); + textGLListener.attachTo(window); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 400); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 1100); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 2500); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 400); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 1100); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 2500); + window.display(); + + destroyWindow(window); + } + + @Test + public void testTextRendererMSAA01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + + GLWindow window = createWindow("r2t0-msaa1", caps, 800, 400); + TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); + textGLListener.attachTo(window); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + + destroyWindow(window); + } + + private class TextGLListener extends GPUTextGLListenerBase01 { + String winTitle; + + public TextGLListener(int type) { + super(SVertex.factory(), type, false, false); + } + + public void attachTo(GLWindow window) { + super.attachTo(window); + winTitle = window.getTitle(); + } + public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ + setMatrix(xt, yt, angle, zoom, fboSize); + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + super.init(drawable); + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + } + + public void display(GLAutoDrawable drawable) { + super.display(drawable); + + try { + printScreen("./", winTitle, drawable.getWidth(), drawable.getHeight(), false); + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} -- cgit v1.2.3 From 2d7cc275ccea2e11deeaf02f63c7984a6c09bf4f Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 13:25:54 +0300 Subject: Added inclass comments to OutlineShape --- src/com/jogamp/graph/curve/OutlineShape.java | 159 ++++++++++++++++++++------ src/com/jogamp/graph/geom/Vertex.java | 2 - src/com/jogamp/graph/geom/opengl/SVertex.java | 7 +- src/demo/GPUTextGLListenerBase01.java | 8 +- src/jogamp/graph/curve/text/GlyphShape.java | 16 +-- 5 files changed, 136 insertions(+), 56 deletions(-) diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index 9373808f1..c385b83f5 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -44,33 +44,85 @@ import com.jogamp.graph.curve.tess.CDTriangulator2D; * closed region defined by the outlines. * * One or more OutlineShape Object can be associated to a region - * this is left high-level representation of the Objects. For - * possible Optimizations. + * this is left as a high-level representation of the Objects. For + * optimizations, flexibility requirements for future features. * + *

+ * Example to creating an Outline Shape: + *
+  	addVertex(...)
+  	addVertex(...)
+  	addVertex(...)
+  	addEnptyOutline()
+  	addVertex(...)
+  	addVertex(...)
+  	addVertex(...)
+ * 
+ * + * The above will create two outlines each with three vertices. By adding these two outlines to + * the OutlineShape, we are stating that the combination of the two outlines represent the shape. + *
+ * + * To specify that the shape is curved at a region, the on-curve flag should be set to false + * for the vertex that is in the middle of the curved region (if the curved region is defined by 3 + * vertices (quadratic curve). + *
+ * In case the curved region is defined by 4 or more vertices the middle vertices should both have + * the on-curve flag set to false. + * + *
Example:
+ *
+  	addVertex(0,0, true);
+  	addVertex(0,1, false);
+  	addVertex(1,1, false);
+  	addVertex(1,0, true);
+ * 
+ * + * The above snippet defines a cubic nurbs curve where (0,1 and 1,1) + * do not belong to the final rendered shape. + * + * Implementation Notes:
+ *
    + *
  • The first vertex of any outline belonging to the shape should be on-curve
  • + *
  • Intersections between off-curved parts of the outline is not handled
  • + *
+ * + * @see Outline * @see Region */ public class OutlineShape { + public static final int QUADRATIC_NURBS = 10; - private final Vertex.Factory pointFactory; + private final Vertex.Factory vertexFactory; + + /** The list of outlines that are part of this + * outline shape. + */ private ArrayList> outlines = new ArrayList>(3); - + /** Create a new Outline based Shape */ public OutlineShape(Vertex.Factory factory) { - pointFactory = factory; + vertexFactory = factory; outlines.add(new Outline()); } - - public final Vertex.Factory pointFactory() { return pointFactory; } - + + /** Returns the associated vertex factory of this outline shape + * @return Vertex.Factory object + */ + public final Vertex.Factory vertexFactory() { return vertexFactory; } + /** Add a new empty outline * to the shape, this new outline will * be placed at the end of the outline list. + * + * After a call to this function all new vertices added + * will belong to the new outline */ public void addEmptyOutline(){ outlines.add(new Outline()); } - + /** Adds an outline to the OutlineShape object * if last outline of the shape is empty, it will replace * that last Outline with the new one. If outline is empty, @@ -86,27 +138,52 @@ public class OutlineShape { } outlines.add(outline); } - + /** Adds a vertex to the last open outline in the - * shape - * @param point + * shape. + * @param v the vertex to be added to the OutlineShape */ - public final void addVertex(Vertex point){ - getLastOutline().addVertex(point); + public final void addVertex(Vertex v){ + getLastOutline().addVertex(v); } - + + /** Add a 2D vertex to the last outline by defining the coordniate attribute + * of the vertex. The 2D vertex will be represented as Z=0. + * + * @param x the x coordinate + * @param y the y coordniate + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(float x, float y, boolean onCurve) { - getLastOutline().addVertex(pointFactory, x, y, onCurve); + getLastOutline().addVertex(vertexFactory, x, y, onCurve); } - + + /** Add a 3D vertex to the last outline by defining the coordniate attribute + * of the vertex. + * @param x the x coordinate + * @param y the y coordniate + * @param z the z coordniate + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(float x, float y, float z, boolean onCurve) { - getLastOutline().addVertex(pointFactory, x, y, z, onCurve); + getLastOutline().addVertex(vertexFactory, x, y, z, onCurve); } - + + /** Add a vertex to the last outline by passing a float array and specifying the offset and length in which. + * the attributes of the vertex are located. The attributes should be continuous (stride = 0). + * Attributes which value are not set (when length less than 3) are set implicitly to zero. + * @param coordsBuffer the coordinate array where the vertex attributes are to be picked from + * @param offset the offset in the buffer to the x coordinate + * @param length the number of attributes to pick from the buffer (maximum 3) + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) { - getLastOutline().addVertex(pointFactory, coordsBuffer, offset, length, onCurve); + getLastOutline().addVertex(vertexFactory, coordsBuffer, offset, length, onCurve); } - + /** Closes the last outline in the shape * if last vertex is not equal to first vertex. * A new temp vertex is added at the end which @@ -115,7 +192,7 @@ public class OutlineShape { public void closeLastOutline(){ getLastOutline().setClosed(true); } - + /** Get the last added outline to the list * of outlines that define the shape * @return the last outline @@ -125,7 +202,7 @@ public class OutlineShape { } /** Make sure that the outlines represent * the specified destinationType, if not - * transform outlines to destinationType. + * transform outlines to destination type. * @param destinationType The curve type needed */ public void transformOutlines(int destinationType){ @@ -133,7 +210,7 @@ public class OutlineShape { transformOutlinesQuadratic(); } } - + private void transformOutlinesQuadratic(){ ArrayList> newOutlines = new ArrayList>(3); @@ -150,9 +227,9 @@ public class OutlineShape { Vertex nextVertex = vertices.get((i+1)%size); if(!(currentVertex.isOnCurve()) && !(nextVertex.isOnCurve())) { newOutline.addVertex(currentVertex); - + float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), nextVertex.getCoord()); - newOutline.addVertex(pointFactory, newCoords, 0, 3, true); + newOutline.addVertex(vertexFactory, newCoords, 0, 3, true); } else { newOutline.addVertex(currentVertex); @@ -162,7 +239,7 @@ public class OutlineShape { } outlines = newOutlines; } - + private void generateVertexIds(){ int maxVertexId = 0; for(Outline outline:outlines){ @@ -173,7 +250,7 @@ public class OutlineShape { } } } - + /** @return the list of vertices associated with the * {@code Outline} list of this object */ @@ -184,10 +261,20 @@ public class OutlineShape { } return vertices; } - - /** Triangluate the graph object - * @param sharpness sharpness of the curved regions default = 0.5 + /** Triangulate the outline shape generating a list of triangles + * @return an arraylist of triangles representing the filled region + * which is produced by the combination of the outlines + */ + public ArrayList> triangulate(){ + return triangulate(0.5f); + } + + /**Triangulate the outline shape generating a list of triangles + * @param sharpness defines the curvature strength around the off-curve vertices. + * defaults to 0.5f + * @return an arraylist of triangles representing the filled region + * which is produced by the combination of the outlines */ public ArrayList> triangulate(float sharpness){ if(outlines.size() == 0){ @@ -195,20 +282,20 @@ public class OutlineShape { } sortOutlines(); generateVertexIds(); - + CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); - + for(int index = 0; index< outlines.size();index++){ Outline outline = outlines.get(index); triangulator2d.addCurve(outline); } - + ArrayList> triangles = triangulator2d.generateTriangulation(); triangulator2d.reset(); - + return triangles; } - + /** Sort the outlines from large * to small depending on the AABox */ diff --git a/src/com/jogamp/graph/geom/Vertex.java b/src/com/jogamp/graph/geom/Vertex.java index 9d19c89f6..0e4e5e8df 100644 --- a/src/com/jogamp/graph/geom/Vertex.java +++ b/src/com/jogamp/graph/geom/Vertex.java @@ -40,8 +40,6 @@ public interface Vertex extends Comparable, Cloneable { T create(float x, float y, float z); T create(float[] coordsBuffer, int offset, int length); - - // T[] create(T ... v); } void setCoord(float x, float y); diff --git a/src/com/jogamp/graph/geom/opengl/SVertex.java b/src/com/jogamp/graph/geom/opengl/SVertex.java index 076ac7456..37ce71a40 100644 --- a/src/com/jogamp/graph/geom/opengl/SVertex.java +++ b/src/com/jogamp/graph/geom/opengl/SVertex.java @@ -61,11 +61,6 @@ public class SVertex implements Vertex { public SVertex create(float[] coordsBuffer, int offset, int length) { return new SVertex(coordsBuffer, offset, length); } - - /* @Override - public Vertex[] create(Vertex ... v) { - return v; - } */ } public SVertex() { @@ -98,7 +93,7 @@ public class SVertex implements Vertex { throw new IndexOutOfBoundsException("coordsBuffer too small: "+coordsBuffer.length+" - "+offset+" < "+length); } if(length > 3) { - throw new IndexOutOfBoundsException("length too bug: "+length+" > "+3); + throw new IndexOutOfBoundsException("length too big: "+length+" > "+3); } int i=0; while(i pointFactory() { return shape.pointFactory(); } + public final Vertex.Factory vertexFactory() { return shape.vertexFactory(); } private void addVertexToLastOutline(Vertex vertex){ shape.addVertex(vertex); @@ -81,40 +81,40 @@ public class GlyphShape { if(!shape.getLastOutline().isEmpty()){ shape.addEmptyOutline(); } - Vertex vert = pointFactory().create(coords[0],coords[1]); + Vertex vert = vertexFactory().create(coords[0],coords[1]); vert.setOnCurve(true); addVertexToLastOutline(vert); numVertices++; } else if(segmentType == PathIterator.SEG_LINETO){ - Vertex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = vertexFactory().create(coords[0],coords[1]); vert1.setOnCurve(true); addVertexToLastOutline(vert1); numVertices++; } else if(segmentType == PathIterator.SEG_QUADTO){ - Vertex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = vertexFactory().create(coords[0],coords[1]); vert1.setOnCurve(false); addVertexToLastOutline(vert1); - Vertex vert2 = pointFactory().create(coords[2],coords[3]); + Vertex vert2 = vertexFactory().create(coords[2],coords[3]); vert2.setOnCurve(true); addVertexToLastOutline(vert2); numVertices+=2; } else if(segmentType == PathIterator.SEG_CUBICTO){ - Vertex vert1 = pointFactory().create(coords[0],coords[1]); + Vertex vert1 = vertexFactory().create(coords[0],coords[1]); vert1.setOnCurve(false); addVertexToLastOutline(vert1); - Vertex vert2 = pointFactory().create(coords[2],coords[3]); + Vertex vert2 = vertexFactory().create(coords[2],coords[3]); vert2.setOnCurve(false); addVertexToLastOutline(vert2); - Vertex vert3 = pointFactory().create(coords[4],coords[5]); + Vertex vert3 = vertexFactory().create(coords[4],coords[5]); vert3.setOnCurve(true); addVertexToLastOutline(vert3); -- cgit v1.2.3 From fca85c495e24322dd8870832fe3934fbe2d40236 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 14:31:48 +0300 Subject: Added inclass documentation to AABBox; Misc changes --- src/com/jogamp/graph/geom/AABBox.java | 115 ++++++++++++++++++-------- src/com/jogamp/graph/geom/Outline.java | 2 - src/com/jogamp/graph/geom/opengl/SVertex.java | 4 + src/jogamp/graph/geom/plane/Path2D.java | 6 +- 4 files changed, 88 insertions(+), 39 deletions(-) diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java index a2566b91f..f97c43a57 100644 --- a/src/com/jogamp/graph/geom/AABBox.java +++ b/src/com/jogamp/graph/geom/AABBox.java @@ -30,15 +30,29 @@ package com.jogamp.graph.geom; import com.jogamp.graph.math.VectorUtil; /** - * Axis Aligned Bounding Box. + * Axis Aligned Bounding Box. Defined by two 3D coordinates (low and high) + * The low being the the lower left corner of the box, and the high being the upper + * right corner of the box. + * */ public class AABBox { private float[] low = {Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE}; private float[] high = {-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE}; private float[] center = new float[3]; + /** Create a Axis Aligned bounding box (AABBox) where the low and and high MAX float Values. + */ public AABBox() {} + /** Create an AABBox specifying the coordinates of the low and high + * + * @param lx min x-coordinate + * @param ly min y-coordnate + * @param lz min z-coordinate + * @param hx max x-coordinate + * @param hy max y-coordinate + * @param hz max z-coordinate + */ public AABBox(float lx, float ly, float lz, float hx, float hy, float hz) { @@ -48,12 +62,10 @@ public class AABBox { computeCenter(); } - public String toString() { - return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+ - center[0]+"/"+center[1]+"/"+center[1]+" ]"; - } - - + /** Create a AABBox defining the low and high + * @param low min xyz-coordinates + * @param high max xyz-coordinates + */ public AABBox(float[] low, float[] high) { this.low = low; @@ -62,27 +74,39 @@ public class AABBox { computeCenter(); } + /** Get the max xyz-coordinates + * @return a float array containing the max xyz coordinates + */ public float[] getHigh() { return high; } - public void setHigh(float hx, float hy, float hz) + + private void setHigh(float hx, float hy, float hz) { this.high[0] = hx; this.high[1] = hy; this.high[2] = hz; } + + /** Get the min xyz-coordinates + * @return a float array containing the min xyz coordinates + */ public float[] getLow() { return low; } - public void setLow(float lx, float ly, float lz) + + private void setLow(float lx, float ly, float lz) { this.low[0] = lx; this.low[1] = ly; this.low[2] = lz; } + /** Resize the AABBox to encapsulate another AABox + * @param newBox AABBox to be encapsulated in + */ public void resize(AABBox newBox) { float[] newLow = newBox.getLow(); @@ -114,6 +138,12 @@ public class AABBox { center[2] = (high[2] + low[2])/2; } + /** Resize the AABBox to encapsulate the passed + * xyz-coordinates. + * @param x x-axis coordinate value + * @param y y-axis coordinate value + * @param z z-axis coordinate value + */ public void resize(float x, float y, float z) { /** test low */ @@ -135,6 +165,13 @@ public class AABBox { computeCenter(); } + /** Check if the x & y coordinates are bounded/contained + * by this AABBox + * @param x x-axis coordinate value + * @param y y-axis coordinate value + * @return true if x belong to (low.x, high.x) and + * y belong to (low.y, high.y) + */ public boolean contains(float x, float y){ if(xhigh[0]){ return false; @@ -145,6 +182,14 @@ public class AABBox { return true; } + /** Check if the xyz coordinates are bounded/contained + * by this AABBox. + * @param x x-axis coordinate value + * @param y y-axis coordinate value + * @param z z-axis coordinate value + * @return true if x belong to (low.x, high.x) and + * y belong to (low.y, high.y) and z belong to (low.z, high.z) + */ public boolean contains(float x, float y, float z){ if(xhigh[0]){ return false; @@ -158,14 +203,15 @@ public class AABBox { return true; } - /** - * @return true if area is empty - */ - boolean isEmpty() { - return getWidth() <=0 || getHeight() <= 0 ; - } - - public boolean intersects(double x, double y, double w, double h) { + /** Check if there is a common region between this AABBox and the passed + * 2D region irrespective of z range + * @param x lower left x-coord + * @param y lower left y-coord + * @param w width + * @param h hight + * @return true if this AABBox might have a common region with this 2D region + */ + public boolean intersects(float x, float y, float w, float h) { if (w <= 0 || h <= 0) { return false; } @@ -176,8 +222,8 @@ public class AABBox { return false; } - final float x0 = getX(); - final float y0 = getY(); + final float x0 = getMinX(); + final float y0 = getMinY(); return (x + w > x0 && y + h > y0 && x < x0 + _w && @@ -185,26 +231,24 @@ public class AABBox { } + /** Get the size of the Box where the size is represented by the + * length of the vector between low and high. + * @return a float representing the size of the AABBox + */ public float getSize(){ return VectorUtil.computeLength(low, high); } + /**Get the Center of the AABBox + * @return the xyz-coordinates of the center of the AABBox + */ public float[] getCenter() { return center; } - public void setCenter(float[] center) { - this.center = center; - } - - public void setHigh(float[] high) { - this.high = high; - } - - public void setLow(float[] low) { - this.low = low; - } - + /** Scale the AABBox by a constant + * @param size a constant float value + */ public void scale(float size) { float[] diffH = new float[3]; diffH[0] = high[0] - center[0]; @@ -224,11 +268,11 @@ public class AABBox { low = VectorUtil.vectorAdd(center, diffL); } - public float getX() { + public float getMinX() { return low[0]; } - public float getY() { + public float getMinY() { return low[1]; } @@ -246,4 +290,9 @@ public class AABBox { public AABBox clone(){ return new AABBox(this.low, this.high); } + + public String toString() { + return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+ + center[0]+"/"+center[1]+"/"+center[1]+" ]"; + } } diff --git a/src/com/jogamp/graph/geom/Outline.java b/src/com/jogamp/graph/geom/Outline.java index 4e588623e..4f8d26783 100644 --- a/src/com/jogamp/graph/geom/Outline.java +++ b/src/com/jogamp/graph/geom/Outline.java @@ -41,9 +41,7 @@ import com.jogamp.graph.math.VectorUtil; * * Note: An outline should be closed to be rendered as a region. * - * * @see OutlineShape, Region - * */ public class Outline implements Comparable>{ diff --git a/src/com/jogamp/graph/geom/opengl/SVertex.java b/src/com/jogamp/graph/geom/opengl/SVertex.java index 37ce71a40..681067e40 100644 --- a/src/com/jogamp/graph/geom/opengl/SVertex.java +++ b/src/com/jogamp/graph/geom/opengl/SVertex.java @@ -31,6 +31,10 @@ package com.jogamp.graph.geom.opengl; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.math.VectorUtil; +/** A Simple Vertex Implementation. Where the coordinates, and other attributes are + * float based, and the coordinates and texture coordinates are saved in two float arrays. + * + */ public class SVertex implements Vertex { private int id = Integer.MAX_VALUE; protected float[] coord = new float[3]; diff --git a/src/jogamp/graph/geom/plane/Path2D.java b/src/jogamp/graph/geom/plane/Path2D.java index e25ae0e84..431891361 100644 --- a/src/jogamp/graph/geom/plane/Path2D.java +++ b/src/jogamp/graph/geom/plane/Path2D.java @@ -360,8 +360,6 @@ public final class Path2D implements Cloneable { } } } - // FIXME: Rami's code had this in, but AABBox uses upper left - lower right - right ? - // return new AABBox(rx1, ry1, 0f, rx2 - rx1, ry2 - ry1, 0f); return new AABBox(rx1, ry1, 0f, rx2, ry2, 0f); } @@ -396,11 +394,11 @@ public final class Path2D implements Cloneable { } public boolean contains(AABBox r) { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + return contains(r); } public boolean intersects(AABBox r) { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + return intersects(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight()); } public PathIterator iterator() { -- cgit v1.2.3 From dbc74b98eb7429cbb51f7af0572ab53ddd0d9edc Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 13:56:48 +0200 Subject: Refactor: Public *Renderer / Unify Region Demos / Using own Screenshot (non AWT, plain GL2ES2) Refactor: Public *Renderer - Sharing common base abstract class Renderer.java - Having public abstract classes RegionRenderer and TextRenderer - Implementation non public, accessed via factory - + shared code - + clean API (same stuff) Unify Region Demos - reduced code / path, sharing common demo/test features Text/Region Using own Screenshot (non AWT, plain GL2ES2) - Remove AWT dependency - Allow GL2ES2 screenshots - Less complex --- .../jogamp/graph/curve/opengl/RegionRenderer.java | 500 +++++---------------- src/com/jogamp/graph/curve/opengl/Renderer.java | 161 +++++++ .../jogamp/graph/curve/opengl/TextRenderer.java | 392 +++------------- .../graph/curve/opengl/shader/curverenderer.fp | 99 ---- .../graph/curve/opengl/shader/curverenderer.vp | 13 - src/demo/GPURegionNewtDemo01.java | 167 +++---- src/demo/GPURegionNewtDemo02.java | 260 +++++------ src/demo/GPURegionRendererListenerBase01.java | 53 +++ src/demo/GPURendererListenerBase01.java | 231 ++++++++++ src/demo/GPUTextGLListenerBase01.java | 324 ------------- src/demo/GPUTextNewtDemo01.java | 17 +- src/demo/GPUTextNewtDemo02.java | 15 +- src/demo/GPUTextRendererListenerBase01.java | 190 ++++++++ src/demo/ReadBufferUtil.java | 107 +++++ src/demo/Screenshot.java | 39 ++ .../graph/curve/opengl/RegionRendererImpl01.java | 206 +++++++++ .../graph/curve/opengl/TextRendererImpl01.java | 189 ++++++++ .../graph/curve/opengl/shader/curverenderer01.fp | 99 ++++ .../graph/curve/opengl/shader/curverenderer01.vp | 13 + .../test/junit/graph/TestRegionRenderer01.java | 152 +++++++ .../test/junit/graph/TestTextRenderer01.java | 31 +- 21 files changed, 1814 insertions(+), 1444 deletions(-) mode change 100755 => 100644 src/com/jogamp/graph/curve/opengl/RegionRenderer.java create mode 100644 src/com/jogamp/graph/curve/opengl/Renderer.java delete mode 100644 src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp delete mode 100644 src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp mode change 100755 => 100644 src/demo/GPURegionNewtDemo02.java create mode 100644 src/demo/GPURegionRendererListenerBase01.java create mode 100644 src/demo/GPURendererListenerBase01.java delete mode 100644 src/demo/GPUTextGLListenerBase01.java create mode 100644 src/demo/GPUTextRendererListenerBase01.java create mode 100644 src/demo/ReadBufferUtil.java create mode 100644 src/demo/Screenshot.java create mode 100755 src/jogamp/graph/curve/opengl/RegionRendererImpl01.java create mode 100644 src/jogamp/graph/curve/opengl/TextRendererImpl01.java create mode 100644 src/jogamp/graph/curve/opengl/shader/curverenderer01.fp create mode 100644 src/jogamp/graph/curve/opengl/shader/curverenderer01.vp create mode 100644 src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java old mode 100755 new mode 100644 index e75ca25cd..4be1506d5 --- a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -1,388 +1,112 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package com.jogamp.graph.curve.opengl; - -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.RegionFactory; -import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.Vertex; - -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class RegionRenderer { - protected static final boolean DEBUG = Debug.debug("RegionRenderer"); - - private ShaderState st; - private PMVMatrix pmvMatrix = new PMVMatrix(); - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private float sharpness = 0.5f; - private float alpha = 1.0f; - private float strength = 3.0f; - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private GLContext context; - private FloatBuffer color = FloatBuffer.allocate(3); - private HashMap regions = new HashMap(); - - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public RegionRenderer(GLContext context) { - this.context = context; - init(context, 0.5f); - } - /** Create a Hardware accelerated Region Renderer - * @param context OpenGL rendering context - * @param type region type (single or multipass) - */ - public RegionRenderer(GLContext context, int type) { - this.context = context; - this.regionType = type; - init(context, 0.5f); - } - - private boolean init(GLContext context, float sharpvalue){ - if(initialized){ - if(DEBUG) { - System.err.println("HWRegionRenderer: Already initialized!"); - } - return true; - } - sharpness = sharpvalue; - - GL2ES2 gl = context.getGL().getGL2ES2(); - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWRegionRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.setSwapInterval(1); - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - initShader(gl); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(); - - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()))) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("p1y", sharpness))) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("g_color", 3, color))) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - st.glUseProgram(gl, false); - - if(DEBUG) { - System.err.println("HWRegionRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public float getAlpha() { - return alpha; - } - public void setAlpha(float alpha_t) { - alpha = alpha_t; - } - - public void setColor(float r, float g, float b){ - color.put(r); - color.put(g); - color.put(b); - color.rewind(); - } - - public void rotate(float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - } - public void translate(float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - } - - public void resetMatrix(){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - } - - /** - * @param drawable - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshape(GLAutoDrawable drawable, float angle, float ratio, float near, float far){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null==st) { - if(DEBUG){ - System.err.println("HWRegionRenderer: Shader State is null, or not"); - } - return false; - } - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - st.glUseProgram(gl, false); - return true; - } - - private void initShader(GL2ES2 gl) { - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RegionRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWRegionRenderer: Couldn't link program: "+sp); - } - - st = new ShaderState(); - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - } - - private Region createRegion(OutlineShape outlineShape) { - Region region = RegionFactory.create(context, st, regionType); - - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); - ArrayList vertices = (ArrayList) outlineShape.getVertices(); - region.addVertices(vertices); - region.addTriangles(triangles); - - region.update(); - return region; - } - - private Region createRegion(OutlineShape[] outlineShapes) { - Region region = RegionFactory.create(context, st, regionType); - - int numVertices = region.getNumVertices(); - - for(OutlineShape outlineShape:outlineShapes){ - outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - - ArrayList> triangles = outlineShape.triangulate(sharpness); - region.addTriangles(triangles); - - ArrayList vertices = outlineShape.getVertices(); - for(Vertex vert:vertices){ - vert.setId(numVertices++); - } - region.addVertices(vertices); - } - - region.update(); - return region; - } - - - /** Render outline in 3D space at the position provided - * the triangles of the shapes will be generated, if not yet generated - * @param outlineShape the OutlineShape to Render. - * @param position the initial translation of the outlineShape. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShape(OutlineShape outlineShape, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - int hashCode = getHashCode(outlineShape); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShape); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - /** Render a list of Outline shapes combined in one region - * at the position provided the triangles of the - * shapes will be generated, if not yet generated - * @param outlineShapes the list of OutlineShapes to Render. - * @param position the initial translation of the outlineShapes. - * @throws Exception if HwRegionRenderer not initialized - */ - public void renderOutlineShapes(OutlineShape[] outlineShapes, float[] position) throws Exception{ - if(!initialized){ - throw new Exception("HWRegionRenderer: not initialized!"); - } - - int hashCode = getHashCode(outlineShapes); - Region region = regions.get(hashCode); - - if(null == region) { - region = createRegion(outlineShapes); - regions.put(hashCode, region); - } - - GL2ES2 gl = context.getGL().getGL2ES2(); - st.glUseProgram(gl, true); - GLUniformData ud = st.getUniform("mgl_PMVMatrix"); - if(null!=ud) { - st.glUniform(gl, ud); - } - if(!st.glUniform(gl, new GLUniformData("g_alpha", alpha))) { - System.err.println("Error setting global alpha in shader: "+st); - } - GLUniformData gcolorUD = st.getUniform("g_color"); - if(null!=gcolorUD) { - st.glUniform(gl, gcolorUD); - } - if(!st.glUniform(gl, new GLUniformData("a_strength", strength))) { - System.err.println("Error setting antialias strength in shader: "+st); - } - region.render(null, 0, 0, 0); - st.glUseProgram(gl, false); - } - - private int getHashCode(OutlineShape outlineShape){ - return outlineShape.hashCode(); - } - - private int getHashCode(OutlineShape[] outlineShapes){ - int hashcode = 0; - for(OutlineShape outlineShape:outlineShapes){ - hashcode += getHashCode(outlineShape); - } - return hashcode; - } - - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void clearCached() { - Iterator iterator = regions.values().iterator(); - while(iterator.hasNext()){ - Region region = iterator.next(); - region.destroy(); - } - regions.clear(); - } -} +package com.jogamp.graph.curve.opengl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import javax.media.opengl.GL2ES2; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.RegionFactory; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex; + +public abstract class RegionRenderer extends Renderer { + + /** Create a Hardware accelerated Region Renderer + */ + public static RegionRenderer create(Vertex.Factory factory, int type) { + return new jogamp.graph.curve.opengl.RegionRendererImpl01(factory, type); + } + + public RegionRenderer(Vertex.Factory factory, int type) { + super(factory, type); + } + + /** Render an array of Outline shapes combined in one region + * at the position provided the triangles of the + * shapes will be generated, if not yet generated + * @param outlineShapes array of OutlineShapes to Render. + * @param position the initial translation of the outlineShapes. + * @param texSize texture size for multipass render * + * @throws Exception if HwRegionRenderer not initialized + */ + public abstract void renderOutlineShapes(GL2ES2 gl, OutlineShape[] outlineShapes, float[] position, int texSize); + + /** Render outline in 3D space at the position provided + * the triangles of the shapes will be generated, if not yet generated + * @param outlineShape the OutlineShape to Render. + * @param position the initial translation of the outlineShape. + * @param texSize texture size for multipass render + * @throws Exception if HwRegionRenderer not initialized + */ + public abstract void renderOutlineShape(GL2ES2 gl, OutlineShape outlineShape, float[] position, int texSize); + + protected HashMap regions = new HashMap(); + + public void flushCash() { + Iterator iterator = regions.values().iterator(); + while(iterator.hasNext()){ + Region region = iterator.next(); + region.destroy(); + } + regions.clear(); + } + + /** + * @param sharpness parameter for Region generation + * @return the resulting Region inclusive the generated region + */ + protected Region createRegion(GL2ES2 gl, OutlineShape outlineShape, float sharpness) { + Region region = RegionFactory.create(gl.getContext(), st, regionType); + + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList vertices = (ArrayList) outlineShape.getVertices(); + region.addVertices(vertices); + region.addTriangles(triangles); + + region.update(); + return region; + } + + /** + * @param sharpness parameter for Region generation + * @return the resulting Region inclusive the generated region + */ + protected Region createRegion(GL2ES2 gl, OutlineShape[] outlineShapes, float sharpness) { + Region region = RegionFactory.create(gl.getContext(), st, regionType); + + int numVertices = region.getNumVertices(); + + for(OutlineShape outlineShape:outlineShapes){ + outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); + + ArrayList> triangles = outlineShape.triangulate(sharpness); + region.addTriangles(triangles); + + ArrayList vertices = outlineShape.getVertices(); + for(Vertex vert:vertices){ + vert.setId(numVertices++); + } + region.addVertices(vertices); + } + + region.update(); + return region; + } + + protected static int getHashCode(OutlineShape outlineShape){ + return outlineShape.hashCode(); + } + + protected static int getHashCode(OutlineShape[] outlineShapes){ + int hashcode = 0; + for(OutlineShape outlineShape:outlineShapes){ + hashcode += getHashCode(outlineShape); + } + return hashcode; + } +} \ No newline at end of file diff --git a/src/com/jogamp/graph/curve/opengl/Renderer.java b/src/com/jogamp/graph/curve/opengl/Renderer.java new file mode 100644 index 000000000..a1755e003 --- /dev/null +++ b/src/com/jogamp/graph/curve/opengl/Renderer.java @@ -0,0 +1,161 @@ +package com.jogamp.graph.curve.opengl; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.opengl.Debug; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; + +public abstract class Renderer { + protected static final boolean DEBUG = Debug.debug("CurveRenderer"); + + protected abstract boolean initImpl(GL2ES2 gl); + + protected abstract void disposeImpl(GL2ES2 gl); + + /** + * Flushes all cached data + */ + public abstract void flushCash(); + + public abstract float getAlpha(); + + public abstract void setAlpha(GL2ES2 gl, float alpha_t); + + public abstract void setColor(GL2ES2 gl, float r, float g, float b); + + protected final Vertex.Factory pointFactory; + protected ShaderState st = new ShaderState(); + protected PMVMatrix pmvMatrix = new PMVMatrix(); + protected GLUniformData mgl_PMVMatrix; + protected int regionType = Region.SINGLE_PASS; + protected int vp_width = 0; + protected int vp_height = 0; + + private boolean vboSupported = false; + private boolean initialized = false; + + protected Renderer(Vertex.Factory factory, int type) { + this.regionType = type; + this.pointFactory = (null != factory) ? factory : SVertex.factory(); + } + + public Vertex.Factory getFactory() { return pointFactory; } + + public final boolean isInitialized() { return initialized; } + + public final boolean isVBOSupported() { return vboSupported; } + + public final int getWidth() { return vp_width; } + public final int getHeight() { return vp_height; } + + /** + * Initialize shaders and bindings for GPU based rendering. + * Leaves the renderer enabled, ie ShaderState on. + * + * @param gl the current GL state + * @return true if succeeded, false otherwise + */ + public boolean init(GL2ES2 gl) { + if(initialized){ + if(DEBUG) { + System.err.println("TextRenderer: Already initialized!"); + } + return true; + } + vboSupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("TextRendererImpl01: VBO Supported = " + isVBOSupported()); + } + + initialized = initImpl(gl); + return initialized; + } + + public void dispose(GL2ES2 gl) { + if(!initialized){ + if(DEBUG) { + System.err.println("TextRenderer: Not initialized!"); + } + return; + } + disposeImpl(gl); + st.destroy(gl); + flushCash(); + initialized = false; + } + + public final ShaderState getShaderState() { return st; } + + public final PMVMatrix getMatrix() { return pmvMatrix; } + + public void rotate(GL2ES2 gl, float angle, float x, float y, float z) { + pmvMatrix.glRotatef(angle, x, y, z); + if(initialized && null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void translate(GL2ES2 gl, float x, float y, float z) { + pmvMatrix.glTranslatef(x, y, z); + if(initialized && null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void resetModelview(GL2ES2 gl) { + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + if(initialized && null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public void updateMatrix(GL2ES2 gl) { + if(initialized && null != gl && st.inUse()) { + st.glUniform(gl, mgl_PMVMatrix); + } + } + + public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far) { + this.vp_width = width; + this.vp_height = height; + float ratio = (float)width/(float)height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.gluPerspective(angle, ratio, near, far); + + if(initialized && null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + + public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { + this.vp_width = width; + this.vp_height = height; + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0, width, 0, height, near, far); + + if(initialized && null != gl) { + st.glUniform(gl, mgl_PMVMatrix); + } + + return true; + } + +} \ No newline at end of file diff --git a/src/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/com/jogamp/graph/curve/opengl/TextRenderer.java index 703f82373..04988a3ab 100644 --- a/src/com/jogamp/graph/curve/opengl/TextRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -1,353 +1,79 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ package com.jogamp.graph.curve.opengl; -import java.nio.FloatBuffer; import java.util.HashMap; import java.util.Iterator; import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLException; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; import jogamp.graph.curve.text.GlyphString; import jogamp.graph.font.FontInt; import jogamp.graph.geom.plane.AffineTransform; import jogamp.graph.geom.plane.Path2D; -import com.jogamp.graph.curve.Region; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.Vertex; -import com.jogamp.graph.geom.opengl.SVertex; -import jogamp.opengl.Debug; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderCode; -import com.jogamp.opengl.util.glsl.ShaderProgram; -import com.jogamp.opengl.util.glsl.ShaderState; -public class TextRenderer { - protected static final boolean DEBUG = Debug.debug("TextRenderer"); - static final boolean FONTTOOL_CUSTOM = false; - - private ShaderState st = new ShaderState(); - - private PMVMatrix pmvMatrix = new PMVMatrix(); - private GLUniformData mgl_PMVMatrix; - - /**Sharpness is equivalent to the value of t value of texture coord - * on the off-curve vertex. The high value of sharpness will - * result in high curvature. - */ - private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); - private GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); - private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); - private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); - - private boolean initialized = false; - - private int regionType = Region.SINGLE_PASS; - - private HashMap strings = new HashMap(); - private final Vertex.Factory pointFactory; - - int win_width = 0; - int win_height = 0; - - /** - * Create a Hardware accelerated Text Renderer. - * @param context OpenGL rendering context - * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. - */ - public TextRenderer(Vertex.Factory factory, int type) { - this.pointFactory = (null != factory) ? factory : SVertex.factory(); - this.regionType = type; - } - - /** - * Initialize shaders and bindings for GPU based text Rendering, - * should be called only once. - * Leaves the renderer enables, ie ShaderState on. - * - * @param drawable the current drawable - * @param shapvalue shaprness around the off-curve vertices - * @return true if init succeeded, false otherwise - */ - public boolean init(GL2ES2 gl){ - if(initialized){ - if(DEBUG) { - System.err.println("HWTextRenderer: Already initialized!"); - } - return true; - } - - boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && - gl.isFunctionAvailable("glBindBuffer") && - gl.isFunctionAvailable("glBufferData") && - gl.isFunctionAvailable("glDrawElements") && - gl.isFunctionAvailable("glVertexAttribPointer") && - gl.isFunctionAvailable("glDeleteBuffers"); - - if(DEBUG) { - System.err.println("HWTextRenderer: VBO Supported = " + VBOsupported); - } - - if(!VBOsupported){ - return false; - } - - gl.glEnable(GL2ES2.GL_BLEND); - gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); - - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, TextRenderer.class, - "shader", "shader/bin", "curverenderer"); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, TextRenderer.class, - "shader", "shader/bin", "curverenderer"); - - ShaderProgram sp = new ShaderProgram(); - sp.add(rsVp); - sp.add(rsFp); - - if(!sp.link(gl, System.err)) { - throw new GLException("HWTextRenderer: Couldn't link program: "+sp); - } - - st.attachShaderProgram(gl, sp); - gl.glBindAttribLocation(sp.id(), 0, "v_position"); - gl.glBindAttribLocation(sp.id(), 1, "texCoord"); - - st.glUseProgram(gl, true); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - resetMatrix(null); - - mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); - if(!st.glUniform(gl, mgl_PMVMatrix)) { - if(DEBUG){ - System.err.println("Error setting PMVMatrix in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_sharpness)) { - if(DEBUG){ - System.err.println("Error setting sharpness in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_alpha)) { - if(DEBUG){ - System.err.println("Error setting global alpha in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_color)) { - if(DEBUG){ - System.err.println("Error setting global color in shader: "+st); - } - return false; - } - - if(!st.glUniform(gl, mgl_strength)) { - System.err.println("Error setting antialias strength in shader: "+st); - } - - if(DEBUG) { - System.err.println("HWTextRenderer initialized: " + Thread.currentThread()+" "+st); - } - initialized = true; - return true; - } - - public void dispose(GL2ES2 gl) { - st.destroy(gl); - flushCash(); - } - - public float getAlpha() { - return mgl_alpha.floatValue(); - } - - public ShaderState getShaderState() { - return st; - } - - public void setAlpha(GL2ES2 gl, float alpha_t) { - mgl_alpha.setData(alpha_t); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_alpha); - } - } - - public void setColor(GL2ES2 gl, float r, float g, float b){ - FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); - fb.put(0, r); - fb.put(1, r); - fb.put(2, r); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_color); - } - } - - public final PMVMatrix matrix() { return pmvMatrix; } - - public void rotate(GL2ES2 gl, float angle, float x, float y, float z){ - pmvMatrix.glRotatef(angle, x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - public void translate(GL2ES2 gl, float x, float y, float z){ - pmvMatrix.glTranslatef(x, y, z); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void resetMatrix(GL2ES2 gl){ - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); - pmvMatrix.glLoadIdentity(); - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void setMatrix(GL2ES2 gl){ - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - } - } - - public void updateAllShaderValues(GL2ES2 gl) { - if(null != gl && st.inUse()) { - st.glUniform(gl, mgl_PMVMatrix); - st.glUniform(gl, mgl_alpha); - st.glUniform(gl, mgl_color); - st.glUniform(gl, mgl_strength); - } +public abstract class TextRenderer extends Renderer { + + /** + * Create a Hardware accelerated Text Renderer. + * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. + */ + public static TextRenderer create(Vertex.Factory factory, int type) { + return new jogamp.graph.curve.opengl.TextRendererImpl01(factory, type); } - /** - * @param gl - * @param angle - * @param ratio - * @param near - * @param far - * @return - */ - public boolean reshapePerspective(GL2ES2 gl, float angle, int width, int height, float near, float far){ - win_width = width; - win_height = height; - float ratio = (float)width/(float)height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.gluPerspective(angle, ratio, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } - - public boolean reshapeOrtho(GL2ES2 gl, int width, int height, float near, float far) { - win_width = width; - win_height = height; - pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - pmvMatrix.glLoadIdentity(); - pmvMatrix.glOrthof(0, width, 0, height, near, far); - - if(null != gl) { - st.glUniform(gl, mgl_PMVMatrix); - } - - return true; - } + protected TextRenderer(Vertex.Factory factory, int type) { + super(factory, type); + } - private GlyphString createString(GL2ES2 gl, Font font, int size, String str) { - AffineTransform affineTransform = new AffineTransform(pointFactory); - - Path2D[] paths = new Path2D[str.length()]; - ((FontInt)font).getOutline(str, size, affineTransform, paths); - - GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); - glyphString.createfromFontPath(paths, affineTransform); - - glyphString.generateRegion(gl.getContext(), mgl_sharpness.floatValue(), st, regionType); - return glyphString; - } - - - /** Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated - * @param font font to be used - * @param str text to be rendered - * @param position the lower left corner of the string + /** Render the String in 3D space wrt to the font provided at the position provided + * the outlines will be generated, if not yet generated + * @param gl the current GL state + * @param font font to be used + * @param str text to be rendered + * @param position the lower left corner of the string * @param fontSize font size - * @param texSize texture size for multipass render - * @throws Exception if TextRenderer not initialized - */ - public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { - if(!initialized){ - throw new GLException("HWTextRenderer: not initialized!"); - } - String fontStrHash = getTextHashCode(font, str, fontSize); - GlyphString glyphString = strings.get(fontStrHash); - if(null == glyphString) { - glyphString = createString(gl, font, fontSize, str); - strings.put(fontStrHash, glyphString); - } - - glyphString.renderString3D(pmvMatrix, win_width, win_height, texSize); - } - - private String getTextHashCode(Font font, String str, int fontSize) { - // FIXME: use integer hash code - return font.getName() + "." + str.hashCode() + "." + fontSize; - } + * @param texSize texture size for multipass render + * @throws Exception if TextRenderer not initialized + */ + public abstract void renderString3D(GL2ES2 gl, Font font, + String str, float[] position, int fontSize, int texSize); - /** Clears the cached string curves - * and destorys underlying buffers - */ - public void flushCash() { - Iterator iterator = strings.values().iterator(); - while(iterator.hasNext()){ - GlyphString glyphString = iterator.next(); - glyphString.destroy(); - } - strings.clear(); - } -} + protected HashMap strings = new HashMap(); + + /** + * + * @param font + * @param size + * @param str + * @param sharpness parameter for Region generation of the resulting GlyphString + * @return the resulting GlyphString inclusive the generated region + */ + protected GlyphString createString(GL2ES2 gl, Font font, int size, String str, float sharpness) { + AffineTransform affineTransform = new AffineTransform(pointFactory); + + Path2D[] paths = new Path2D[str.length()]; + ((FontInt)font).getOutline(str, size, affineTransform, paths); + + GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); + glyphString.createfromFontPath(paths, affineTransform); + glyphString.generateRegion(gl.getContext(), sharpness, st, regionType); + + return glyphString; + } + + protected static String getTextHashCode(Font font, String str, int fontSize) { + // FIXME: use integer hash code + return font.getName() + "." + str.hashCode() + "." + fontSize; + } + + public void flushCash() { + Iterator iterator = strings.values().iterator(); + while(iterator.hasNext()){ + GlyphString glyphString = iterator.next(); + glyphString.destroy(); + } + strings.clear(); + } +} \ No newline at end of file diff --git a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp deleted file mode 100644 index 2b3a0ce1d..000000000 --- a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.fp +++ /dev/null @@ -1,99 +0,0 @@ -//#version 100 - -uniform float p1y; -uniform float g_alpha; -uniform vec3 g_color; -uniform float a_strength; - -varying vec2 v_texCoord; - -vec3 b_color = vec3(0.0, 0.0, 0.0); - -uniform sampler2D texture; -vec4 weights = vec4(0.075, 0.06, 0.045, 0.025); - -void main (void) -{ - vec2 rtex = vec2(abs(v_texCoord.x),abs(v_texCoord.y)); - vec3 c = g_color; - - float alpha = 0.0; - - if((v_texCoord.x == 0.0) && (v_texCoord.y == 0.0)){ - alpha = g_alpha; - } - else if((v_texCoord.x >= 5.0)){ - vec2 dfx = dFdx(v_texCoord); - vec2 dfy = dFdy(v_texCoord); - - vec2 size = 1.0/textureSize(texture,0); //version 130 - rtex -= 5.0; - vec4 t = texture2D(texture, rtex)* 0.18; - - t += texture2D(texture, rtex + size*(vec2(1, 0)))*weights.x; - t += texture2D(texture, rtex - size*(vec2(1, 0)))*weights.x; - t += texture2D(texture, rtex + size*(vec2(0, 1)))*weights.x; - t += texture2D(texture, rtex - size*(vec2(0, 1)))*weights.x; - - t += texture2D(texture, rtex + 2.0*size*(vec2(1, 0))) *weights.y; - t += texture2D(texture, rtex - 2.0*size*(vec2(1, 0)))*weights.y; - t += texture2D(texture, rtex + 2.0*size*(vec2(0, 1)))*weights.y; - t += texture2D(texture, rtex - 2.0*size*(vec2(0, 1)))*weights.y; - - t += texture2D(texture, rtex + 3.0*size*(vec2(1, 0))) *weights.z; - t += texture2D(texture, rtex - 3.0*size*(vec2(1, 0)))*weights.z; - t += texture2D(texture, rtex + 3.0*size*(vec2(0, 1)))*weights.z; - t += texture2D(texture, rtex - 3.0*size*(vec2(0, 1)))*weights.z; - - t += texture2D(texture, rtex + 4.0*size*(vec2(1, 0))) *weights.w; - t += texture2D(texture, rtex - 4.0*size*(vec2(1, 0)))*weights.w; - t += texture2D(texture, rtex + 4.0*size*(vec2(0, 1)))*weights.w; - t += texture2D(texture, rtex - 4.0*size*(vec2(0, 1)))*weights.w; - - if(t.w == 0.0){ - discard; - } - - c = t.xyz; - alpha = g_alpha* t.w; - } - /////////////////////////////////////////////////////////// - else if ((v_texCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)){ - vec2 dtx = dFdx(rtex); - vec2 dty = dFdy(rtex); - - rtex.y -= 0.1; - if(rtex.y < 0.0) { - if(v_texCoord.y < 0.0) - discard; - else{ - rtex.y = 0.0; - } - } - - vec2 f = vec2((dtx.y - 2.0*p1y*dtx.x + 4.0*p1y*rtex.x*dtx.x), (dty.y - 2.0*p1y*dty.x + 4.0*p1y*rtex.x*dty.x)); - - float position = rtex.y - ((2.0 * rtex.x * p1y) * (1.0 - rtex.x)); - float d = position/(length(f)); - - float a = (0.5 - d * sign(v_texCoord.y)); - - - if (a >= 1.0) { - alpha = g_alpha; - // c = vec3(1.0,1.0,1.0); - } - else if (a <= 0.0) { - alpha = 0.0;//discard; - // c = vec3(0.0,0.0,0.0); - - } - else { - alpha = g_alpha*a; - // c = vec3(a,a,a); - mix(b_color,g_color, a); - } - } - - gl_FragColor = vec4(c, alpha); -} diff --git a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp b/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp deleted file mode 100644 index bc9ecb41e..000000000 --- a/src/com/jogamp/graph/curve/opengl/shader/curverenderer.vp +++ /dev/null @@ -1,13 +0,0 @@ -//#version 100 - -uniform mat4 mgl_PMVMatrix[2]; -attribute vec4 v_position; -attribute vec2 texCoord; - -varying vec2 v_texCoord; - -void main(void) -{ - gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * v_position; - v_texCoord = texCoord.st; -} \ No newline at end of file diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java index d58d4148d..676621692 100755 --- a/src/demo/GPURegionNewtDemo01.java +++ b/src/demo/GPURegionNewtDemo01.java @@ -32,18 +32,14 @@ import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.Animator; /** Demonstrate the rendering of multiple outlines into one region/OutlineShape * These Outlines are not necessary connected or contained. @@ -53,21 +49,18 @@ import com.jogamp.opengl.util.FPSAnimator; * */ public class GPURegionNewtDemo01 { - private static void create(){ - new RegionNewtWindow(); - } - public static void main(String[] args) { - create(); - } -} - -class RegionNewtWindow { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GPURegionNewtDemo01 test = new GPURegionNewtDemo01(); + test.testMe(); + } + RegionGLListener regionGLListener = null; - - public RegionNewtWindow(){ - createWindow(); - } - private void createWindow() { + GLWindow window; + + public void testMe() { GLProfile.initSingleton(true); GLProfile glp = GLProfile.getGL2ES2(); GLCapabilities caps = new GLCapabilities(glp); @@ -75,65 +68,45 @@ class RegionNewtWindow { caps.setSampleBuffers(true); caps.setNumSamples(4); // 2 samples is not enough .. System.out.println("Requested: " + caps); - final GLWindow window = GLWindow.create(caps); - window.setPosition(10, 10); - window.setSize(500, 500); - window.setTitle("GPU Curve Region Newt Demo 01 - r2t0 msaa1"); - regionGLListener = new RegionGLListener(); + + GLWindow w = GLWindow.create(caps); + w.setPosition(10, 10); + w.setSize(800, 400); + w.setTitle("GPU Curve Region Newt Demo 01 - r2t0 msaa1"); + + regionGLListener = createRegionRendererListener(w); + window.addGLEventListener(regionGLListener); + window.enablePerfLog(true); window.setVisible(true); - window.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - regionGLListener.zoomIn(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - regionGLListener.zoomOut(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - regionGLListener.move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - regionGLListener.move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - regionGLListener.move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - regionGLListener.move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - regionGLListener.rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - regionGLListener.rotate(-1); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - }); - - FPSAnimator animator = new FPSAnimator(60); + //FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); animator.add(window); - window.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent arg0) { - System.exit(0); - }; - }); animator.start(); } - private class RegionGLListener implements GLEventListener{ - RegionRenderer regionRenderer = null; - + + public RegionGLListener createRegionRendererListener(GLWindow w) { + this.window = w; + + RegionGLListener l = new RegionGLListener(); + l.attachInputListenerTo(w); + + return l; + } + + public class RegionGLListener extends GPURegionRendererListenerBase01 { OutlineShape outlineShape = null; - public RegionGLListener() {} + public RegionGLListener() { + super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); + setMatrix(-20, 00, 0f, -50, 400); + } private void createTestOutline(){ float offset = 0; - outlineShape = new OutlineShape(SVertex.factory()); + outlineShape = new OutlineShape(getRenderer().getFactory()); outlineShape.addVertex(0.0f,-10.0f, true); outlineShape.addVertex(15.0f,-10.0f, true); outlineShape.addVertex(10.0f,5.0f, false); @@ -169,64 +142,38 @@ class RegionNewtWindow { } public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); + super.init(drawable); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer = new RegionRenderer(drawable.getContext()); - regionRenderer.setAlpha(1.0f); - regionRenderer.setColor(0.0f, 0.0f, 0.0f); + regionRenderer.init(gl); + regionRenderer.setAlpha(gl, 1.0f); + regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); //gl.glSampleCoverage(0.95f, false); //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); + createTestOutline(); } - float ang = 0; - float zoom = -70; - float xTran = -20; - float yTran = 5; - public void display(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - regionRenderer.resetMatrix(); - regionRenderer.translate(xTran, yTran, zoom); - regionRenderer.rotate(ang, 0, 1, 0); - - try { - regionRenderer.renderOutlineShape(outlineShape, new float[]{0,0,0}); - } catch (Exception e) { - e.printStackTrace(); - } - } - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ - GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.glViewport(xstart, ystart, width, height); - - regionRenderer.reshape(drawable, 45.0f, (float)width / (float)height, 0.1f, 7000.0f); - } + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + regionRenderer.resetModelview(null); + regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); + regionRenderer.rotate(gl, getAngle(), 0, 1, 0); - public void zoomIn(){ - zoom++; - } - public void zoomOut(){ - zoom--; - } - public void move(float x, float y){ - xTran += x; - yTran += y; - } - public void rotate(float delta){ - ang+= delta; - ang%=360; - } - public void dispose(GLAutoDrawable arg0) { - regionRenderer.clearCached(); - - } + regionRenderer.renderOutlineShape(gl, outlineShape, getPosition(), getTexSize()); + } } } diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java old mode 100755 new mode 100644 index 19889ac6e..a7b56ad42 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -32,193 +32,145 @@ import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.event.WindowAdapter; -import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.Animator; /** Demonstrate the rendering of multiple OutlineShapes * into one region * */ public class GPURegionNewtDemo02 { - private static void create(){ - new RegionsNewtWindow(); - } - public static void main(String[] args) { - create(); - } -} - -class RegionsNewtWindow { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GPURegionNewtDemo02 test = new GPURegionNewtDemo02(); + test.testMe(); + } + RegionGLListener regionGLListener = null; - - public RegionsNewtWindow(){ - createWindow(); - } - private void createWindow() { + GLWindow window; + public void testMe() { GLProfile.initSingleton(true); - GLProfile glp = GLProfile.getGL2ES2(); - GLCapabilities caps = new GLCapabilities(glp); - System.out.println("Requested: "+caps); - final GLWindow window = GLWindow.create(caps); - window.setPosition(10, 10); - window.setSize(500, 500); - - window.setTitle("GPU Curve Region Newt Demo 02 - r2t0 msaa0"); - regionGLListener = new RegionGLListener(); - window.addGLEventListener(regionGLListener); - + GLProfile glp = GLProfile.get(GLProfile.GL3); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + System.out.println("Requested: " + caps); + + GLWindow w = GLWindow.create(caps); + w.setPosition(10, 10); + w.setSize(800, 400); + w.setTitle("GPU Curve Region Newt Demo 02 - r2t1 msaa0"); + + regionGLListener = createRegionRendererListener(w); + window.addGLEventListener(regionGLListener); + + window.enablePerfLog(true); window.setVisible(true); - window.addKeyListener(new KeyListener() { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - regionGLListener.zoomIn(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - regionGLListener.zoomOut(); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - regionGLListener.move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - regionGLListener.move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - regionGLListener.move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - regionGLListener.move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - regionGLListener.rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - regionGLListener.rotate(-1); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - }); - - FPSAnimator animator = new FPSAnimator(60); + //FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); animator.add(window); - window.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent arg0) { - System.exit(0); - }; - }); animator.start(); } - private class RegionGLListener implements GLEventListener{ - RegionRenderer regionRenderer = null; - - OutlineShape[] outlineShapes = new OutlineShape[2]; + + public RegionGLListener createRegionRendererListener(GLWindow w) { + this.window = w; + + RegionGLListener l = new RegionGLListener(); + l.attachInputListenerTo(w); + + return l; + } + + public class RegionGLListener extends GPURegionRendererListenerBase01 { + OutlineShape[] outlineShapes = new OutlineShape[2]; - public RegionGLListener() {} - - private void createTestOutline(){ - float offset = 0; - outlineShapes[0] = new OutlineShape(SVertex.factory()); - outlineShapes[0].addVertex(0.0f,-10.0f,true); - outlineShapes[0].addVertex(15.0f,-10.0f, true); - outlineShapes[0].addVertex(10.0f,5.0f, false); - outlineShapes[0].addVertex(15.0f,10.0f, true); - outlineShapes[0].addVertex(6.0f,15.0f, false); - outlineShapes[0].addVertex(5.0f,8.0f, false); - outlineShapes[0].addVertex(0.0f,10.0f,true); - outlineShapes[0].closeLastOutline(); - outlineShapes[0].addEmptyOutline(); - outlineShapes[0].addVertex(5.0f,-5.0f,true); - outlineShapes[0].addVertex(10.0f,-5.0f, false); - outlineShapes[0].addVertex(10.0f,0.0f, true); - outlineShapes[0].addVertex(5.0f,0.0f, false); - outlineShapes[0].closeLastOutline(); - - /** Same shape as above but without any off-curve vertices */ - outlineShapes[1] = new OutlineShape(SVertex.factory()); - offset = 30; - outlineShapes[1].addVertex(offset+0.0f,-10.0f, true); - outlineShapes[1].addVertex(offset+17.0f,-10.0f, true); - outlineShapes[1].addVertex(offset+11.0f,5.0f, true); - outlineShapes[1].addVertex(offset+16.0f,10.0f, true); - outlineShapes[1].addVertex(offset+7.0f,15.0f, true); - outlineShapes[1].addVertex(offset+6.0f,8.0f, true); - outlineShapes[1].addVertex(offset+0.0f,10.0f, true); - outlineShapes[1].closeLastOutline(); - outlineShapes[1].addEmptyOutline(); - outlineShapes[1].addVertex(offset+5.0f,0.0f, true); - outlineShapes[1].addVertex(offset+5.0f,-5.0f, true); - outlineShapes[1].addVertex(offset+10.0f,-5.0f, true); - outlineShapes[1].addVertex(offset+10.0f,0.0f, true); - outlineShapes[1].closeLastOutline(); + public RegionGLListener() { + super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); + setMatrix(-20, 00, 0f, -50, 400); + //setMatrix(-20, 00, 0f, -400, 400); + //setMatrix(-20, 00, 0f, -400, 400); + //setMatrix(-20, 00, 0f, -100, 800); } + + private void createTestOutline(){ + float offset = 0; + outlineShapes[0] = new OutlineShape(SVertex.factory()); + outlineShapes[0].addVertex(0.0f,-10.0f,true); + outlineShapes[0].addVertex(15.0f,-10.0f, true); + outlineShapes[0].addVertex(10.0f,5.0f, false); + outlineShapes[0].addVertex(15.0f,10.0f, true); + outlineShapes[0].addVertex(6.0f,15.0f, false); + outlineShapes[0].addVertex(5.0f,8.0f, false); + outlineShapes[0].addVertex(0.0f,10.0f,true); + outlineShapes[0].closeLastOutline(); + outlineShapes[0].addEmptyOutline(); + outlineShapes[0].addVertex(5.0f,-5.0f,true); + outlineShapes[0].addVertex(10.0f,-5.0f, false); + outlineShapes[0].addVertex(10.0f,0.0f, true); + outlineShapes[0].addVertex(5.0f,0.0f, false); + outlineShapes[0].closeLastOutline(); + + /** Same shape as above but without any off-curve vertices */ + outlineShapes[1] = new OutlineShape(SVertex.factory()); + offset = 30; + outlineShapes[1].addVertex(offset+0.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+17.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+11.0f,5.0f, true); + outlineShapes[1].addVertex(offset+16.0f,10.0f, true); + outlineShapes[1].addVertex(offset+7.0f,15.0f, true); + outlineShapes[1].addVertex(offset+6.0f,8.0f, true); + outlineShapes[1].addVertex(offset+0.0f,10.0f, true); + outlineShapes[1].closeLastOutline(); + outlineShapes[1].addEmptyOutline(); + outlineShapes[1].addVertex(offset+5.0f,0.0f, true); + outlineShapes[1].addVertex(offset+5.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,0.0f, true); + outlineShapes[1].closeLastOutline(); + } public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); + super.init(drawable); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer = new RegionRenderer(drawable.getContext()); - regionRenderer.setAlpha(1.0f); - regionRenderer.setColor(0.0f, 0.0f, 0.0f); + regionRenderer.init(gl); + regionRenderer.setAlpha(gl, 1.0f); + regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + //gl.glSampleCoverage(0.95f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); + createTestOutline(); } - float ang = 0; - float zoom = -70; - float xTran = -20; - float yTran = 5; - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); + GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - regionRenderer.resetMatrix(); - regionRenderer.translate(xTran, yTran, zoom); - regionRenderer.rotate(ang, 0, 1, 0); + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + regionRenderer.resetModelview(null); + regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); + regionRenderer.rotate(gl, getAngle(), 0, 1, 0); - try { - regionRenderer.renderOutlineShapes(outlineShapes, new float[]{0,0,0}); - } catch (Exception e) { - e.printStackTrace(); - } - } - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height){ - GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.glViewport(xstart, ystart, width, height); - - regionRenderer.reshape(drawable, 45.0f, (float)width / (float)height, 0.1f, 7000.0f); - } - - public void zoomIn(){ - zoom++; - } - public void zoomOut(){ - zoom--; - } - public void move(float x, float y){ - xTran += x; - yTran += y; - } - public void rotate(float delta){ - ang+= delta; - ang%=360; - } - public void dispose(GLAutoDrawable arg0) { - regionRenderer.clearCached(); + regionRenderer.renderOutlineShapes(gl, outlineShapes, getPosition(), getTexSize()); - } + } } } diff --git a/src/demo/GPURegionRendererListenerBase01.java b/src/demo/GPURegionRendererListenerBase01.java new file mode 100644 index 000000000..19742a17a --- /dev/null +++ b/src/demo/GPURegionRendererListenerBase01.java @@ -0,0 +1,53 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import jogamp.graph.curve.opengl.RegionRendererImpl01; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.geom.Vertex; + +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 3/4: font +/- + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - s: toogle draw 'font set' + * - f: toggle draw fps + * - v: toggle v-sync + * - space: toggle font (ubuntu/java) + */ +public abstract class GPURegionRendererListenerBase01 extends GPURendererListenerBase01 { + OutlineShape outlineShape = null; + + public GPURegionRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { + super(new RegionRendererImpl01(factory, mode), debug, trace); + } +} \ No newline at end of file diff --git a/src/demo/GPURendererListenerBase01.java b/src/demo/GPURendererListenerBase01.java new file mode 100644 index 000000000..ae72e6f66 --- /dev/null +++ b/src/demo/GPURendererListenerBase01.java @@ -0,0 +1,231 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLRunnable; + +import com.jogamp.graph.curve.opengl.Renderer; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; + +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - v: toggle v-sync + */ +public abstract class GPURendererListenerBase01 implements GLEventListener { + private Screenshot screenshot; + private Renderer renderer; + private boolean debug; + private boolean trace; + + private KeyAction keyAction; + + private volatile GLAutoDrawable autoDrawable = null; + + private final float[] position = new float[] {0,0,0}; + + private float xTran = -10; + private float yTran = 10; + private float ang = 0f; + private float zoom = -70f; + private int texSize = 400; + + boolean updateMatrix = true; + + public GPURendererListenerBase01(Renderer renderer, boolean debug, boolean trace) { + this.renderer = renderer; + this.debug = debug; + this.trace = trace; + this.screenshot = new Screenshot(); + } + + public final Renderer getRenderer() { return renderer; } + public final float getZoom() { return zoom; } + public final float getXTran() { return xTran; } + public final float getYTran() { return yTran; } + public final float getAngle() { return ang; } + public final int getTexSize() { return texSize; } + public final float[] getPosition() { return position; } + + public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) { + this.xTran = xtrans; + this.yTran = ytrans; + this.ang = angle; + this.zoom = zoom; + this.texSize = fbosize; + updateMatrix = true; + } + + public void init(GLAutoDrawable drawable) { + autoDrawable = drawable; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + } + + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glViewport(xstart, ystart, width, height); + renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f); + + dumpMatrix(); + } + + public void dispose(GLAutoDrawable drawable) { + autoDrawable = null; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + screenshot.dispose(); + renderer.dispose(gl); + } + + public void zoom(int v){ + zoom += v; + updateMatrix = true; + dumpMatrix(); + } + + public void move(float x, float y){ + xTran += x; + yTran += y; + updateMatrix = true; + dumpMatrix(); + } + public void rotate(float delta){ + ang += delta; + ang %= 360.0f; + updateMatrix = true; + dumpMatrix(); + } + + void dumpMatrix() { + System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang); + } + + /** Attach the input listener to the window */ + public void attachInputListenerTo(GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + } + } + + public void detachFrom(GLWindow window) { + if ( null == keyAction ) { + return; + } + window.removeGLEventListener(this); + window.removeKeyListener(keyAction); + } + + public void printScreen(GLAutoDrawable drawable, String dir, String tech, String objName, boolean exportAlpha) throws GLException, IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize, objName); + + String filename = dir + tech + sw +".tga"; + screenshot.surface2File(drawable, filename /*, exportAlpha */); + } + + public class KeyAction implements KeyListener { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_1){ + zoom(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + zoom(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + texSize -= 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + texSize += 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + rotate(-1); + } + else if(arg0.getKeyChar() == 'v') { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + public void run(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + int i = gl.getSwapInterval(); + i = i==0 ? 1 : 0; + gl.setSwapInterval(i); + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetCounter(); + } + System.err.println("Swap Interval: "+i); + } + }); + } + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + } +} diff --git a/src/demo/GPUTextGLListenerBase01.java b/src/demo/GPUTextGLListenerBase01.java deleted file mode 100644 index 238a733ce..000000000 --- a/src/demo/GPUTextGLListenerBase01.java +++ /dev/null @@ -1,324 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLException; -import javax.media.opengl.GLPipelineFactory; -import javax.media.opengl.GLRunnable; - -import com.jogamp.graph.curve.opengl.TextRenderer; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.awt.Screenshot; - -/** - * - * Action Keys: - * - 1/2: zoom in/out - * - 3/4: font +/- - * - 6/7: 2nd pass texture size - * - 0/9: rotate - * - s: toogle draw 'font set' - * - f: toggle draw fps - * - v: toggle v-sync - * - space: toggle font (ubuntu/java) - */ -public abstract class GPUTextGLListenerBase01 implements GLEventListener { - Vertex.Factory vfactory; - protected TextRenderer textRenderer; - int fontSet = FontFactory.UBUNTU; - Font font; - boolean debug; - boolean trace; - - KeyAction keyAction; - - volatile GLAutoDrawable autoDrawable = null; - boolean drawFontSet = true; - boolean drawFPS = true; - boolean updateFont = true; - int fontSize = 40; - final int fontSizeModulo = 100; - - final float[] position = new float[] {0,0,0}; - - float xTran = -10; - float yTran = 10; - float ang = 0f; - float zoom = -70f; - int texSize = 400; - - boolean updateMatrix = true; - static final String text1; - static final String text2; - - static { - text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; - text2 = "The quick brown fox jumps over the lazy dog"; - } - - public GPUTextGLListenerBase01(Vertex.Factory vfactory, int mode, boolean debug, boolean trace) { - // this.font = FontFactory.get(FontFactory.JAVA).getDefault(); - this.font = FontFactory.get(fontSet).getDefault(); - this.vfactory = vfactory; - this.textRenderer = new TextRenderer(vfactory, mode); - this.debug = debug; - this.trace = trace; - } - - public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) { - this.xTran = xtrans; - this.yTran = ytrans; - this.ang = angle; - this.zoom = zoom; - this.texSize = fbosize; - updateMatrix = true; - } - - public void init(GLAutoDrawable drawable) { - autoDrawable = drawable; - GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(debug) { - gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); - } - if(trace) { - gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); - } - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - } - - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glViewport(xstart, ystart, width, height); - textRenderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f); - - dumpMatrix(true); - } - protected boolean printScreen = true; - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - if(drawFPS || drawFontSet || updateMatrix) { - final int width = drawable.getWidth(); - final int height = drawable.getHeight(); - final GLAnimatorControl animator = drawable.getAnimator(); - final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFrames()>10; - - if(_drawFPS || drawFontSet) { - textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f); - } - if(_drawFPS) { - final float fps = ( animator.getTotalFrames() * 1000.0f ) / (float) animator.getDuration() ; - final String fpsS = String.valueOf(fps); - final int fpsSp = fpsS.indexOf('.'); - textRenderer.resetMatrix(null); - textRenderer.translate(gl, 0, 0, -6000); - textRenderer.renderString3D(gl, font, fpsS.substring(0, fpsSp+2), position, fontSize, texSize); - } - if(drawFontSet) { - textRenderer.resetMatrix(null); - textRenderer.translate(gl, 0, height-50, -6000); - textRenderer.renderString3D(gl, font, text1, position, fontSize, texSize); - } - if(_drawFPS || drawFontSet) { - textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f); - } - - textRenderer.resetMatrix(null); - textRenderer.translate(null, xTran, yTran, zoom); - textRenderer.rotate(gl, ang, 0, 1, 0); - updateMatrix = false; - } - - textRenderer.renderString3D(gl, font, text2, position, fontSize, texSize); - } - - public void dispose(GLAutoDrawable drawable) { - autoDrawable = null; - GL2ES2 gl = drawable.getGL().getGL2ES2(); - textRenderer.dispose(gl); - } - - public void fontIncr(int v) { - fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; - updateFont = true; - dumpMatrix(true); - } - - public void zoom(int v){ - zoom += v; - updateMatrix = true; - dumpMatrix(false); - } - - public void nextFontSet() { - fontSet = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; - font = FontFactory.get(fontSet).getDefault(); - } - - public void setFontSet(int set, int family, int stylebits) { - fontSet = set; - font = FontFactory.get(fontSet).get(family, stylebits); - } - - public void move(float x, float y){ - xTran += x; - yTran += y; - updateMatrix = true; - dumpMatrix(false); - } - public void rotate(float delta){ - ang += delta; - ang %= 360.0f; - updateMatrix = true; - dumpMatrix(false); - } - - void dumpMatrix(boolean bbox) { - System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang +" fontSize "+fontSize); - if(bbox) { - System.err.println("bbox: "+font.getStringBounds(text2, fontSize)); - } - } - - public void attachTo(GLWindow window) { - if ( null == keyAction ) { - keyAction = new KeyAction(); - } - window.addGLEventListener(this); - window.addKeyListener(keyAction); - } - - public void detachFrom(GLWindow window) { - if ( null == keyAction ) { - return; - } - window.removeGLEventListener(this); - window.removeKeyListener(keyAction); - } - - public void printScreen(String dir, String tech, int width, int height, boolean exportAlpha) throws GLException, IOException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.printf("-%03dx%03d-Z%04d-T%04d-%s", width, height, (int)Math.abs(zoom), texSize, font.getName()); - - String filename = dir + tech + sw +".tga"; - Screenshot.writeToTargaFile(new File(filename), width, height, exportAlpha); - } - - public class KeyAction implements KeyListener { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - zoom(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - zoom(-10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_3){ - fontIncr(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_4){ - fontIncr(-10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_6){ - texSize -= 10; - System.err.println("Tex Size: " + texSize); - } - else if(arg0.getKeyCode() == KeyEvent.VK_7){ - texSize += 10; - System.err.println("Tex Size: " + texSize); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - rotate(-1); - } - else if(arg0.getKeyChar() == 's') { - drawFontSet = !drawFontSet; - System.err.println("Draw font set: "+drawFontSet); - } - else if(arg0.getKeyChar() == 'f'){ - drawFPS = !drawFPS; - System.err.println("Draw FPS: "+drawFPS); - } - else if(arg0.getKeyChar() == 'v') { - if(null != autoDrawable) { - autoDrawable.invoke(false, new GLRunnable() { - public void run(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - int i = gl.getSwapInterval(); - i = i==0 ? 1 : 0; - gl.setSwapInterval(i); - final GLAnimatorControl a = drawable.getAnimator(); - if( null != a ) { - a.resetCounter(); - } - System.err.println("Swap Interval: "+i); - } - }); - } - } - else if(arg0.getKeyChar() == ' ') { - nextFontSet(); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - } -} \ No newline at end of file diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java index 934eba1ba..9a3067548 100644 --- a/src/demo/GPUTextNewtDemo01.java +++ b/src/demo/GPUTextNewtDemo01.java @@ -34,6 +34,7 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; @@ -58,14 +59,14 @@ public class GPUTextNewtDemo01 { caps.setNumSamples(4); // 2 samples is not enough .. System.out.println("Requested: "+caps); - window = GLWindow.create(caps); - + window = GLWindow.create(caps); window.setPosition(10, 10); window.setSize(800, 400); - window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); + textGLListener = new TextGLListener(); - textGLListener.attachTo(window); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); window.enablePerfLog(true); window.setVisible(true); @@ -75,7 +76,7 @@ public class GPUTextNewtDemo01 { animator.start(); } - private class TextGLListener extends GPUTextGLListenerBase01 { + private class TextGLListener extends GPUTextRendererListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); // FBO size unrelated with 1 pass @@ -85,10 +86,12 @@ public class GPUTextNewtDemo01 { } public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - super.init(drawable); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + gl.setSwapInterval(1); gl.glEnable(GL2ES2.GL_DEPTH_TEST); textRenderer.init(gl); diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java index b46053f1d..2078527dc 100644 --- a/src/demo/GPUTextNewtDemo02.java +++ b/src/demo/GPUTextNewtDemo02.java @@ -34,6 +34,7 @@ import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLProfile; import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.Animator; @@ -52,8 +53,7 @@ public class GPUTextNewtDemo02 { public static void main(String[] args) { GPUTextNewtDemo02 test = new GPUTextNewtDemo02(); - test.testMe(); - + test.testMe(); } GLWindow window; @@ -61,7 +61,7 @@ public class GPUTextNewtDemo02 { public void testMe() { GLProfile.initSingleton(true); - GLProfile glp = GLProfile.get(GLProfile.GL3bc); + GLProfile glp = GLProfile.get(GLProfile.GL3); GLCapabilities caps = new GLCapabilities(glp); caps.setAlphaBits(4); @@ -74,7 +74,8 @@ public class GPUTextNewtDemo02 { window.setTitle("GPU Text Newt Demo 02 - r2t1 msaa0"); textGLListener = new TextGLListener(); - textGLListener.attachTo(window); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); window.enablePerfLog(true); window.setVisible(true); @@ -85,7 +86,7 @@ public class GPUTextNewtDemo02 { animator.start(); } - private class TextGLListener extends GPUTextGLListenerBase01 { + private class TextGLListener extends GPUTextRendererListenerBase01 { public TextGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); // FIXME: Rami will fix FBO size !! @@ -95,9 +96,11 @@ public class GPUTextNewtDemo02 { } public void init(GLAutoDrawable drawable) { + super.init(drawable); + GL3 gl = drawable.getGL().getGL3(); - super.init(drawable); + final TextRenderer textRenderer = (TextRenderer) getRenderer(); gl.setSwapInterval(1); gl.glEnable(GL3.GL_DEPTH_TEST); diff --git a/src/demo/GPUTextRendererListenerBase01.java b/src/demo/GPUTextRendererListenerBase01.java new file mode 100644 index 000000000..4ee4f62de --- /dev/null +++ b/src/demo/GPUTextRendererListenerBase01.java @@ -0,0 +1,190 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package demo; + +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLException; +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; + +/** + * + * GPURendererListenerBase01 Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - v: toggle v-sync + * + * Additional Keys: + * - 3/4: font +/- + * - s: toogle draw 'font set' + * - f: toggle draw fps + * - space: toggle font (ubuntu/java) + */ +public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 { + int fontSet = FontFactory.UBUNTU; + Font font; + + boolean drawFontSet = true; + boolean drawFPS = true; + boolean updateFont = true; + int fontSize = 40; + final int fontSizeModulo = 100; + + static final String text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; + static final String text2 = "The quick brown fox jumps over the lazy dog"; + + public GPUTextRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { + super(TextRenderer.create(factory, mode), debug, trace); + this.font = FontFactory.get(fontSet).getDefault(); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + + if(drawFPS || drawFontSet || updateMatrix) { + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + final GLAnimatorControl animator = drawable.getAnimator(); + final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFrames()>10; + + if(_drawFPS || drawFontSet) { + textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f); + } + if(_drawFPS) { + final float fps = ( animator.getTotalFrames() * 1000.0f ) / (float) animator.getDuration() ; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + textRenderer.resetModelview(null); + textRenderer.translate(gl, 0, 0, -6000); + textRenderer.renderString3D(gl, font, fpsS.substring(0, fpsSp+2), getPosition(), fontSize, getTexSize()); + } + if(drawFontSet) { + textRenderer.resetModelview(null); + textRenderer.translate(gl, 0, height-50, -6000); + textRenderer.renderString3D(gl, font, text1, getPosition(), fontSize, getTexSize()); + } + if(_drawFPS || drawFontSet) { + textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f); + } + + textRenderer.resetModelview(null); + textRenderer.translate(null, getXTran(), getYTran(), getZoom()); + textRenderer.rotate(gl, getAngle(), 0, 1, 0); + updateMatrix = false; + } + + textRenderer.renderString3D(gl, font, text2, getPosition(), fontSize, getTexSize()); + } + + public void fontIncr(int v) { + fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; + updateFont = true; + dumpMatrix(true); + } + + public void nextFontSet() { + fontSet = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; + font = FontFactory.get(fontSet).getDefault(); + } + + public void setFontSet(int set, int family, int stylebits) { + fontSet = set; + font = FontFactory.get(fontSet).get(family, stylebits); + } + + void dumpMatrix(boolean bbox) { + System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZoom() + " @"+getAngle() +" fontSize "+fontSize); + if(bbox) { + System.err.println("bbox: "+font.getStringBounds(text2, fontSize)); + } + } + + KeyAction keyAction = null; + + @Override + public void attachInputListenerTo(GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + super.attachInputListenerTo(window); + } + + } + + @Override + public void detachFrom(GLWindow window) { + super.detachFrom(window); + if ( null == keyAction ) { + return; + } + window.removeKeyListener(keyAction); + } + + public void printScreen(GLAutoDrawable drawable, String dir, String tech, boolean exportAlpha) throws GLException, IOException { + printScreen(drawable, dir, tech, font.getName(), exportAlpha); + } + + public class KeyAction implements KeyListener { + public void keyPressed(KeyEvent arg0) { + if(arg0.getKeyCode() == KeyEvent.VK_3){ + fontIncr(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_4){ + fontIncr(-10); + } + else if(arg0.getKeyChar() == 's') { + drawFontSet = !drawFontSet; + System.err.println("Draw font set: "+drawFontSet); + } + else if(arg0.getKeyChar() == 'f'){ + drawFPS = !drawFPS; + System.err.println("Draw FPS: "+drawFPS); + } + else if(arg0.getKeyChar() == ' ') { + nextFontSet(); + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + } +} \ No newline at end of file diff --git a/src/demo/ReadBufferUtil.java b/src/demo/ReadBufferUtil.java new file mode 100644 index 000000000..1de61974b --- /dev/null +++ b/src/demo/ReadBufferUtil.java @@ -0,0 +1,107 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package demo; + +import com.jogamp.opengl.util.GLBuffers; +import java.nio.*; +import javax.media.opengl.*; + +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureData; + +public class ReadBufferUtil { + protected int readPixelSizeLast = 0; + protected Buffer readPixelBuffer = null; + protected TextureData readTextureData = null; + protected Texture readTexture = new Texture(GL.GL_TEXTURE_2D); + + public Buffer getPixelBuffer() { return readPixelBuffer; } + public void rewindPixelBuffer() { readPixelBuffer.rewind(); } + + public TextureData getTextureData() { return readTextureData; } + public Texture getTexture() { return readTexture; } + + public boolean isValid() { + return null!=readTexture && null!=readTextureData && null!=readPixelBuffer ; + } + + public void fetchOffscreenTexture(GLDrawable drawable, GL gl) { + int readPixelSize = drawable.getWidth() * drawable.getHeight() * 3 ; // RGB + boolean newData = false; + if(readPixelSize>readPixelSizeLast) { + readPixelBuffer = GLBuffers.newDirectGLBuffer(GL.GL_UNSIGNED_BYTE, readPixelSize); + readPixelSizeLast = readPixelSize ; + try { + readTextureData = new TextureData( + gl.getGLProfile(), + // gl.isGL2GL3()?gl.GL_RGBA:gl.GL_RGB, + GL.GL_RGB, + drawable.getWidth(), drawable.getHeight(), + 0, + GL.GL_RGB, + GL.GL_UNSIGNED_BYTE, + false, false, + false /* flip */, + readPixelBuffer, + null /* Flusher */); + newData = true; + } catch (Exception e) { + readTextureData = null; + readPixelBuffer = null; + readPixelSizeLast = 0; + throw new RuntimeException("can not fetch offscreen texture", e); + } + } + if(null!=readPixelBuffer) { + readPixelBuffer.clear(); + gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, readPixelBuffer); + readPixelBuffer.rewind(); + if(newData) { + readTexture.updateImage(readTextureData); + } else { + readTexture.updateSubImage(readTextureData, 0, + 0, 0, // src offset + 0, 0, // dst offset + drawable.getWidth(), drawable.getHeight()); + } + readPixelBuffer.rewind(); + } + } + + @SuppressWarnings("deprecation") + public void dispose() { + readTexture.dispose(); + readTextureData = null; + readPixelBuffer.clear(); + readPixelBuffer = null; + readPixelSizeLast = 0; + } + +} + diff --git a/src/demo/Screenshot.java b/src/demo/Screenshot.java new file mode 100644 index 000000000..8e05b17ea --- /dev/null +++ b/src/demo/Screenshot.java @@ -0,0 +1,39 @@ +package demo; + +import java.io.File; +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; + +import com.jogamp.opengl.util.texture.TextureIO; + +public class Screenshot { + + ReadBufferUtil readBufferUtil = new ReadBufferUtil(); + + public void dispose() { + readBufferUtil.dispose(); + } + + public void surface2File(GLAutoDrawable drawable, String filename) { + GL gl = drawable.getGL(); + // FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec + gl.glFinish(); + readBufferUtil.fetchOffscreenTexture(drawable, gl); + gl.glFinish(); + try { + surface2File(filename); + } catch (IOException ex) { + throw new RuntimeException("can not write survace to file", ex); + } + } + + void surface2File(String filename) throws IOException { + File file = new File(filename); + TextureIO.write(readBufferUtil.getTextureData(), file); + System.err.println("Wrote: " + file.getAbsolutePath() + ", ..."); + readBufferUtil.rewindPixelBuffer(); + } + +} diff --git a/src/jogamp/graph/curve/opengl/RegionRendererImpl01.java b/src/jogamp/graph/curve/opengl/RegionRendererImpl01.java new file mode 100755 index 000000000..c1f293fff --- /dev/null +++ b/src/jogamp/graph/curve/opengl/RegionRendererImpl01.java @@ -0,0 +1,206 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + + +public class RegionRendererImpl01 extends RegionRenderer { + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 3.0f); + + public RegionRendererImpl01(Vertex.Factory factory, int type) { + super(factory, type); + } + + protected boolean initImpl(GL2ES2 gl) { + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("RegionRenderer: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, RegionRendererImpl01.class, + "shader", "shader/bin", "curverenderer01"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, RegionRendererImpl01.class, + "shader", "shader/bin", "curverenderer01"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("RegionRenderer: Couldn't link program: "+sp); + } + + st = new ShaderState(); + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetModelview(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_sharpness)) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_alpha)) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_color)) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_strength)) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + if(DEBUG) { + System.err.println("RegionRendererImpl01 initialized: " + Thread.currentThread()+" "+st); + } + return true; + } + + @Override + protected void disposeImpl(GL2ES2 gl) { + } + + + @Override + public float getAlpha() { + return mgl_alpha.floatValue(); + } + + @Override + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } + } + + @Override + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + + @Override + public void renderOutlineShape(GL2ES2 gl, OutlineShape outlineShape, float[] position, int texSize) { + if(!isInitialized()){ + throw new GLException("RegionRendererImpl01: not initialized!"); + } + int hashCode = getHashCode(outlineShape); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(gl, outlineShape, mgl_sharpness.floatValue()); + regions.put(hashCode, region); + } + region.render(pmvMatrix, vp_width, vp_height, texSize); + } + + @Override + public void renderOutlineShapes(GL2ES2 gl, OutlineShape[] outlineShapes, float[] position, int texSize) { + if(!isInitialized()){ + throw new GLException("RegionRendererImpl01: not initialized!"); + } + + int hashCode = getHashCode(outlineShapes); + Region region = regions.get(hashCode); + + if(null == region) { + region = createRegion(gl, outlineShapes, mgl_sharpness.floatValue()); + regions.put(hashCode, region); + } + region.render(pmvMatrix, vp_width, vp_height, texSize); + } +} diff --git a/src/jogamp/graph/curve/opengl/TextRendererImpl01.java b/src/jogamp/graph/curve/opengl/TextRendererImpl01.java new file mode 100644 index 000000000..aa3202805 --- /dev/null +++ b/src/jogamp/graph/curve/opengl/TextRendererImpl01.java @@ -0,0 +1,189 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import jogamp.graph.curve.text.GlyphString; + +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; + +public class TextRendererImpl01 extends TextRenderer { + /**Sharpness is equivalent to the value of t value of texture coord + * on the off-curve vertex. The high value of sharpness will + * result in high curvature. + */ + private GLUniformData mgl_sharpness = new GLUniformData("p1y", 0.5f); + GLUniformData mgl_alpha = new GLUniformData("g_alpha", 1.0f); + private GLUniformData mgl_color = new GLUniformData("g_color", 3, FloatBuffer.allocate(3)); + private GLUniformData mgl_strength = new GLUniformData("a_strength", 1.8f); + + public TextRendererImpl01(Vertex.Factory factory, int type) { + super(factory, type); + } + + @Override + protected boolean initImpl(GL2ES2 gl){ + boolean VBOsupported = gl.isFunctionAvailable("glGenBuffers") && + gl.isFunctionAvailable("glBindBuffer") && + gl.isFunctionAvailable("glBufferData") && + gl.isFunctionAvailable("glDrawElements") && + gl.isFunctionAvailable("glVertexAttribPointer") && + gl.isFunctionAvailable("glDeleteBuffers"); + + if(DEBUG) { + System.err.println("TextRendererImpl01: VBO Supported = " + VBOsupported); + } + + if(!VBOsupported){ + return false; + } + + gl.glEnable(GL2ES2.GL_BLEND); + gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA); + + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, 1, TextRendererImpl01.class, + "shader", "shader/bin", "curverenderer01"); + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, 1, TextRendererImpl01.class, + "shader", "shader/bin", "curverenderer01"); + + ShaderProgram sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + + if(!sp.link(gl, System.err)) { + throw new GLException("TextRendererImpl01: Couldn't link program: "+sp); + } + + st.attachShaderProgram(gl, sp); + gl.glBindAttribLocation(sp.id(), 0, "v_position"); + gl.glBindAttribLocation(sp.id(), 1, "texCoord"); + + st.glUseProgram(gl, true); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + resetModelview(null); + + mgl_PMVMatrix = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + if(!st.glUniform(gl, mgl_PMVMatrix)) { + if(DEBUG){ + System.err.println("Error setting PMVMatrix in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_sharpness)) { + if(DEBUG){ + System.err.println("Error setting sharpness in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_alpha)) { + if(DEBUG){ + System.err.println("Error setting global alpha in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_color)) { + if(DEBUG){ + System.err.println("Error setting global color in shader: "+st); + } + return false; + } + + if(!st.glUniform(gl, mgl_strength)) { + System.err.println("Error setting antialias strength in shader: "+st); + } + + if(DEBUG) { + System.err.println("TextRendererImpl01 initialized: " + Thread.currentThread()+" "+st); + } + return true; + } + + @Override + protected void disposeImpl(GL2ES2 gl) { + } + + @Override + public float getAlpha() { + return mgl_alpha.floatValue(); + } + + @Override + public void setAlpha(GL2ES2 gl, float alpha_t) { + mgl_alpha.setData(alpha_t); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_alpha); + } + } + + @Override + public void setColor(GL2ES2 gl, float r, float g, float b){ + FloatBuffer fb = (FloatBuffer) mgl_color.getBuffer(); + fb.put(0, r); + fb.put(1, r); + fb.put(2, r); + if(null != gl && st.inUse()) { + st.glUniform(gl, mgl_color); + } + } + + @Override + public void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize) { + if(!isInitialized()){ + throw new GLException("TextRendererImpl01: not initialized!"); + } + String fontStrHash = getTextHashCode(font, str, fontSize); + GlyphString glyphString = strings.get(fontStrHash); + if(null == glyphString) { + glyphString = createString(gl, font, fontSize, str, mgl_sharpness.floatValue()); + strings.put(fontStrHash, glyphString); + } + + glyphString.renderString3D(pmvMatrix, vp_width, vp_height, texSize); + } + +} diff --git a/src/jogamp/graph/curve/opengl/shader/curverenderer01.fp b/src/jogamp/graph/curve/opengl/shader/curverenderer01.fp new file mode 100644 index 000000000..2b3a0ce1d --- /dev/null +++ b/src/jogamp/graph/curve/opengl/shader/curverenderer01.fp @@ -0,0 +1,99 @@ +//#version 100 + +uniform float p1y; +uniform float g_alpha; +uniform vec3 g_color; +uniform float a_strength; + +varying vec2 v_texCoord; + +vec3 b_color = vec3(0.0, 0.0, 0.0); + +uniform sampler2D texture; +vec4 weights = vec4(0.075, 0.06, 0.045, 0.025); + +void main (void) +{ + vec2 rtex = vec2(abs(v_texCoord.x),abs(v_texCoord.y)); + vec3 c = g_color; + + float alpha = 0.0; + + if((v_texCoord.x == 0.0) && (v_texCoord.y == 0.0)){ + alpha = g_alpha; + } + else if((v_texCoord.x >= 5.0)){ + vec2 dfx = dFdx(v_texCoord); + vec2 dfy = dFdy(v_texCoord); + + vec2 size = 1.0/textureSize(texture,0); //version 130 + rtex -= 5.0; + vec4 t = texture2D(texture, rtex)* 0.18; + + t += texture2D(texture, rtex + size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(1, 0)))*weights.x; + t += texture2D(texture, rtex + size*(vec2(0, 1)))*weights.x; + t += texture2D(texture, rtex - size*(vec2(0, 1)))*weights.x; + + t += texture2D(texture, rtex + 2.0*size*(vec2(1, 0))) *weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(1, 0)))*weights.y; + t += texture2D(texture, rtex + 2.0*size*(vec2(0, 1)))*weights.y; + t += texture2D(texture, rtex - 2.0*size*(vec2(0, 1)))*weights.y; + + t += texture2D(texture, rtex + 3.0*size*(vec2(1, 0))) *weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(1, 0)))*weights.z; + t += texture2D(texture, rtex + 3.0*size*(vec2(0, 1)))*weights.z; + t += texture2D(texture, rtex - 3.0*size*(vec2(0, 1)))*weights.z; + + t += texture2D(texture, rtex + 4.0*size*(vec2(1, 0))) *weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(1, 0)))*weights.w; + t += texture2D(texture, rtex + 4.0*size*(vec2(0, 1)))*weights.w; + t += texture2D(texture, rtex - 4.0*size*(vec2(0, 1)))*weights.w; + + if(t.w == 0.0){ + discard; + } + + c = t.xyz; + alpha = g_alpha* t.w; + } + /////////////////////////////////////////////////////////// + else if ((v_texCoord.x > 0.0) && (rtex.y > 0.0 || rtex.x == 1.0)){ + vec2 dtx = dFdx(rtex); + vec2 dty = dFdy(rtex); + + rtex.y -= 0.1; + if(rtex.y < 0.0) { + if(v_texCoord.y < 0.0) + discard; + else{ + rtex.y = 0.0; + } + } + + vec2 f = vec2((dtx.y - 2.0*p1y*dtx.x + 4.0*p1y*rtex.x*dtx.x), (dty.y - 2.0*p1y*dty.x + 4.0*p1y*rtex.x*dty.x)); + + float position = rtex.y - ((2.0 * rtex.x * p1y) * (1.0 - rtex.x)); + float d = position/(length(f)); + + float a = (0.5 - d * sign(v_texCoord.y)); + + + if (a >= 1.0) { + alpha = g_alpha; + // c = vec3(1.0,1.0,1.0); + } + else if (a <= 0.0) { + alpha = 0.0;//discard; + // c = vec3(0.0,0.0,0.0); + + } + else { + alpha = g_alpha*a; + // c = vec3(a,a,a); + mix(b_color,g_color, a); + } + } + + gl_FragColor = vec4(c, alpha); +} diff --git a/src/jogamp/graph/curve/opengl/shader/curverenderer01.vp b/src/jogamp/graph/curve/opengl/shader/curverenderer01.vp new file mode 100644 index 000000000..bc9ecb41e --- /dev/null +++ b/src/jogamp/graph/curve/opengl/shader/curverenderer01.vp @@ -0,0 +1,13 @@ +//#version 100 + +uniform mat4 mgl_PMVMatrix[2]; +attribute vec4 v_position; +attribute vec2 texCoord; + +varying vec2 v_texCoord; + +void main(void) +{ + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * v_position; + v_texCoord = texCoord.st; +} \ No newline at end of file diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java new file mode 100644 index 000000000..35f0325c9 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java @@ -0,0 +1,152 @@ +package test.com.jogamp.opengl.test.junit.graph; + +import java.io.IOException; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; + +import demo.GPURegionNewtDemo01; +import demo.GPURegionNewtDemo02; +import demo.GPURegionRendererListenerBase01; + +public class TestRegionRenderer01 { + + public static void main(String args[]) throws IOException { + String tstname = TestRegionRenderer01.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(true); + NativeWindowFactory.initSingleton(true); + } + + static void destroyWindow(GLWindow window) { + if(null!=window) { + window.destroy(); + } + } + + static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { + Assert.assertNotNull(caps); + + GLWindow window = GLWindow.create(caps); + window.setSize(width, height); + window.setPosition(10, 10); + window.setTitle(title); + Assert.assertNotNull(window); + window.setVisible(true); + + return window; + } + + @Test + public void testRegionRendererR2T01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL3); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + caps.setAlphaBits(4); + + GLWindow window = createWindow("shape-r2t1-msaa0", caps, 800,400); + + GPURegionNewtDemo02 demo02 = new GPURegionNewtDemo02(); + GPURegionNewtDemo02.RegionGLListener demo02Listener = demo02.createRegionRendererListener(window); + + RegionGLListener listener = new RegionGLListener(demo02Listener, window.getTitle(), "GPURegionNewtDemo02"); + window.addGLEventListener(listener); + + listener.setTech(-20, 00, 0f, -300, 400); + window.display(); + + listener.setTech(-20, 00, 0f, -150, 800); + window.display(); + + listener.setTech(-20, 00, 0f, -50, 1000); + window.display(); + + destroyWindow(window); + } + + @Test + public void testRegionRendererMSAA01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities caps = new GLCapabilities(glp); + caps.setOnscreen(false); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + + GLWindow window = createWindow("shape-r2t0-msaa1", caps, 800, 400); + + GPURegionNewtDemo01 demo01 = new GPURegionNewtDemo01(); + GPURegionNewtDemo01.RegionGLListener demo01Listener = demo01.createRegionRendererListener(window); + + RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegionNewtDemo01"); + window.addGLEventListener(listener); + + listener.setTech(-20, 00, 0f, -300, 400); + window.display(); + + listener.setTech(-20, 00, 0f, -150, 800); + window.display(); + + listener.setTech(-20, 00, 0f, -50, 1000); + window.display(); + + destroyWindow(window); + } + + private class RegionGLListener implements GLEventListener { + String winTitle; + String name; + GPURegionRendererListenerBase01 impl; + + public RegionGLListener(GPURegionRendererListenerBase01 impl, String title, String name) { + this.impl = impl; + this.winTitle = title; + this.name = name; + } + + public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ + impl.setMatrix(xt, yt, angle, zoom, fboSize); + } + + public void init(GLAutoDrawable drawable) { + impl.init(drawable); + } + + public void display(GLAutoDrawable drawable) { + impl.display(drawable); + + try { + impl.printScreen(drawable, "./", winTitle, name, false); + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void dispose(GLAutoDrawable drawable) { + impl.dispose(drawable); + + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + impl.reshape(drawable, x, y, width, height); + + } + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java index 501bdbb75..8f5174a89 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java @@ -16,14 +16,20 @@ import org.junit.BeforeClass; import org.junit.Test; import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.TextRenderer; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.newt.opengl.GLWindow; -import demo.GPUTextGLListenerBase01; +import demo.GPUTextRendererListenerBase01; public class TestTextRenderer01 { + public static void main(String args[]) throws IOException { + String tstname = TestRegionRenderer01.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + @BeforeClass public static void initClass() { GLProfile.initSingleton(true); @@ -51,14 +57,15 @@ public class TestTextRenderer01 { @Test public void testTextRendererR2T01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL3bc); + GLProfile glp = GLProfile.get(GLProfile.GL3); GLCapabilities caps = new GLCapabilities(glp); caps.setOnscreen(false); caps.setAlphaBits(4); - GLWindow window = createWindow("r2t1-msaa0", caps, 800,400); + GLWindow window = createWindow("text-r2t1-msaa0", caps, 800,400); TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); - textGLListener.attachTo(window); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); textGLListener.setTech(-400, -30, 0f, -1000, 400); @@ -92,9 +99,10 @@ public class TestTextRenderer01 { caps.setSampleBuffers(true); caps.setNumSamples(4); - GLWindow window = createWindow("r2t0-msaa1", caps, 800, 400); + GLWindow window = createWindow("text-r2t0-msaa1", caps, 800, 400); TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); - textGLListener.attachTo(window); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); textGLListener.setTech(-400, -30, 0f, -1000, 0); @@ -119,15 +127,15 @@ public class TestTextRenderer01 { destroyWindow(window); } - private class TextGLListener extends GPUTextGLListenerBase01 { + private class TextGLListener extends GPUTextRendererListenerBase01 { String winTitle; public TextGLListener(int type) { super(SVertex.factory(), type, false, false); } - public void attachTo(GLWindow window) { - super.attachTo(window); + public void attachInputListenerTo(GLWindow window) { + super.attachInputListenerTo(window); winTitle = window.getTitle(); } public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ @@ -139,6 +147,9 @@ public class TestTextRenderer01 { super.init(drawable); gl.setSwapInterval(1); gl.glEnable(GL.GL_DEPTH_TEST); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + textRenderer.init(gl); textRenderer.setAlpha(gl, 1.0f); textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); @@ -148,7 +159,7 @@ public class TestTextRenderer01 { super.display(drawable); try { - printScreen("./", winTitle, drawable.getWidth(), drawable.getHeight(), false); + printScreen(drawable, "./", winTitle, false); } catch (GLException e) { e.printStackTrace(); } catch (IOException e) { -- cgit v1.2.3 From ff32688c4520373468315b6dad4ec26f481bcd00 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 14:20:14 +0200 Subject: Avoid NPE in Screenshot/ReadBufferUtil --- src/demo/ReadBufferUtil.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/demo/ReadBufferUtil.java b/src/demo/ReadBufferUtil.java index 1de61974b..9a2da0d7e 100644 --- a/src/demo/ReadBufferUtil.java +++ b/src/demo/ReadBufferUtil.java @@ -95,11 +95,13 @@ public class ReadBufferUtil { } @SuppressWarnings("deprecation") - public void dispose() { + public void dispose() { readTexture.dispose(); readTextureData = null; - readPixelBuffer.clear(); - readPixelBuffer = null; + if(null != readPixelBuffer) { + readPixelBuffer.clear(); + readPixelBuffer = null; + } readPixelSizeLast = 0; } -- cgit v1.2.3 From d06d5596d18101c876c869a514e42e795ee9357c Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 14:47:19 +0200 Subject: Demo/Test: Use public API --- src/demo/GPURegionRendererListenerBase01.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/demo/GPURegionRendererListenerBase01.java b/src/demo/GPURegionRendererListenerBase01.java index 19742a17a..39a920656 100644 --- a/src/demo/GPURegionRendererListenerBase01.java +++ b/src/demo/GPURegionRendererListenerBase01.java @@ -27,9 +27,8 @@ */ package demo; -import jogamp.graph.curve.opengl.RegionRendererImpl01; - import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.geom.Vertex; /** @@ -48,6 +47,6 @@ public abstract class GPURegionRendererListenerBase01 extends GPURendererListene OutlineShape outlineShape = null; public GPURegionRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { - super(new RegionRendererImpl01(factory, mode), debug, trace); + super(RegionRenderer.create(factory, mode), debug, trace); } } \ No newline at end of file -- cgit v1.2.3 From 133edeb70921dbcae3ec7cc76f1bc6dd0cd36da8 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 16:17:09 +0300 Subject: Fix: RegionRenderer TwoPass Renderering, fix methodnames in Renderer --- src/com/jogamp/graph/curve/opengl/RegionRenderer.java | 2 +- src/com/jogamp/graph/curve/opengl/Renderer.java | 4 ++-- src/com/jogamp/graph/curve/opengl/TextRenderer.java | 2 +- src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 8 ++++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java index 4be1506d5..a1d888da9 100644 --- a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -45,7 +45,7 @@ public abstract class RegionRenderer extends Renderer { protected HashMap regions = new HashMap(); - public void flushCash() { + public void flushCache() { Iterator iterator = regions.values().iterator(); while(iterator.hasNext()){ Region region = iterator.next(); diff --git a/src/com/jogamp/graph/curve/opengl/Renderer.java b/src/com/jogamp/graph/curve/opengl/Renderer.java index a1755e003..a36cf870b 100644 --- a/src/com/jogamp/graph/curve/opengl/Renderer.java +++ b/src/com/jogamp/graph/curve/opengl/Renderer.java @@ -22,7 +22,7 @@ public abstract class Renderer { /** * Flushes all cached data */ - public abstract void flushCash(); + public abstract void flushCache(); public abstract float getAlpha(); @@ -93,7 +93,7 @@ public abstract class Renderer { } disposeImpl(gl); st.destroy(gl); - flushCash(); + flushCache(); initialized = false; } diff --git a/src/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/com/jogamp/graph/curve/opengl/TextRenderer.java index 04988a3ab..25e8b950f 100644 --- a/src/com/jogamp/graph/curve/opengl/TextRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -68,7 +68,7 @@ public abstract class TextRenderer extends Renderer { return font.getName() + "." + str.hashCode() + "." + fontSize; } - public void flushCash() { + public void flushCache() { Iterator iterator = strings.values().iterator(); while(iterator.hasNext()){ GlyphString glyphString = iterator.next(); diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java index baca05dc7..ac2be6097 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -121,8 +121,12 @@ public class VBORegion2PGL3 implements Region{ verticesBuffer.put(v.getY()); } verticesBuffer.put(v.getZ()); - - box.resize(v.getX(), -1*v.getY(), v.getZ()); + if(flipped){ + box.resize(v.getX(), -1*v.getY(), v.getZ()); + } + else{ + box.resize(v.getX(), v.getY(), v.getZ()); + } } verticesBuffer.rewind(); -- cgit v1.2.3 From 630a9ea52b16da6badb31a98b70893f8d294b4e8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 15:25:18 +0200 Subject: Remove generics notion of Type, since Vertex _is_ the lowest denominator for our implementation and curve API --- src/com/jogamp/graph/curve/OutlineShape.java | 28 ++--- src/com/jogamp/graph/curve/Region.java | 2 +- .../jogamp/graph/curve/opengl/RegionRenderer.java | 4 +- .../jogamp/graph/curve/tess/CDTriangulator2D.java | 69 ++++++------- src/com/jogamp/graph/geom/Outline.java | 29 +++--- src/com/jogamp/graph/geom/Triangle.java | 8 +- src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 6 +- src/jogamp/graph/curve/opengl/VBORegionSPES2.java | 6 +- src/jogamp/graph/curve/tess/GraphOutline.java | 24 ++--- src/jogamp/graph/curve/tess/GraphVertex.java | 34 +++--- src/jogamp/graph/curve/tess/HEdge.java | 43 ++++---- src/jogamp/graph/curve/tess/Loop.java | 114 ++++++++++----------- src/jogamp/graph/curve/text/GlyphShape.java | 2 +- src/jogamp/graph/curve/text/GlyphString.java | 8 +- 14 files changed, 185 insertions(+), 192 deletions(-) diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index 9373808f1..2a6e3745f 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -52,13 +52,13 @@ import com.jogamp.graph.curve.tess.CDTriangulator2D; public class OutlineShape { public static final int QUADRATIC_NURBS = 10; private final Vertex.Factory pointFactory; - private ArrayList> outlines = new ArrayList>(3); + private ArrayList outlines = new ArrayList(3); /** Create a new Outline based Shape */ public OutlineShape(Vertex.Factory factory) { pointFactory = factory; - outlines.add(new Outline()); + outlines.add(new Outline()); } public final Vertex.Factory pointFactory() { return pointFactory; } @@ -68,7 +68,7 @@ public class OutlineShape { * be placed at the end of the outline list. */ public void addEmptyOutline(){ - outlines.add(new Outline()); + outlines.add(new Outline()); } /** Adds an outline to the OutlineShape object @@ -77,7 +77,7 @@ public class OutlineShape { * it will do nothing. * @param outline an Outline object */ - public void addOutline(Outline outline){ + public void addOutline(Outline outline){ if(outline.isEmpty()){ return; } @@ -120,7 +120,7 @@ public class OutlineShape { * of outlines that define the shape * @return the last outline */ - public final Outline getLastOutline(){ + public final Outline getLastOutline(){ return outlines.get(outlines.size()-1); } /** Make sure that the outlines represent @@ -135,13 +135,13 @@ public class OutlineShape { } private void transformOutlinesQuadratic(){ - ArrayList> newOutlines = new ArrayList>(3); + ArrayList newOutlines = new ArrayList(3); /**loop over the outlines and make sure no * adj off-curve vertices */ - for(Outline outline:outlines){ - Outline newOutline = new Outline(); + for(Outline outline:outlines){ + Outline newOutline = new Outline(); ArrayList vertices = outline.getVertices(); int size =vertices.size()-1; @@ -165,7 +165,7 @@ public class OutlineShape { private void generateVertexIds(){ int maxVertexId = 0; - for(Outline outline:outlines){ + for(Outline outline:outlines){ ArrayList vertices = outline.getVertices(); for(Vertex vert:vertices){ vert.setId(maxVertexId); @@ -179,7 +179,7 @@ public class OutlineShape { */ public ArrayList getVertices(){ ArrayList vertices = new ArrayList(); - for(Outline polyline:outlines){ + for(Outline polyline:outlines){ vertices.addAll(polyline.getVertices()); } return vertices; @@ -189,21 +189,21 @@ public class OutlineShape { /** Triangluate the graph object * @param sharpness sharpness of the curved regions default = 0.5 */ - public ArrayList> triangulate(float sharpness){ + public ArrayList triangulate(float sharpness){ if(outlines.size() == 0){ return null; } sortOutlines(); generateVertexIds(); - CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); + CDTriangulator2D triangulator2d = new CDTriangulator2D(sharpness); for(int index = 0; index< outlines.size();index++){ - Outline outline = outlines.get(index); + Outline outline = outlines.get(index); triangulator2d.addCurve(outline); } - ArrayList> triangles = triangulator2d.generateTriangulation(); + ArrayList triangles = triangulator2d.generateTriangulation(); triangulator2d.reset(); return triangles; diff --git a/src/com/jogamp/graph/curve/Region.java b/src/com/jogamp/graph/curve/Region.java index f3a87bb7f..143b6f502 100755 --- a/src/com/jogamp/graph/curve/Region.java +++ b/src/com/jogamp/graph/curve/Region.java @@ -80,7 +80,7 @@ public interface Region { * * @see update() */ - public void addTriangles(ArrayList> tris); + public void addTriangles(ArrayList tris); /** Get the current number of vertices associated * with this region. This number is not necessary equal to diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java index 4be1506d5..602399010 100644 --- a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -63,7 +63,7 @@ public abstract class RegionRenderer extends Renderer { outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - ArrayList> triangles = (ArrayList>) outlineShape.triangulate(sharpness); + ArrayList triangles = (ArrayList) outlineShape.triangulate(sharpness); ArrayList vertices = (ArrayList) outlineShape.getVertices(); region.addVertices(vertices); region.addTriangles(triangles); @@ -84,7 +84,7 @@ public abstract class RegionRenderer extends Renderer { for(OutlineShape outlineShape:outlineShapes){ outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); - ArrayList> triangles = outlineShape.triangulate(sharpness); + ArrayList triangles = outlineShape.triangulate(sharpness); region.addTriangles(triangles); ArrayList vertices = outlineShape.getVertices(); diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index 0a7cf08d4..beef2d4a5 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -46,15 +46,15 @@ import jogamp.opengl.Debug; * Closed Regions with optional n holes. * */ -public class CDTriangulator2D { +public class CDTriangulator2D { protected static final boolean DEBUG = Debug.debug("Triangulation"); private float sharpness = 0.5f; - private ArrayList> loops; - private ArrayList vertices; + private ArrayList loops; + private ArrayList vertices; - private ArrayList> triangles; + private ArrayList triangles; private int maxTriID = 0; @@ -76,31 +76,31 @@ public class CDTriangulator2D { */ public void reset() { maxTriID = 0; - vertices = new ArrayList(); - triangles = new ArrayList>(3); - loops = new ArrayList>(); + vertices = new ArrayList(); + triangles = new ArrayList(3); + loops = new ArrayList(); } /** Add a curve to the list of profiles provided * @param polyline a bounding Outline */ - public void addCurve(Outline polyline){ - Loop loop = null; + public void addCurve(Outline polyline){ + Loop loop = null; if(!loops.isEmpty()){ loop = getContainerLoop(polyline); } if(loop == null) { - GraphOutline outline = new GraphOutline(polyline); - GraphOutline innerPoly = extractBoundaryTriangles(outline, false); + GraphOutline outline = new GraphOutline(polyline); + GraphOutline innerPoly = extractBoundaryTriangles(outline, false); vertices.addAll(polyline.getVertices()); - loop = new Loop(innerPoly, VectorUtil.CCW); + loop = new Loop(innerPoly, VectorUtil.CCW); loops.add(loop); } else { - GraphOutline outline = new GraphOutline(polyline); - GraphOutline innerPoly = extractBoundaryTriangles(outline, true); + GraphOutline outline = new GraphOutline(polyline); + GraphOutline innerPoly = extractBoundaryTriangles(outline, true); vertices.addAll(innerPoly.getPoints()); loop.addConstraintCurve(innerPoly); } @@ -109,13 +109,13 @@ public class CDTriangulator2D { /** Generate the triangulation of the provided * List of Outlines */ - public ArrayList> generateTriangulation(){ + public ArrayList generateTriangulation(){ for(int i=0;i loop = loops.get(i); + Loop loop = loops.get(i); int numTries = 0; int size = loop.computeLoopSize(); while(!loop.isSimplex()){ - Triangle tri = null; + Triangle tri = null; if(numTries > size){ tri = loop.cut(false); } @@ -140,41 +140,40 @@ public class CDTriangulator2D { break; } } - Triangle tri = loop.cut(true); + Triangle tri = loop.cut(true); if(tri != null) triangles.add(tri); } return triangles; } - @SuppressWarnings("unchecked") - private GraphOutline extractBoundaryTriangles(GraphOutline outline, boolean hole){ - GraphOutline innerOutline = new GraphOutline(); - ArrayList> outVertices = outline.getGraphPoint(); + private GraphOutline extractBoundaryTriangles(GraphOutline outline, boolean hole){ + GraphOutline innerOutline = new GraphOutline(); + ArrayList outVertices = outline.getGraphPoint(); int size = outVertices.size(); for(int i=0; i < size; i++) { - GraphVertex currentVertex = outVertices.get(i); - GraphVertex gv0 = outVertices.get((i+size-1)%size); - GraphVertex gv2 = outVertices.get((i+1)%size); - GraphVertex gv1 = currentVertex; + GraphVertex currentVertex = outVertices.get(i); + GraphVertex gv0 = outVertices.get((i+size-1)%size); + GraphVertex gv2 = outVertices.get((i+1)%size); + GraphVertex gv1 = currentVertex; if(!currentVertex.getPoint().isOnCurve()) { - T v0 = (T) gv0.getPoint().clone(); - T v2 = (T) gv2.getPoint().clone(); - T v1 = (T) gv1.getPoint().clone(); + Vertex v0 = gv0.getPoint().clone(); + Vertex v2 = gv2.getPoint().clone(); + Vertex v1 = gv1.getPoint().clone(); gv0.setBoundaryContained(true); gv1.setBoundaryContained(true); gv2.setBoundaryContained(true); - Triangle t= null; + Triangle t= null; boolean holeLike = false; if(VectorUtil.ccw(v0,v1,v2)){ - t = new Triangle(v0, v1, v2); + t = new Triangle(v0, v1, v2); } else { holeLike = true; - t = new Triangle(v2, v1, v0); + t = new Triangle(v2, v1, v0); } t.setId(maxTriID++); triangles.add(t); @@ -203,10 +202,10 @@ public class CDTriangulator2D { return innerOutline; } - private Loop getContainerLoop(Outline polyline){ - T v = polyline.getVertex(0); + private Loop getContainerLoop(Outline polyline){ + Vertex v = polyline.getVertex(0); - for (Loop loop:loops){ + for (Loop loop:loops){ if(loop.checkInside(v)){ return loop; } diff --git a/src/com/jogamp/graph/geom/Outline.java b/src/com/jogamp/graph/geom/Outline.java index 4e588623e..85b6e8001 100644 --- a/src/com/jogamp/graph/geom/Outline.java +++ b/src/com/jogamp/graph/geom/Outline.java @@ -45,9 +45,9 @@ import com.jogamp.graph.math.VectorUtil; * @see OutlineShape, Region * */ -public class Outline implements Comparable>{ +public class Outline implements Comparable { - private ArrayList vertices = new ArrayList(3); + private ArrayList vertices = new ArrayList(3); private boolean closed = false; private AABBox box = new AABBox(); @@ -63,7 +63,7 @@ public class Outline implements Comparable>{ * end of the outline loop/strip. * @param vertex Vertex to be added */ - public final void addVertex(T vertex) { + public final void addVertex(Vertex vertex) { vertices.add(vertex); box.resize(vertex.getX(), vertex.getY(), vertex.getZ()); } @@ -72,38 +72,36 @@ public class Outline implements Comparable>{ addVertex(factory, x, y, 0f, onCurve); } - @SuppressWarnings("unchecked") public final void addVertex(Vertex.Factory factory, float x, float y, float z, boolean onCurve) { Vertex v = factory.create(x, y, z); v.setOnCurve(onCurve); - addVertex((T)v); + addVertex(v); } - @SuppressWarnings("unchecked") public final void addVertex(Vertex.Factory factory, float[] coordsBuffer, int offset, int length, boolean onCurve) { Vertex v = factory.create(coordsBuffer, offset, length); v.setOnCurve(onCurve); - addVertex((T)v); + addVertex(v); } - public T getVertex(int index){ + public Vertex getVertex(int index){ return vertices.get(index); } public boolean isEmpty(){ return (vertices.size() == 0); } - public T getLastVertex(){ + public Vertex getLastVertex(){ if(isEmpty()){ return null; } return vertices.get(vertices.size()-1); } - public ArrayList getVertices() { + public ArrayList getVertices() { return vertices; } - public void setVertices(ArrayList vertices) { + public void setVertices(ArrayList vertices) { this.vertices = vertices; } public AABBox getBox() { @@ -122,11 +120,10 @@ public class Outline implements Comparable>{ public void setClosed(boolean closed) { this.closed = closed; if(closed){ - T first = vertices.get(0); - T last = getLastVertex(); + Vertex first = vertices.get(0); + Vertex last = getLastVertex(); if(!VectorUtil.checkEquality(first.getCoord(), last.getCoord())){ - @SuppressWarnings("unchecked") - T v = (T) first.clone(); + Vertex v = first.clone(); vertices.add(v); } } @@ -136,7 +133,7 @@ public class Outline implements Comparable>{ * as criteria. * @see java.lang.Comparable#compareTo(java.lang.Object) */ - public int compareTo(Outline outline) { + public int compareTo(Outline outline) { float size = box.getSize(); float newSize = outline.getBox().getSize(); if(size < newSize){ diff --git a/src/com/jogamp/graph/geom/Triangle.java b/src/com/jogamp/graph/geom/Triangle.java index 7b11ba23d..d13e8ddb1 100644 --- a/src/com/jogamp/graph/geom/Triangle.java +++ b/src/com/jogamp/graph/geom/Triangle.java @@ -27,13 +27,13 @@ */ package com.jogamp.graph.geom; -public class Triangle { +public class Triangle { private int id = Integer.MAX_VALUE; - final private T[] vertices; + final private Vertex[] vertices; private boolean[] boundaryEdges = new boolean[3]; private boolean[] boundaryVertices = null; - public Triangle(T ... v123){ + public Triangle(Vertex ... v123){ vertices = v123; } @@ -45,7 +45,7 @@ public class Triangle { this.id = id; } - public T[] getVertices() { + public Vertex[] getVertices() { return vertices; } diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java index baca05dc7..a17809d79 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java @@ -53,7 +53,7 @@ public class VBORegion2PGL3 implements Region{ private IntBuffer t_vboIds; - private ArrayList> triangles = new ArrayList>(); + private ArrayList triangles = new ArrayList(); private ArrayList vertices = new ArrayList(); private GLContext context; @@ -85,7 +85,7 @@ public class VBORegion2PGL3 implements Region{ GL3 gl = context.getGL().getGL3(); ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); - for(Triangle t:triangles){ + for(Triangle t:triangles){ if(t.getVertices()[0].getId() == Integer.MAX_VALUE){ t.getVertices()[0].setId(numVertices++); t.getVertices()[1].setId(numVertices++); @@ -338,7 +338,7 @@ public class VBORegion2PGL3 implements Region{ gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); } - public void addTriangles(ArrayList> tris) { + public void addTriangles(ArrayList tris) { triangles.addAll(tris); dirty = true; } diff --git a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java index 155d35f0b..f509dbd58 100644 --- a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -45,7 +45,7 @@ public class VBORegionSPES2 implements Region{ private int numVertices = 0; private IntBuffer vboIds; - private ArrayList> triangles = new ArrayList>(); + private ArrayList triangles = new ArrayList(); private ArrayList vertices = new ArrayList(); private GLContext context; @@ -63,7 +63,7 @@ public class VBORegionSPES2 implements Region{ GL2ES2 gl = context.getGL().getGL2ES2(); ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); - for(Triangle t:triangles){ + for(Triangle t:triangles){ final Vertex[] t_vertices = t.getVertices(); if(t_vertices[0].getId() == Integer.MAX_VALUE){ @@ -151,7 +151,7 @@ public class VBORegionSPES2 implements Region{ render(); } - public void addTriangles(ArrayList> tris) { + public void addTriangles(ArrayList tris) { triangles.addAll(tris); dirty = true; } diff --git a/src/jogamp/graph/curve/tess/GraphOutline.java b/src/jogamp/graph/curve/tess/GraphOutline.java index bb262ce5b..5dae296e5 100644 --- a/src/jogamp/graph/curve/tess/GraphOutline.java +++ b/src/jogamp/graph/curve/tess/GraphOutline.java @@ -32,27 +32,27 @@ import java.util.ArrayList; import com.jogamp.graph.geom.Outline; import com.jogamp.graph.geom.Vertex; -public class GraphOutline { - final private Outline outline; - final private ArrayList> controlpoints = new ArrayList>(3); +public class GraphOutline { + final private Outline outline; + final private ArrayList controlpoints = new ArrayList(3); public GraphOutline(){ - this.outline = new Outline(); + this.outline = new Outline(); } /**Create a control polyline of control vertices * the curve pieces can be identified by onCurve flag * of each cp the control polyline is open by default */ - public GraphOutline(Outline ol){ + public GraphOutline(Outline ol){ this.outline = ol; - ArrayList vertices = this.outline.getVertices(); - for(T v:vertices){ - this.controlpoints.add(new GraphVertex(v)); + ArrayList vertices = this.outline.getVertices(); + for(Vertex v:vertices){ + this.controlpoints.add(new GraphVertex(v)); } } - public Outline getOutline() { + public Outline getOutline() { return outline; } @@ -61,11 +61,11 @@ public class GraphOutline { }*/ - public ArrayList> getGraphPoint() { + public ArrayList getGraphPoint() { return controlpoints; } - public ArrayList getPoints() { + public ArrayList getPoints() { return outline.getVertices(); } @@ -73,7 +73,7 @@ public class GraphOutline { this.controlpoints = controlpoints; }*/ - public void addVertex(GraphVertex v) { + public void addVertex(GraphVertex v) { controlpoints.add(v); outline.addVertex(v.getPoint()); } diff --git a/src/jogamp/graph/curve/tess/GraphVertex.java b/src/jogamp/graph/curve/tess/GraphVertex.java index a474a002e..b9f95a0e7 100644 --- a/src/jogamp/graph/curve/tess/GraphVertex.java +++ b/src/jogamp/graph/curve/tess/GraphVertex.java @@ -31,16 +31,16 @@ import java.util.ArrayList; import com.jogamp.graph.geom.Vertex; -public class GraphVertex { - private T point; - private ArrayList> edges = null; +public class GraphVertex { + private Vertex point; + private ArrayList edges = null; private boolean boundaryContained = false; - public GraphVertex(T point) { + public GraphVertex(Vertex point) { this.point = point; } - public T getPoint() { + public Vertex getPoint() { return point; } @@ -59,25 +59,25 @@ public class GraphVertex { return point.getCoord(); } - public void setPoint(T point) { + public void setPoint(Vertex point) { this.point = point; } - public ArrayList> getEdges() { + public ArrayList getEdges() { return edges; } - public void setEdges(ArrayList> edges) { + public void setEdges(ArrayList edges) { this.edges = edges; } - public void addEdge(HEdge edge){ + public void addEdge(HEdge edge){ if(edges == null){ - edges = new ArrayList>(); + edges = new ArrayList(); } edges.add(edge); } - public void removeEdge(HEdge edge){ + public void removeEdge(HEdge edge){ if(edges == null) return; edges.remove(edge); @@ -85,24 +85,24 @@ public class GraphVertex { edges = null; } } - public HEdge findNextEdge(GraphVertex nextVert){ - for(HEdge e:edges){ + public HEdge findNextEdge(GraphVertex nextVert){ + for(HEdge e:edges){ if(e.getNext().getGraphPoint() == nextVert){ return e; } } return null; } - public HEdge findBoundEdge(){ - for(HEdge e:edges){ + public HEdge findBoundEdge(){ + for(HEdge e:edges){ if((e.getType() == HEdge.BOUNDARY) || (e.getType() == HEdge.HOLE)){ return e; } } return null; } - public HEdge findPrevEdge(GraphVertex prevVert){ - for(HEdge e:edges){ + public HEdge findPrevEdge(GraphVertex prevVert){ + for(HEdge e:edges){ if(e.getPrev().getGraphPoint() == prevVert){ return e; } diff --git a/src/jogamp/graph/curve/tess/HEdge.java b/src/jogamp/graph/curve/tess/HEdge.java index 5635e2c31..d1bcc6e17 100644 --- a/src/jogamp/graph/curve/tess/HEdge.java +++ b/src/jogamp/graph/curve/tess/HEdge.java @@ -31,24 +31,24 @@ import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; -public class HEdge { +public class HEdge { public static int BOUNDARY = 3; public static int INNER = 1; public static int HOLE = 2; - private GraphVertex vert; - private HEdge prev = null; - private HEdge next = null; - private HEdge sibling = null; + private GraphVertex vert; + private HEdge prev = null; + private HEdge next = null; + private HEdge sibling = null; private int type = BOUNDARY; - private Triangle triangle = null; + private Triangle triangle = null; - public HEdge(GraphVertex vert, int type) { + public HEdge(GraphVertex vert, int type) { this.vert = vert; this.type = type; } - public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) { + public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type) { this.vert = vert; this.prev = prev; this.next = next; @@ -56,8 +56,7 @@ public class HEdge { this.type = type; } - public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, - Triangle triangle) { + public HEdge(GraphVertex vert, HEdge prev, HEdge next, HEdge sibling, int type, Triangle triangle) { this.vert = vert; this.prev = prev; this.next = next; @@ -66,35 +65,35 @@ public class HEdge { this.triangle = triangle; } - public GraphVertex getGraphPoint() { + public GraphVertex getGraphPoint() { return vert; } - public void setVert(GraphVertex vert) { + public void setVert(GraphVertex vert) { this.vert = vert; } - public HEdge getPrev() { + public HEdge getPrev() { return prev; } - public void setPrev(HEdge prev) { + public void setPrev(HEdge prev) { this.prev = prev; } - public HEdge getNext() { + public HEdge getNext() { return next; } - public void setNext(HEdge next) { + public void setNext(HEdge next) { this.next = next; } - public HEdge getSibling() { + public HEdge getSibling() { return sibling; } - public void setSibling(HEdge sibling) { + public void setSibling(HEdge sibling) { this.sibling = sibling; } @@ -106,20 +105,20 @@ public class HEdge { this.type = type; } - public Triangle getTriangle() { + public Triangle getTriangle() { return triangle; } - public void setTriangle(Triangle triangle) { + public void setTriangle(Triangle triangle) { this.triangle = triangle; } - public static void connect(HEdge first, HEdge next){ + public static void connect(HEdge first, HEdge next){ first.setNext(next); next.setPrev(first); } - public static void makeSiblings(HEdge first, HEdge second){ + public static void makeSiblings(HEdge first, HEdge second){ first.setSibling(second); second.setSibling(first); } diff --git a/src/jogamp/graph/curve/tess/Loop.java b/src/jogamp/graph/curve/tess/Loop.java index 80b96b939..d2162bbeb 100644 --- a/src/jogamp/graph/curve/tess/Loop.java +++ b/src/jogamp/graph/curve/tess/Loop.java @@ -35,56 +35,55 @@ import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.math.VectorUtil; -public class Loop { - private HEdge root = null; +public class Loop { + private HEdge root = null; private AABBox box = new AABBox(); - private GraphOutline initialOutline = null; + private GraphOutline initialOutline = null; - public Loop(GraphOutline polyline, int direction){ + public Loop(GraphOutline polyline, int direction){ initialOutline = polyline; this.root = initFromPolyline(initialOutline, direction); } - public HEdge getHEdge(){ + public HEdge getHEdge(){ return root; } - public Triangle cut(boolean delaunay){ + public Triangle cut(boolean delaunay){ if(isSimplex()){ - @SuppressWarnings("unchecked") - Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(), + Triangle t = new Triangle(root.getGraphPoint().getPoint(), root.getNext().getGraphPoint().getPoint(), root.getNext().getNext().getGraphPoint().getPoint()); t.setVerticesBoundary(checkVerticesBoundary(root)); return t; } - HEdge prev = root.getPrev(); - HEdge next1 = root.getNext(); + HEdge prev = root.getPrev(); + HEdge next1 = root.getNext(); - HEdge next2 =findClosestValidNeighbor(next1.getNext(), delaunay); + HEdge next2 = findClosestValidNeighbor(next1.getNext(), delaunay); if(next2 == null){ root = root.getNext(); return null; } - GraphVertex v1 = root.getGraphPoint(); - GraphVertex v2 = next1.getGraphPoint(); - GraphVertex v3 = next2.getGraphPoint(); + GraphVertex v1 = root.getGraphPoint(); + GraphVertex v2 = next1.getGraphPoint(); + GraphVertex v3 = next2.getGraphPoint(); - HEdge v3Edge = new HEdge(v3, HEdge.INNER); + HEdge v3Edge = new HEdge(v3, HEdge.INNER); HEdge.connect(v3Edge, root); HEdge.connect(next1, v3Edge); - HEdge v3EdgeSib = v3Edge.getSibling(); + HEdge v3EdgeSib = v3Edge.getSibling(); if(v3EdgeSib == null){ - v3EdgeSib = new HEdge(v3Edge.getNext().getGraphPoint(), HEdge.INNER); + v3EdgeSib = new HEdge(v3Edge.getNext().getGraphPoint(), HEdge.INNER); HEdge.makeSiblings(v3Edge, v3EdgeSib); } HEdge.connect(prev, v3EdgeSib); HEdge.connect(v3EdgeSib, next2); - Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root); + Triangle t = createTriangle(v1.getPoint(), v2.getPoint(), v3.getPoint(), root); this.root = next2; return t; } @@ -97,8 +96,8 @@ public class Loop { * from the boundary profile * @param direction requested winding of edges (CCW or CW) */ - private HEdge initFromPolyline(GraphOutline outline, int direction){ - ArrayList> vertices = outline.getGraphPoint(); + private HEdge initFromPolyline(GraphOutline outline, int direction){ + ArrayList vertices = outline.getGraphPoint(); if(vertices.size()<3) { throw new IllegalArgumentException("outline's vertices < 3: " + vertices.size()); @@ -107,8 +106,8 @@ public class Loop { vertices.get(2).getPoint()); boolean invert = isCCW && (direction == VectorUtil.CW); - HEdge firstEdge = null; - HEdge lastEdge = null; + HEdge firstEdge = null; + HEdge lastEdge = null; int index =0; int max = vertices.size(); @@ -120,10 +119,10 @@ public class Loop { } while(index != max){ - GraphVertex v1 = vertices.get(index); + GraphVertex v1 = vertices.get(index); box.resize(v1.getX(), v1.getY(), v1.getZ()); - HEdge edge = new HEdge(v1, edgeType); + HEdge edge = new HEdge(v1, edgeType); v1.addEdge(edge); if(lastEdge != null){ @@ -157,22 +156,22 @@ public class Loop { return firstEdge; } - public void addConstraintCurve(GraphOutline polyline) { + public void addConstraintCurve(GraphOutline polyline) { // GraphOutline outline = new GraphOutline(polyline); /**needed to generate vertex references.*/ initFromPolyline(polyline, VectorUtil.CW); - GraphVertex v3 = locateClosestVertex(polyline); - HEdge v3Edge = v3.findBoundEdge(); - HEdge v3EdgeP = v3Edge.getPrev(); - HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER); + GraphVertex v3 = locateClosestVertex(polyline); + HEdge v3Edge = v3.findBoundEdge(); + HEdge v3EdgeP = v3Edge.getPrev(); + HEdge crossEdge = new HEdge(root.getGraphPoint(), HEdge.INNER); HEdge.connect(root.getPrev(), crossEdge); HEdge.connect(crossEdge, v3Edge); - HEdge crossEdgeSib = crossEdge.getSibling(); + HEdge crossEdgeSib = crossEdge.getSibling(); if(crossEdgeSib == null) { - crossEdgeSib = new HEdge(crossEdge.getNext().getGraphPoint(), HEdge.INNER); + crossEdgeSib = new HEdge(crossEdge.getNext().getGraphPoint(), HEdge.INNER); HEdge.makeSiblings(crossEdge, crossEdgeSib); } @@ -186,22 +185,22 @@ public class Loop { * to search for closestvertices * @return the vertex that is closest to the newly set root Hedge. */ - private GraphVertex locateClosestVertex(GraphOutline polyline) { - HEdge closestE = null; - GraphVertex closestV = null; + private GraphVertex locateClosestVertex(GraphOutline polyline) { + HEdge closestE = null; + GraphVertex closestV = null; float minDistance = Float.MAX_VALUE; boolean inValid = false; - ArrayList> initVertices = initialOutline.getGraphPoint(); - ArrayList> vertices = polyline.getGraphPoint(); + ArrayList initVertices = initialOutline.getGraphPoint(); + ArrayList vertices = polyline.getGraphPoint(); for(int i=0; i< initVertices.size()-1; i++){ - GraphVertex v = initVertices.get(i); - GraphVertex nextV = initVertices.get(i+1); - for(GraphVertex cand:vertices){ + GraphVertex v = initVertices.get(i); + GraphVertex nextV = initVertices.get(i+1); + for(GraphVertex cand:vertices){ float distance = VectorUtil.computeLength(v.getCoord(), cand.getCoord()); if(distance < minDistance){ - for (GraphVertex vert:vertices){ + for (GraphVertex vert:vertices){ if(vert == v || vert == nextV || vert == cand) continue; inValid = VectorUtil.inCircle(v.getPoint(), nextV.getPoint(), @@ -227,20 +226,20 @@ public class Loop { return closestV; } - private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) { - HEdge next = root.getNext(); + private HEdge findClosestValidNeighbor(HEdge edge, boolean delaunay) { + HEdge next = root.getNext(); if(!VectorUtil.ccw(root.getGraphPoint().getPoint(), next.getGraphPoint().getPoint(), edge.getGraphPoint().getPoint())){ return null; } - HEdge candEdge = edge; + HEdge candEdge = edge; boolean inValid = false; if(delaunay){ - T cand = candEdge.getGraphPoint().getPoint(); - HEdge e = candEdge.getNext(); + Vertex cand = candEdge.getGraphPoint().getPoint(); + HEdge e = candEdge.getNext(); while (e != candEdge){ if(e.getGraphPoint() == root.getGraphPoint() || e.getGraphPoint() == next.getGraphPoint() @@ -270,18 +269,17 @@ public class Loop { * @param root and edge of this triangle * @return the triangle iff it satisfies, null otherwise */ - private Triangle createTriangle(T v1, T v2, T v3, HEdge rootT){ - @SuppressWarnings("unchecked") - Triangle t = new Triangle(v1, v2, v3); + private Triangle createTriangle(Vertex v1, Vertex v2, Vertex v3, HEdge rootT){ + Triangle t = new Triangle(v1, v2, v3); t.setVerticesBoundary(checkVerticesBoundary(rootT)); return t; } - private boolean[] checkVerticesBoundary(HEdge rootT) { + private boolean[] checkVerticesBoundary(HEdge rootT) { boolean[] boundary = new boolean[3]; - HEdge e1 = rootT; - HEdge e2 = rootT.getNext(); - HEdge e3 = rootT.getNext().getNext(); + HEdge e1 = rootT; + HEdge e2 = rootT.getNext(); + HEdge e3 = rootT.getNext().getNext(); if(e1.getGraphPoint().isBoundaryContained()){ boundary[0] = true; @@ -300,7 +298,7 @@ public class Loop { * @param vertex the Vertex * @return true if the vertex is inside, false otherwise */ - public boolean checkInside(T vertex) { + public boolean checkInside(Vertex vertex) { if(!box.contains(vertex.getX(), vertex.getY(), vertex.getZ())){ return false; } @@ -308,8 +306,8 @@ public class Loop { float[] center = box.getCenter(); int hits = 0; - HEdge current = root; - HEdge next = root.getNext(); + HEdge current = root; + HEdge next = root.getNext(); while(next!= root){ if(current.getType() == HEdge.INNER || next.getType() == HEdge.INNER){ current = next; @@ -317,8 +315,8 @@ public class Loop { continue; } - T vert1 = current.getGraphPoint().getPoint(); - T vert2 = next.getGraphPoint().getPoint(); + Vertex vert1 = current.getGraphPoint().getPoint(); + Vertex vert2 = next.getGraphPoint().getPoint(); /** The ray is P0+s*D0, where P0 is the ray origin, D0 is a direction vector and s >= 0. * The segment is P1+t*D1, where P1 and P1+D1 are the endpoints, and 0 <= t <= 1. @@ -366,7 +364,7 @@ public class Loop { public int computeLoopSize(){ int size = 0; - HEdge e = root; + HEdge e = root; do{ size++; e = e.getNext(); diff --git a/src/jogamp/graph/curve/text/GlyphShape.java b/src/jogamp/graph/curve/text/GlyphShape.java index 712633f4b..70a725424 100644 --- a/src/jogamp/graph/curve/text/GlyphShape.java +++ b/src/jogamp/graph/curve/text/GlyphShape.java @@ -148,7 +148,7 @@ public class GlyphShape { * @param sharpness sharpness of the curved regions default = 0.5 * @return ArrayList of triangles which define this shape */ - public ArrayList> triangulate(float sharpness){ + public ArrayList triangulate(float sharpness){ return shape.triangulate(sharpness); } diff --git a/src/jogamp/graph/curve/text/GlyphString.java b/src/jogamp/graph/curve/text/GlyphString.java index a7418c6de..808e3a415 100644 --- a/src/jogamp/graph/curve/text/GlyphString.java +++ b/src/jogamp/graph/curve/text/GlyphString.java @@ -94,10 +94,10 @@ public class GlyphString { } } - private ArrayList> initializeTriangles(float sharpness){ - ArrayList> triangles = new ArrayList>(); + private ArrayList initializeTriangles(float sharpness){ + ArrayList triangles = new ArrayList(); for(GlyphShape glyph:glyphs){ - ArrayList> tris = glyph.triangulate(sharpness); + ArrayList tris = glyph.triangulate(sharpness); triangles.addAll(tris); } return triangles; @@ -112,7 +112,7 @@ public class GlyphString { region = RegionFactory.create(context, st, type); region.setFlipped(true); - ArrayList> tris = initializeTriangles(shaprness); + ArrayList tris = initializeTriangles(shaprness); region.addTriangles(tris); int numVertices = region.getNumVertices(); -- cgit v1.2.3 From 34f9f49738bc37cf5ddbd638f3a36d591d7d7a4a Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 16:47:26 +0300 Subject: Set relative texSize to RegionDemo02 --- src/demo/GPURegionNewtDemo02.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java index a7b56ad42..3d7b60574 100644 --- a/src/demo/GPURegionNewtDemo02.java +++ b/src/demo/GPURegionNewtDemo02.java @@ -94,10 +94,7 @@ public class GPURegionNewtDemo02 { public RegionGLListener() { super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-20, 00, 0f, -50, 400); - //setMatrix(-20, 00, 0f, -400, 400); - //setMatrix(-20, 00, 0f, -400, 400); - //setMatrix(-20, 00, 0f, -100, 800); + setMatrix(-20, 00, 0f, -50, 1140); } private void createTestOutline(){ @@ -149,9 +146,6 @@ public class GPURegionNewtDemo02 { regionRenderer.init(gl); regionRenderer.setAlpha(gl, 1.0f); regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - //gl.glSampleCoverage(0.95f, false); - //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines - //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); MSAATool.dump(drawable); createTestOutline(); -- cgit v1.2.3 From 48d0ea92f795d2f187a418918c9246ee28848065 Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 17:06:15 +0300 Subject: Temp: updated Testcases to onscreen --- src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java | 4 ++-- src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java index 35f0325c9..52892e646 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java @@ -56,7 +56,7 @@ public class TestRegionRenderer01 { public void testRegionRendererR2T01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL3); GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); + //caps.setOnscreen(false); caps.setAlphaBits(4); GLWindow window = createWindow("shape-r2t1-msaa0", caps, 800,400); @@ -83,7 +83,7 @@ public class TestRegionRenderer01 { public void testRegionRendererMSAA01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL2ES2); GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); + // caps.setOnscreen(false); caps.setAlphaBits(4); caps.setSampleBuffers(true); caps.setNumSamples(4); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java index 8f5174a89..acfde7e1f 100755 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java @@ -59,7 +59,6 @@ public class TestTextRenderer01 { public void testTextRendererR2T01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL3); GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); caps.setAlphaBits(4); GLWindow window = createWindow("text-r2t1-msaa0", caps, 800,400); @@ -94,7 +93,6 @@ public class TestTextRenderer01 { public void testTextRendererMSAA01() throws InterruptedException { GLProfile glp = GLProfile.get(GLProfile.GL2ES2); GLCapabilities caps = new GLCapabilities(glp); - caps.setOnscreen(false); caps.setAlphaBits(4); caps.setSampleBuffers(true); caps.setNumSamples(4); -- cgit v1.2.3 From 69e9ae0bd6ada2177562714e301d68480eb001b8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 30 Mar 2011 16:09:59 +0200 Subject: VBORegion2PGL3 -> VBORegion2PES2 --- src/com/jogamp/graph/curve/RegionFactory.java | 10 +- src/jogamp/graph/curve/opengl/VBORegion2PES2.java | 385 ++++++++++++++++++++++ src/jogamp/graph/curve/opengl/VBORegion2PGL3.java | 382 --------------------- 3 files changed, 392 insertions(+), 385 deletions(-) create mode 100644 src/jogamp/graph/curve/opengl/VBORegion2PES2.java delete mode 100644 src/jogamp/graph/curve/opengl/VBORegion2PGL3.java diff --git a/src/com/jogamp/graph/curve/RegionFactory.java b/src/com/jogamp/graph/curve/RegionFactory.java index 158f9db5b..fe77e1be5 100755 --- a/src/com/jogamp/graph/curve/RegionFactory.java +++ b/src/com/jogamp/graph/curve/RegionFactory.java @@ -28,11 +28,12 @@ package com.jogamp.graph.curve; import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; import com.jogamp.opengl.util.glsl.ShaderState; import jogamp.graph.curve.opengl.VBORegionSPES2; -import jogamp.graph.curve.opengl.VBORegion2PGL3; +import jogamp.graph.curve.opengl.VBORegion2PES2; /** RegionFactory to create a Context specific Region implementation. @@ -48,8 +49,11 @@ public class RegionFactory { * @return region */ public static Region create(GLContext context, ShaderState st, int type){ - if(Region.TWO_PASS == type && context.isGL3()){ - return new VBORegion2PGL3(context, st); + if( !context.isGL2ES2() ) { + throw new GLException("At least a GL2ES2 GL context is required. Given: " + context); + } + if( Region.TWO_PASS == type ){ + return new VBORegion2PES2(context, st); } else{ return new VBORegionSPES2(context); diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogamp/graph/curve/opengl/VBORegion2PES2.java new file mode 100644 index 000000000..c424c4ddd --- /dev/null +++ b/src/jogamp/graph/curve/opengl/VBORegion2PES2.java @@ -0,0 +1,385 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package jogamp.graph.curve.opengl; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; +import java.util.ArrayList; + +import javax.media.opengl.GL2ES2; +// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER ! +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.common.nio.Buffers; + +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Triangle; +import com.jogamp.graph.geom.Vertex; + +import com.jogamp.graph.curve.Region; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class VBORegion2PES2 implements Region{ + private int numVertices = 0; + private IntBuffer vboIds; + + private IntBuffer t_vboIds; + + private ArrayList triangles = new ArrayList(); + private ArrayList vertices = new ArrayList(); + private GLContext context; + + private int numBuffers = 3; + + private boolean flipped = false; + + private boolean dirty = false; + + private AABBox box = null; + private int[] texture = { 0 } ; + private int[] fbo = { 0 } ; + private int[] rbo_depth = { 0 } ; + private boolean texInitialized = false; + + private int tex_width_c = 0; + private int tex_height_c = 0; + + private ShaderState st; + + public VBORegion2PES2(GLContext context, ShaderState st){ + this.context =context; + this.st = st; + } + + public void update(){ + box = new AABBox(); + + GL2ES2 gl = context.getGL().getGL2ES2(); + ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); + + for(Triangle t:triangles){ + if(t.getVertices()[0].getId() == Integer.MAX_VALUE){ + t.getVertices()[0].setId(numVertices++); + t.getVertices()[1].setId(numVertices++); + t.getVertices()[2].setId(numVertices++); + + vertices.add(t.getVertices()[0]); + vertices.add(t.getVertices()[1]); + vertices.add(t.getVertices()[2]); + + indicies.put((short) t.getVertices()[0].getId()); + indicies.put((short) t.getVertices()[1].getId()); + indicies.put((short) t.getVertices()[2].getId()); + } + else{ + Vertex v1 = t.getVertices()[0]; + Vertex v2 = t.getVertices()[1]; + Vertex v3 = t.getVertices()[2]; + + indicies.put((short) v1.getId()); + indicies.put((short) v2.getId()); + indicies.put((short) v3.getId()); + } + } + indicies.rewind(); + + FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); + for(Vertex v:vertices){ + verticesBuffer.put(v.getX()); + if(flipped){ + verticesBuffer.put(-1*v.getY()); + } + else{ + verticesBuffer.put(v.getY()); + } + verticesBuffer.put(v.getZ()); + if(flipped){ + box.resize(v.getX(), -1*v.getY(), v.getZ()); + } + else{ + box.resize(v.getX(), v.getY(), v.getZ()); + } + } + verticesBuffer.rewind(); + + FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); + for(Vertex v:vertices){ + float[] tex = v.getTexCoord(); + texCoordBuffer.put(tex[0]); + texCoordBuffer.put(tex[1]); + } + texCoordBuffer.rewind(); + + vboIds = IntBuffer.allocate(numBuffers); + gl.glGenBuffers(numBuffers, vboIds); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); // vertices + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, numVertices * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); //texture + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, numVertices * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); //triangles + gl.glBufferData(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, triangles.size()* 3 * Buffers.SIZEOF_SHORT, indicies, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, 0); + + dirty = false; + } + + public void render(PMVMatrix matrix, int vp_width, int vp_height, int width){ + if(null == matrix || vp_width <=0 || vp_height <= 0 || width <= 0){ + renderRegion(); + } + else { + if(width != tex_width_c){ + texInitialized = false; + tex_width_c = width; + } + if(!texInitialized){ + initFBOTexture(matrix,vp_width, vp_height); + texInitialized = true; + } +// System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3)); + renderTexture(matrix, vp_width, vp_height); + } + } + + private void renderTexture(PMVMatrix matrix, int width, int hight){ + GL2ES2 gl = context.getGL().getGL2ES2(); + gl.glViewport(0, 0, width, hight); + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, matrix.glGetPMvMatrixf()))){ + System.out.println("Cnt set tex based mat"); + } + gl.glEnable(GL2ES2.GL_TEXTURE_2D); + gl.glActiveTexture(GL2ES2.GL_TEXTURE0); + gl.glBindTexture(GL2ES2.GL_TEXTURE_2D, texture[0]); + + st.glUniform(gl, new GLUniformData("texture", texture[0])); + int loc = gl.glGetUniformLocation(st.shaderProgram().id(), "texture"); + gl.glUniform1i(loc, 0); + + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(0)); + gl.glEnableVertexAttribArray(VERTEX_POS_INDX); + gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(1)); + gl.glEnableVertexAttribArray(TEX_COORD); + gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); + gl.glDrawElements(GL2ES2.GL_TRIANGLES, 2 * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + } + + private void setupBoundingBuffers(){ + GL2ES2 gl = context.getGL().getGL2ES2(); + + ShortBuffer indicies = Buffers.newDirectShortBuffer(6); + indicies.put((short) 0); indicies.put((short) 1); indicies.put((short) 3); + indicies.put((short) 1); indicies.put((short) 2); indicies.put((short) 3); + indicies.rewind(); + + FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(4 * 3); + FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(4 * 2); + + verticesBuffer.put(box.getLow()[0]); + verticesBuffer.put(box.getLow()[1]); + verticesBuffer.put(box.getLow()[2]); + texCoordBuffer.put(5); + texCoordBuffer.put(5); + + verticesBuffer.put(box.getLow()[0]); + verticesBuffer.put(box.getHigh()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(5); + texCoordBuffer.put(6); + + verticesBuffer.put(box.getHigh()[0]); + verticesBuffer.put(box.getHigh()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(6); + texCoordBuffer.put(6); + + verticesBuffer.put(box.getHigh()[0]); + verticesBuffer.put(box.getLow()[1]); + verticesBuffer.put(box.getLow()[2]); + + texCoordBuffer.put(6); + texCoordBuffer.put(5); + + verticesBuffer.rewind(); + texCoordBuffer.rewind(); + + t_vboIds = IntBuffer.allocate(3); + gl.glGenBuffers(numBuffers, t_vboIds); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(0)); // vertices + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(1)); //texture + gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, 4 * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); //triangles + gl.glBufferData(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_SHORT, indicies, GL2ES2.GL_STATIC_DRAW); + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + private void initFBOTexture(PMVMatrix m, int width, int hight){ + tex_height_c = (int)(tex_width_c*box.getHeight()/box.getWidth()); + // tex_height_c = tex_width_c; + System.out.println("FBO Size: "+tex_height_c+"x"+tex_width_c); + System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); + GL2ES2 gl = context.getGL().getGL2ES2(); + + if(fbo[0] > 0) { + gl.glDeleteFramebuffers(1, fbo, 0); + fbo[0] = 0; + } + if(texture[0]>0) { + gl.glDeleteTextures(1, texture, 0); + texture[0] = 0; + } + + gl.glGenFramebuffers(1, fbo, 0); + gl.glGenTextures(1, texture, 0); + gl.glGenRenderbuffers(1,rbo_depth, 0); + System.out.println("FBO: fbo " + fbo[0] + ", tex " + texture[0] + ", depth " + rbo_depth[0]); + + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); + gl.glBindTexture(GL2ES2.GL_TEXTURE_2D, texture[0]); + gl.glTexImage2D(GL2ES2.GL_TEXTURE_2D, 0, GL2ES2.GL_RGBA, tex_width_c, + tex_height_c, 0, GL2ES2.GL_RGBA, GL2ES2.GL_UNSIGNED_BYTE, null); + + gl.glTexParameterf(GL2ES2.GL_TEXTURE_2D, GL2ES2.GL_TEXTURE_MIN_FILTER, GL2ES2.GL_LINEAR); + gl.glTexParameterf(GL2ES2.GL_TEXTURE_2D, GL2ES2.GL_TEXTURE_MAG_FILTER, GL2ES2.GL_LINEAR); + gl.glTexParameterf(GL2ES2.GL_TEXTURE_2D, GL2ES2.GL_TEXTURE_WRAP_S, GL2ES2.GL_CLAMP_TO_EDGE); + gl.glTexParameterf(GL2ES2.GL_TEXTURE_2D, GL2ES2.GL_TEXTURE_WRAP_T, GL2ES2.GL_CLAMP_TO_EDGE); + + gl.glFramebufferTexture2D(GL2GL3.GL_DRAW_FRAMEBUFFER, GL2ES2.GL_COLOR_ATTACHMENT0, + GL2ES2.GL_TEXTURE_2D, texture[0], 0); + + // Set up the depth buffer + gl.glBindRenderbuffer(GL2ES2.GL_RENDERBUFFER, rbo_depth[0]); + gl.glRenderbufferStorage(GL2ES2.GL_RENDERBUFFER, GL2ES2.GL_DEPTH_COMPONENT, tex_width_c, tex_height_c); + gl.glFramebufferRenderbuffer(GL2ES2.GL_FRAMEBUFFER, GL2ES2.GL_DEPTH_COMPONENT, GL2ES2.GL_RENDERBUFFER, rbo_depth[0]); + + int status = gl.glCheckFramebufferStatus(GL2ES2.GL_FRAMEBUFFER); + if(status != GL2ES2.GL_FRAMEBUFFER_COMPLETE){ + System.err.println("Cant Create R2T pass!"); + } + + //render texture + PMVMatrix tex_matrix = new PMVMatrix(); + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); + gl.glViewport(0, 0, tex_width_c, tex_height_c); + tex_matrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + tex_matrix.glLoadIdentity(); + tex_matrix.glOrthof(box.getLow()[0], box.getHigh()[0], box.getLow()[1], box.getHigh()[1], -1, 1); + + if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, tex_matrix.glGetPMvMatrixf()))){ + System.out.println("Cnt set tex based mat"); + } + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT); + renderRegion(); + + gl.glBindFramebuffer(GL2ES2.GL_FRAMEBUFFER, 0); + gl.glBindTexture(GL2ES2.GL_TEXTURE_2D, 0); + + setupBoundingBuffers(); + } + + private void renderRegion(){ + GL2ES2 gl = context.getGL().getGL2ES2(); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); + gl.glEnableVertexAttribArray(VERTEX_POS_INDX); + gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); + gl.glEnableVertexAttribArray(TEX_COORD); + gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + + gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); + gl.glDrawElements(GL2ES2.GL_TRIANGLES, triangles.size() * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); + + gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, 0); + } + + public void addTriangles(ArrayList tris) { + triangles.addAll(tris); + dirty = true; + } + + public int getNumVertices(){ + return numVertices; + } + + public void addVertices(ArrayList verts){ + vertices.addAll(verts); + numVertices = vertices.size(); + dirty = true; + } + + public boolean isDirty(){ + return dirty; + } + + public void destroy() { + GL2ES2 gl = context.getGL().getGL2ES2(); + gl.glDeleteBuffers(numBuffers, vboIds); + gl.glDeleteFramebuffers(1, fbo, 0); + fbo[0] = 0; + gl.glDeleteTextures(1, texture, 0); + texture[0] = 0; + gl.glDeleteRenderbuffers(1, rbo_depth, 0); + rbo_depth[0] = 0; + } + + public boolean isFlipped() { + return flipped; + } + + public void setFlipped(boolean flipped) { + this.flipped = flipped; + } +} diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java b/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java deleted file mode 100644 index 066f43afc..000000000 --- a/src/jogamp/graph/curve/opengl/VBORegion2PGL3.java +++ /dev/null @@ -1,382 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.graph.curve.opengl; - -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.ShortBuffer; -import java.util.ArrayList; - -import javax.media.opengl.GL3; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLUniformData; -import javax.media.opengl.fixedfunc.GLMatrixFunc; - -import com.jogamp.common.nio.Buffers; - -import com.jogamp.graph.geom.AABBox; -import com.jogamp.graph.geom.Triangle; -import com.jogamp.graph.geom.Vertex; - -import com.jogamp.graph.curve.Region; -import com.jogamp.opengl.util.PMVMatrix; -import com.jogamp.opengl.util.glsl.ShaderState; - -public class VBORegion2PGL3 implements Region{ - private int numVertices = 0; - private IntBuffer vboIds; - - private IntBuffer t_vboIds; - - private ArrayList triangles = new ArrayList(); - private ArrayList vertices = new ArrayList(); - private GLContext context; - - private int numBuffers = 3; - - private boolean flipped = false; - - private boolean dirty = false; - - private AABBox box = null; - private int[] texture = { 0 } ; - private int[] fbo = { 0 } ; - private int[] rbo_depth = { 0 } ; - private boolean texInitialized = false; - - private int tex_width_c = 0; - private int tex_height_c = 0; - - private ShaderState st; - - public VBORegion2PGL3(GLContext context, ShaderState st){ - this.context =context; - this.st = st; - } - - public void update(){ - box = new AABBox(); - - GL3 gl = context.getGL().getGL3(); - ShortBuffer indicies = Buffers.newDirectShortBuffer(triangles.size() * 3); - - for(Triangle t:triangles){ - if(t.getVertices()[0].getId() == Integer.MAX_VALUE){ - t.getVertices()[0].setId(numVertices++); - t.getVertices()[1].setId(numVertices++); - t.getVertices()[2].setId(numVertices++); - - vertices.add(t.getVertices()[0]); - vertices.add(t.getVertices()[1]); - vertices.add(t.getVertices()[2]); - - indicies.put((short) t.getVertices()[0].getId()); - indicies.put((short) t.getVertices()[1].getId()); - indicies.put((short) t.getVertices()[2].getId()); - } - else{ - Vertex v1 = t.getVertices()[0]; - Vertex v2 = t.getVertices()[1]; - Vertex v3 = t.getVertices()[2]; - - indicies.put((short) v1.getId()); - indicies.put((short) v2.getId()); - indicies.put((short) v3.getId()); - } - } - indicies.rewind(); - - FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 3); - for(Vertex v:vertices){ - verticesBuffer.put(v.getX()); - if(flipped){ - verticesBuffer.put(-1*v.getY()); - } - else{ - verticesBuffer.put(v.getY()); - } - verticesBuffer.put(v.getZ()); - if(flipped){ - box.resize(v.getX(), -1*v.getY(), v.getZ()); - } - else{ - box.resize(v.getX(), v.getY(), v.getZ()); - } - } - verticesBuffer.rewind(); - - FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(vertices.size() * 2); - for(Vertex v:vertices){ - float[] tex = v.getTexCoord(); - texCoordBuffer.put(tex[0]); - texCoordBuffer.put(tex[1]); - } - texCoordBuffer.rewind(); - - vboIds = IntBuffer.allocate(numBuffers); - gl.glGenBuffers(numBuffers, vboIds); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(0)); // vertices - gl.glBufferData(GL3.GL_ARRAY_BUFFER, numVertices * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(1)); //texture - gl.glBufferData(GL3.GL_ARRAY_BUFFER, numVertices * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); //triangles - gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER, triangles.size()* 3 * Buffers.SIZEOF_SHORT, indicies, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0); - - dirty = false; - } - - public void render(PMVMatrix matrix, int vp_width, int vp_height, int width){ - if(null == matrix || vp_width <=0 || vp_height <= 0 || width <= 0){ - renderRegion(); - } - else { - if(width != tex_width_c){ - texInitialized = false; - tex_width_c = width; - } - if(!texInitialized){ - initFBOTexture(matrix,vp_width, vp_height); - texInitialized = true; - } -// System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3)); - renderTexture(matrix, vp_width, vp_height); - } - } - - private void renderTexture(PMVMatrix matrix, int width, int hight){ - GL3 gl = context.getGL().getGL3(); - gl.glViewport(0, 0, width, hight); - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, matrix.glGetPMvMatrixf()))){ - System.out.println("Cnt set tex based mat"); - } - gl.glEnable(GL3.GL_TEXTURE_2D); - gl.glActiveTexture(GL3.GL_TEXTURE0); - gl.glBindTexture(GL3.GL_TEXTURE_2D, texture[0]); - - st.glUniform(gl, new GLUniformData("texture", texture[0])); - int loc = gl.glGetUniformLocation(st.shaderProgram().id(), "texture"); - gl.glUniform1i(loc, 0); - - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(0)); - gl.glEnableVertexAttribArray(VERTEX_POS_INDX); - gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL3.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(1)); - gl.glEnableVertexAttribArray(TEX_COORD); - gl.glVertexAttribPointer(TEX_COORD, 2, GL3.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); - - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); - gl.glDrawElements(GL3.GL_TRIANGLES, 2 * 3, GL3.GL_UNSIGNED_SHORT, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - } - - private void setupBoundingBuffers(){ - GL3 gl = context.getGL().getGL3(); - ShortBuffer indicies = Buffers.newDirectShortBuffer(6); - indicies.put((short) 0); indicies.put((short) 1); indicies.put((short) 3); - indicies.put((short) 1); indicies.put((short) 2); indicies.put((short) 3); - indicies.rewind(); - - FloatBuffer verticesBuffer = Buffers.newDirectFloatBuffer(4 * 3); - FloatBuffer texCoordBuffer = Buffers.newDirectFloatBuffer(4 * 2); - - verticesBuffer.put(box.getLow()[0]); - verticesBuffer.put(box.getLow()[1]); - verticesBuffer.put(box.getLow()[2]); - texCoordBuffer.put(5); - texCoordBuffer.put(5); - - verticesBuffer.put(box.getLow()[0]); - verticesBuffer.put(box.getHigh()[1]); - verticesBuffer.put(box.getLow()[2]); - - texCoordBuffer.put(5); - texCoordBuffer.put(6); - - verticesBuffer.put(box.getHigh()[0]); - verticesBuffer.put(box.getHigh()[1]); - verticesBuffer.put(box.getLow()[2]); - - texCoordBuffer.put(6); - texCoordBuffer.put(6); - - verticesBuffer.put(box.getHigh()[0]); - verticesBuffer.put(box.getLow()[1]); - verticesBuffer.put(box.getLow()[2]); - - texCoordBuffer.put(6); - texCoordBuffer.put(5); - - verticesBuffer.rewind(); - texCoordBuffer.rewind(); - - t_vboIds = IntBuffer.allocate(3); - gl.glGenBuffers(numBuffers, t_vboIds); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(0)); // vertices - gl.glBufferData(GL3.GL_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_FLOAT, verticesBuffer, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, t_vboIds.get(1)); //texture - gl.glBufferData(GL3.GL_ARRAY_BUFFER, 4 * 2 * Buffers.SIZEOF_FLOAT, texCoordBuffer, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); //triangles - gl.glBufferData(GL3.GL_ELEMENT_ARRAY_BUFFER, 4 * 3 * Buffers.SIZEOF_SHORT, indicies, GL3.GL_STATIC_DRAW); - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, 0); - } - - private void initFBOTexture(PMVMatrix m, int width, int hight){ - tex_height_c = (int)(tex_width_c*box.getHeight()/box.getWidth()); - // tex_height_c = tex_width_c; - System.out.println("FBO Size: "+tex_height_c+"x"+tex_width_c); - System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); - GL3 gl = context.getGL().getGL3(); - - if(fbo[0] > 0) { - gl.glDeleteFramebuffers(1, fbo, 0); - fbo[0] = 0; - } - if(texture[0]>0) { - gl.glDeleteTextures(1, texture, 0); - texture[0] = 0; - } - - gl.glGenFramebuffers(1, fbo, 0); - gl.glGenTextures(1, texture, 0); - gl.glGenRenderbuffers(1,rbo_depth, 0); - System.out.println("FBO: fbo " + fbo[0] + ", tex " + texture[0] + ", depth " + rbo_depth[0]); - - gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); - gl.glBindTexture(GL3.GL_TEXTURE_2D, texture[0]); - gl.glTexImage2D(GL3.GL_TEXTURE_2D, 0, GL3.GL_RGBA, tex_width_c, - tex_height_c, 0, GL3.GL_RGBA, GL3.GL_UNSIGNED_BYTE, null); - - gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_LINEAR); - gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_LINEAR); - gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE); - gl.glTexParameterf(GL3.GL_TEXTURE_2D, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE); - - gl.glFramebufferTexture2D(GL3.GL_DRAW_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, - GL3.GL_TEXTURE_2D, texture[0], 0); - - // Set up the depth buffer - gl.glBindRenderbuffer(GL3.GL_RENDERBUFFER, rbo_depth[0]); - gl.glRenderbufferStorage(GL3.GL_RENDERBUFFER, GL3.GL_DEPTH_COMPONENT, tex_width_c, tex_height_c); - gl.glFramebufferRenderbuffer(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_COMPONENT, GL3.GL_RENDERBUFFER, rbo_depth[0]); - - int status = gl.glCheckFramebufferStatus(GL3.GL_FRAMEBUFFER); - if(status != GL3.GL_FRAMEBUFFER_COMPLETE){ - System.err.println("Cant Create R2T pass!"); - } - - //render texture - PMVMatrix tex_matrix = new PMVMatrix(); - gl.glBindFramebuffer(GL3.GL_DRAW_FRAMEBUFFER, fbo[0]); - gl.glViewport(0, 0, tex_width_c, tex_height_c); - tex_matrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); - tex_matrix.glLoadIdentity(); - tex_matrix.glOrthof(box.getLow()[0], box.getHigh()[0], box.getLow()[1], box.getHigh()[1], -1, 1); - - if(!st.glUniform(gl, new GLUniformData("mgl_PMVMatrix", 4, 4, tex_matrix.glGetPMvMatrixf()))){ - System.out.println("Cnt set tex based mat"); - } - - gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT); - renderRegion(); - - gl.glBindFramebuffer(GL3.GL_FRAMEBUFFER, 0); - gl.glBindTexture(GL3.GL_TEXTURE_2D, 0); - - setupBoundingBuffers(); - } - - private void renderRegion(){ - GL3 gl = context.getGL().getGL3(); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(0)); - gl.glEnableVertexAttribArray(VERTEX_POS_INDX); - gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL3.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vboIds.get(1)); - gl.glEnableVertexAttribArray(TEX_COORD); - gl.glVertexAttribPointer(TEX_COORD, 2, GL3.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); - - gl.glBindBuffer(GL3.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); - gl.glDrawElements(GL3.GL_TRIANGLES, triangles.size() * 3, GL3.GL_UNSIGNED_SHORT, 0); - - gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, 0); - } - - public void addTriangles(ArrayList tris) { - triangles.addAll(tris); - dirty = true; - } - - public int getNumVertices(){ - return numVertices; - } - - public void addVertices(ArrayList verts){ - vertices.addAll(verts); - numVertices = vertices.size(); - dirty = true; - } - - public boolean isDirty(){ - return dirty; - } - - public void destroy() { - GL3 gl = context.getGL().getGL3(); - gl.glDeleteBuffers(numBuffers, vboIds); - gl.glDeleteFramebuffers(1, fbo, 0); - fbo[0] = 0; - gl.glDeleteTextures(1, texture, 0); - texture[0] = 0; - gl.glDeleteRenderbuffers(1, rbo_depth, 0); - rbo_depth[0] = 0; - } - - public boolean isFlipped() { - return flipped; - } - - public void setFlipped(boolean flipped) { - this.flipped = flipped; - } -} -- cgit v1.2.3 From c604c520c174ae5f54931743cd9138c66fcefc9b Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 30 Mar 2011 17:25:10 +0300 Subject: Text Demo listener: Use keycode instead of keychar --- src/demo/GPUTextRendererListenerBase01.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/demo/GPUTextRendererListenerBase01.java b/src/demo/GPUTextRendererListenerBase01.java index 4ee4f62de..d3f46ca20 100644 --- a/src/demo/GPUTextRendererListenerBase01.java +++ b/src/demo/GPUTextRendererListenerBase01.java @@ -172,15 +172,15 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB else if(arg0.getKeyCode() == KeyEvent.VK_4){ fontIncr(-10); } - else if(arg0.getKeyChar() == 's') { + else if(arg0.getKeyCode() == KeyEvent.VK_S) { drawFontSet = !drawFontSet; System.err.println("Draw font set: "+drawFontSet); } - else if(arg0.getKeyChar() == 'f'){ + else if(arg0.getKeyCode() == KeyEvent.VK_F){ drawFPS = !drawFPS; System.err.println("Draw FPS: "+drawFPS); } - else if(arg0.getKeyChar() == ' ') { + else if(arg0.getKeyCode() == KeyEvent.VK_SPACE) { nextFontSet(); } } -- cgit v1.2.3 From 1c1a7d7ad51ea2041a5a121f034d4d748827b16c Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Thu, 31 Mar 2011 17:48:15 +0300 Subject: Fix: Outline over triangulation. With triangualtion exluding outter boundary triangles not all hole vertices will be inside the boundary (float issues). Workaround, check for all vertices, need a better solution and should sync with Java Fonts. --- src/com/jogamp/graph/curve/tess/CDTriangulator2D.java | 13 +++++++------ src/com/jogamp/graph/geom/AABBox.java | 7 ++++--- src/jogamp/graph/curve/tess/Loop.java | 11 +++++------ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index beef2d4a5..cc2478409 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -203,13 +203,14 @@ public class CDTriangulator2D { } private Loop getContainerLoop(Outline polyline){ - Vertex v = polyline.getVertex(0); - - for (Loop loop:loops){ - if(loop.checkInside(v)){ - return loop; + ArrayList vertices = polyline.getVertices(); + for(Vertex vert: vertices){ + for (Loop loop:loops){ + if(loop.checkInside(vert)){ + return loop; + } } - } + } return null; } } diff --git a/src/com/jogamp/graph/geom/AABBox.java b/src/com/jogamp/graph/geom/AABBox.java index f97c43a57..8cd06329e 100644 --- a/src/com/jogamp/graph/geom/AABBox.java +++ b/src/com/jogamp/graph/geom/AABBox.java @@ -40,12 +40,13 @@ public class AABBox { private float[] high = {-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE}; private float[] center = new float[3]; - /** Create a Axis Aligned bounding box (AABBox) where the low and and high MAX float Values. + /** Create a Axis Aligned bounding box (AABBox) + * where the low and and high MAX float Values. */ public AABBox() {} - /** Create an AABBox specifying the coordinates of the low and high - * + /** Create an AABBox specifying the coordinates + * of the low and high * @param lx min x-coordinate * @param ly min y-coordnate * @param lz min z-coordinate diff --git a/src/jogamp/graph/curve/tess/Loop.java b/src/jogamp/graph/curve/tess/Loop.java index d2162bbeb..fd7736a20 100644 --- a/src/jogamp/graph/curve/tess/Loop.java +++ b/src/jogamp/graph/curve/tess/Loop.java @@ -314,7 +314,6 @@ public class Loop { next = current.getNext(); continue; } - Vertex vert1 = current.getGraphPoint().getPoint(); Vertex vert2 = next.getGraphPoint().getPoint(); @@ -331,13 +330,13 @@ public class Loop { float[] d1 = {vert2.getX() - vert1.getX(), vert2.getY() - vert1.getY(), vert2.getZ() - vert1.getZ()}; - float[] prepD1 = {d1[1],-1*d1[0], d1[2]}; - float[] prepD0 = {d0[1],-1*d0[0], d0[2]}; + float[] prep_d1 = {d1[1],-1*d1[0], d1[2]}; + float[] prep_d0 = {d0[1],-1*d0[0], d0[2]}; float[] p0p1 = new float[]{vert1.getX() - vertex.getX(), vert1.getY() - vertex.getY(), vert1.getZ() - vertex.getZ()}; - float dotD1D0 = VectorUtil.dot(prepD1, d0); + float dotD1D0 = VectorUtil.dot(prep_d1, d0); if(dotD1D0 == 0){ /** ray parallel to segment */ current = next; @@ -345,8 +344,8 @@ public class Loop { continue; } - float s = VectorUtil.dot(prepD1,p0p1)/dotD1D0; - float t = VectorUtil.dot(prepD0,p0p1)/dotD1D0; + float s = VectorUtil.dot(prep_d1,p0p1)/dotD1D0; + float t = VectorUtil.dot(prep_d0,p0p1)/dotD1D0; if(s >= 0 && t >= 0 && t<= 1){ hits++; -- cgit v1.2.3 From e8c69e69374b6650e37594ebf104602fb06b548b Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Thu, 31 Mar 2011 18:38:23 +0300 Subject: Inclass Documentation cleanup of public API --- src/com/jogamp/graph/curve/OutlineShape.java | 20 +++++++------ src/com/jogamp/graph/curve/Region.java | 6 ++-- src/com/jogamp/graph/curve/RegionFactory.java | 4 +-- .../jogamp/graph/curve/opengl/RegionRenderer.java | 13 +++++---- .../jogamp/graph/curve/opengl/TextRenderer.java | 16 +++++------ .../jogamp/graph/curve/tess/CDTriangulator2D.java | 4 +-- src/com/jogamp/graph/geom/Outline.java | 33 +++++++++++++++++++++- 7 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/com/jogamp/graph/curve/OutlineShape.java b/src/com/jogamp/graph/curve/OutlineShape.java index 0c3988db3..827717aa5 100755 --- a/src/com/jogamp/graph/curve/OutlineShape.java +++ b/src/com/jogamp/graph/curve/OutlineShape.java @@ -95,7 +95,7 @@ public class OutlineShape { public static final int QUADRATIC_NURBS = 10; private final Vertex.Factory vertexFactory; - /** The list of outlines that are part of this + /** The list of {@link Outline}s that are part of this * outline shape. */ private ArrayList outlines = new ArrayList(3); @@ -112,7 +112,7 @@ public class OutlineShape { */ public final Vertex.Factory vertexFactory() { return vertexFactory; } - /** Add a new empty outline + /** Add a new empty {@link Outline} * to the shape, this new outline will * be placed at the end of the outline list. * @@ -123,7 +123,7 @@ public class OutlineShape { outlines.add(new Outline()); } - /** Adds an outline to the OutlineShape object + /** Adds an {@link Outline} to the OutlineShape object * if last outline of the shape is empty, it will replace * that last Outline with the new one. If outline is empty, * it will do nothing. @@ -147,7 +147,7 @@ public class OutlineShape { getLastOutline().addVertex(v); } - /** Add a 2D vertex to the last outline by defining the coordniate attribute + /** Add a 2D {@link Vertex} to the last outline by defining the coordniate attribute * of the vertex. The 2D vertex will be represented as Z=0. * * @param x the x coordinate @@ -159,7 +159,7 @@ public class OutlineShape { getLastOutline().addVertex(vertexFactory, x, y, onCurve); } - /** Add a 3D vertex to the last outline by defining the coordniate attribute + /** Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute * of the vertex. * @param x the x coordinate * @param y the y coordniate @@ -171,9 +171,11 @@ public class OutlineShape { getLastOutline().addVertex(vertexFactory, x, y, z, onCurve); } - /** Add a vertex to the last outline by passing a float array and specifying the offset and length in which. - * the attributes of the vertex are located. The attributes should be continuous (stride = 0). - * Attributes which value are not set (when length less than 3) are set implicitly to zero. + /** Add a vertex to the last outline by passing a float array and specifying the + * offset and length in which. The attributes of the vertex are located. + * The attributes should be continuous (stride = 0). + * Attributes which value are not set (when length less than 3) + * are set implicitly to zero. * @param coordsBuffer the coordinate array where the vertex attributes are to be picked from * @param offset the offset in the buffer to the x coordinate * @param length the number of attributes to pick from the buffer (maximum 3) @@ -270,7 +272,7 @@ public class OutlineShape { return triangulate(0.5f); } - /**Triangulate the outline shape generating a list of triangles + /**Triangulate the {@link OutlineShape} generating a list of triangles * @param sharpness defines the curvature strength around the off-curve vertices. * defaults to 0.5f * @return an arraylist of triangles representing the filled region diff --git a/src/com/jogamp/graph/curve/Region.java b/src/com/jogamp/graph/curve/Region.java index 143b6f502..5c4e8dad1 100755 --- a/src/com/jogamp/graph/curve/Region.java +++ b/src/com/jogamp/graph/curve/Region.java @@ -64,7 +64,7 @@ public interface Region { /** Renders the associated OGL objects specifying * current width/hight of window for multi pass rendering * of the region. - * @param matrix current pmv matrix. + * @param matrix current {@link PMVMatrix}. * @param vp_width current screen width * @param vp_height current screen height * @param width texture width for mp rendering @@ -73,7 +73,7 @@ public interface Region { */ public void render(PMVMatrix matrix, int vp_width, int vp_height, int width); - /** Adds a list of {@code Triangle} objects to the Region + /** Adds a list of {@link Triangle} objects to the Region * These triangles are to be binded to OGL objects * on the next call to {@code update} * @param tris an arraylist of triangle objects @@ -91,7 +91,7 @@ public interface Region { */ public int getNumVertices(); - /** Adds a list of {@code Vertex} objects to the Region + /** Adds a list of {@link Vertex} objects to the Region * These vertices are to be binded to OGL objects * on the next call to {@code update} * @param verts an arraylist of vertex objects diff --git a/src/com/jogamp/graph/curve/RegionFactory.java b/src/com/jogamp/graph/curve/RegionFactory.java index fe77e1be5..d3b978b8a 100755 --- a/src/com/jogamp/graph/curve/RegionFactory.java +++ b/src/com/jogamp/graph/curve/RegionFactory.java @@ -43,8 +43,8 @@ import jogamp.graph.curve.opengl.VBORegion2PES2; public class RegionFactory { /**Create a Region based on the GLContext attached - * @param context the current opengl context - * @param st the shader state object + * @param context the current {@link GLContext} + * @param st the {@link ShaderState} object * @param type can be one of Region.SINGLE_PASS or Region.TWO_PASS * @return region */ diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java index dfeff1b55..746eba636 100644 --- a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -14,7 +14,7 @@ import com.jogamp.graph.geom.Vertex; public abstract class RegionRenderer extends Renderer { - /** Create a Hardware accelerated Region Renderer + /** Create a Hardware accelerated Curve Region Renderer */ public static RegionRenderer create(Vertex.Factory factory, int type) { return new jogamp.graph.curve.opengl.RegionRendererImpl01(factory, type); @@ -24,7 +24,7 @@ public abstract class RegionRenderer extends Renderer { super(factory, type); } - /** Render an array of Outline shapes combined in one region + /** Render an array of {@link OutlineShape}s combined in one region * at the position provided the triangles of the * shapes will be generated, if not yet generated * @param outlineShapes array of OutlineShapes to Render. @@ -34,7 +34,7 @@ public abstract class RegionRenderer extends Renderer { */ public abstract void renderOutlineShapes(GL2ES2 gl, OutlineShape[] outlineShapes, float[] position, int texSize); - /** Render outline in 3D space at the position provided + /** Render an {@link OutlineShape} in 3D space at the position provided * the triangles of the shapes will be generated, if not yet generated * @param outlineShape the OutlineShape to Render. * @param position the initial translation of the outlineShape. @@ -54,9 +54,9 @@ public abstract class RegionRenderer extends Renderer { regions.clear(); } - /** + /** Create an ogl {@link Region} defining this {@link OutlineShape} * @param sharpness parameter for Region generation - * @return the resulting Region inclusive the generated region + * @return the resulting Region. */ protected Region createRegion(GL2ES2 gl, OutlineShape outlineShape, float sharpness) { Region region = RegionFactory.create(gl.getContext(), st, regionType); @@ -72,7 +72,8 @@ public abstract class RegionRenderer extends Renderer { return region; } - /** + /** Create an ogl {@link Region} defining the list of {@link OutlineShape}. + * Combining the Shapes into single buffers. * @param sharpness parameter for Region generation * @return the resulting Region inclusive the generated region */ diff --git a/src/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/com/jogamp/graph/curve/opengl/TextRenderer.java index 25e8b950f..83f2c93ca 100644 --- a/src/com/jogamp/graph/curve/opengl/TextRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -15,6 +15,8 @@ import com.jogamp.graph.geom.Vertex; public abstract class TextRenderer extends Renderer { + protected HashMap strings = new HashMap(); + /** * Create a Hardware accelerated Text Renderer. * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. @@ -30,7 +32,7 @@ public abstract class TextRenderer extends Renderer { /** Render the String in 3D space wrt to the font provided at the position provided * the outlines will be generated, if not yet generated * @param gl the current GL state - * @param font font to be used + * @param font {@link Font} to be used * @param str text to be rendered * @param position the lower left corner of the string * @param fontSize font size @@ -40,13 +42,11 @@ public abstract class TextRenderer extends Renderer { public abstract void renderString3D(GL2ES2 gl, Font font, String str, float[] position, int fontSize, int texSize); - protected HashMap strings = new HashMap(); - - /** - * - * @param font - * @param size - * @param str + /**Create the resulting {@link GlyphString} that represents + * the String wrt to the font. + * @param font {@link Font} to be used + * @param size font size + * @param str {@link String} to be created * @param sharpness parameter for Region generation of the resulting GlyphString * @return the resulting GlyphString inclusive the generated region */ diff --git a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java index cc2478409..a2e4ca50f 100644 --- a/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/com/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -82,7 +82,7 @@ public class CDTriangulator2D { } /** Add a curve to the list of profiles provided - * @param polyline a bounding Outline + * @param polyline a bounding {@link Outline} */ public void addCurve(Outline polyline){ Loop loop = null; @@ -107,7 +107,7 @@ public class CDTriangulator2D { } /** Generate the triangulation of the provided - * List of Outlines + * List of {@link Outline}s */ public ArrayList generateTriangulation(){ for(int i=0;i { } - /** Add a vertex to the outline. The vertex is added at the + /** Add a vertex to the outline. The {@link Vertex} is added at the * end of the outline loop/strip. * @param vertex Vertex to be added */ @@ -66,16 +66,47 @@ public class Outline implements Comparable { box.resize(vertex.getX(), vertex.getY(), vertex.getZ()); } + /** Add a {@link Vertex} by specifying its 2D attributes to the outline. + * The {@link Vertex} is added at the + * end of the outline loop/strip. + * @param factory a {@link Factory} to get the required Vertex impl + * @param x the x coordinate + * @param y the y coordinate + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(Vertex.Factory factory, float x, float y, boolean onCurve) { addVertex(factory, x, y, 0f, onCurve); } + /** Add a {@link Vertex} by specifying its 3D attributes to the outline. + * The {@link Vertex} is added at the + * end of the outline loop/strip. + * @param factory a {@link Factory} to get the required Vertex impl + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(Vertex.Factory factory, float x, float y, float z, boolean onCurve) { Vertex v = factory.create(x, y, z); v.setOnCurve(onCurve); addVertex(v); } + /** Add a vertex to the outline by passing a float array and specifying the + * offset and length in which. The attributes of the vertex are located. + * The attributes should be continuous (stride = 0). + * Attributes which value are not set (when length less than 3) + * are set implicitly to zero. + * @param factory a {@link Factory} to get the required Vertex impl + * @param coordsBuffer the coordinate array where the vertex attributes are to be picked from + * @param offset the offset in the buffer to the x coordinate + * @param length the number of attributes to pick from the buffer (maximum 3) + * @param onCurve flag if this vertex is on the final curve or defines a curved region + * of the shape around this vertex. + */ public final void addVertex(Vertex.Factory factory, float[] coordsBuffer, int offset, int length, boolean onCurve) { Vertex v = factory.create(coordsBuffer, offset, length); v.setOnCurve(onCurve); -- cgit v1.2.3 From 4b8bd5ec58cb2edfb51bd9ee930beb9c539a8a0b Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 1 Apr 2011 06:48:52 +0200 Subject: Final core and demo changes for jogl merge Core: - Region: Cleanup up constant names - Renderer: Add getRenderType() - TextRenderer: Add cache size limit - JavaFontLoader: Add FIXME 'Add cache size to limit memory usage' - UbuntuFontLoader: Add cache and FIXME 'Add cache size to limit memory usage' - TypecastFont: Add FIXME 'Add cache size to limit memory usage ??' Demos: - Relocated and split (main/listener) for jogl merge - Add 's' for screenshot - Text: - Add 'i' for live editing mode (until CR, backspace supported) --- src/com/jogamp/graph/curve/Region.java | 11 +- .../jogamp/graph/curve/opengl/RegionRenderer.java | 4 +- src/com/jogamp/graph/curve/opengl/Renderer.java | 14 +- .../jogamp/graph/curve/opengl/TextRenderer.java | 46 +++- .../test/junit/graph/TestRegionRenderer01.java | 156 ++++++++++++ .../test/junit/graph/TestTextRenderer01.java | 169 +++++++++++++ .../junit/graph/demos/GPURegionGLListener01.java | 124 ++++++++++ .../junit/graph/demos/GPURegionGLListener02.java | 120 ++++++++++ .../junit/graph/demos/GPURegionNewtDemo01.java | 75 ++++++ .../junit/graph/demos/GPURegionNewtDemo02.java | 75 ++++++ .../demos/GPURegionRendererListenerBase01.java | 52 ++++ .../graph/demos/GPURendererListenerBase01.java | 264 +++++++++++++++++++++ .../junit/graph/demos/GPUTextGLListener0A.java | 61 +++++ .../test/junit/graph/demos/GPUTextNewtDemo01.java | 67 ++++++ .../test/junit/graph/demos/GPUTextNewtDemo02.java | 76 ++++++ .../graph/demos/GPUTextRendererListenerBase01.java | 229 ++++++++++++++++++ .../opengl/test/junit/graph/demos/MSAATool.java | 69 ++++++ .../test/junit/graph/demos/ReadBufferUtil.java | 109 +++++++++ .../opengl/test/junit/graph/demos/Screenshot.java | 39 +++ src/demo/GPURegionNewtDemo01.java | 179 -------------- src/demo/GPURegionNewtDemo02.java | 170 ------------- src/demo/GPURegionRendererListenerBase01.java | 52 ---- src/demo/GPURendererListenerBase01.java | 231 ------------------ src/demo/GPUTextNewtDemo01.java | 107 --------- src/demo/GPUTextNewtDemo02.java | 115 --------- src/demo/GPUTextRendererListenerBase01.java | 190 --------------- src/demo/MSAATool.java | 69 ------ src/demo/ReadBufferUtil.java | 109 --------- src/demo/Screenshot.java | 39 --- .../graph/curve/opengl/TextRendererImpl01.java | 5 +- src/jogamp/graph/curve/opengl/VBORegion2PES2.java | 16 +- src/jogamp/graph/curve/opengl/VBORegionSPES2.java | 8 +- src/jogamp/graph/font/JavaFontLoader.java | 43 ++-- src/jogamp/graph/font/UbuntuFontLoader.java | 35 ++- src/jogamp/graph/font/typecast/TypecastFont.java | 2 + .../test/junit/graph/TestRegionRenderer01.java | 152 ------------ .../test/junit/graph/TestTextRenderer01.java | 168 ------------- 37 files changed, 1808 insertions(+), 1642 deletions(-) create mode 100644 src/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java create mode 100755 src/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java create mode 100755 src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/ReadBufferUtil.java create mode 100644 src/com/jogamp/opengl/test/junit/graph/demos/Screenshot.java delete mode 100755 src/demo/GPURegionNewtDemo01.java delete mode 100644 src/demo/GPURegionNewtDemo02.java delete mode 100644 src/demo/GPURegionRendererListenerBase01.java delete mode 100644 src/demo/GPURendererListenerBase01.java delete mode 100644 src/demo/GPUTextNewtDemo01.java delete mode 100644 src/demo/GPUTextNewtDemo02.java delete mode 100644 src/demo/GPUTextRendererListenerBase01.java delete mode 100644 src/demo/MSAATool.java delete mode 100644 src/demo/ReadBufferUtil.java delete mode 100644 src/demo/Screenshot.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java delete mode 100755 src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java diff --git a/src/com/jogamp/graph/curve/Region.java b/src/com/jogamp/graph/curve/Region.java index 5c4e8dad1..051cb1c38 100755 --- a/src/com/jogamp/graph/curve/Region.java +++ b/src/com/jogamp/graph/curve/Region.java @@ -46,14 +46,17 @@ import com.jogamp.opengl.util.PMVMatrix; public interface Region { /** The vertices index in an OGL object */ - public static int VERTEX_POS_INDX = 0; + public static int VERTEX_ATTR_IDX = 0; /** The Texture Coord index in an OGL object */ - public static int TEX_COORD = 1; + public static int TEXCOORD_ATTR_IDX = 1; - public static int SINGLE_PASS = 10; - public static int TWO_PASS = 20; + /** single pass rendering, fast, but AA might not be perfect */ + public static int SINGLE_PASS = 1; + + /** two pass rendering, slower and more resource hungry (FBO), but AA is perfect */ + public static int TWO_PASS = 2; /** Updates a graph region by updating the ogl related * objects for use in rendering. if called for the first time diff --git a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java index 746eba636..c1fec10b8 100644 --- a/src/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -59,7 +59,7 @@ public abstract class RegionRenderer extends Renderer { * @return the resulting Region. */ protected Region createRegion(GL2ES2 gl, OutlineShape outlineShape, float sharpness) { - Region region = RegionFactory.create(gl.getContext(), st, regionType); + Region region = RegionFactory.create(gl.getContext(), st, renderType); outlineShape.transformOutlines(OutlineShape.QUADRATIC_NURBS); @@ -78,7 +78,7 @@ public abstract class RegionRenderer extends Renderer { * @return the resulting Region inclusive the generated region */ protected Region createRegion(GL2ES2 gl, OutlineShape[] outlineShapes, float sharpness) { - Region region = RegionFactory.create(gl.getContext(), st, regionType); + Region region = RegionFactory.create(gl.getContext(), st, renderType); int numVertices = region.getNumVertices(); diff --git a/src/com/jogamp/graph/curve/opengl/Renderer.java b/src/com/jogamp/graph/curve/opengl/Renderer.java index a36cf870b..863928ed4 100644 --- a/src/com/jogamp/graph/curve/opengl/Renderer.java +++ b/src/com/jogamp/graph/curve/opengl/Renderer.java @@ -6,7 +6,6 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc; import jogamp.opengl.Debug; -import com.jogamp.graph.curve.Region; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.opengl.SVertex; import com.jogamp.opengl.util.PMVMatrix; @@ -34,15 +33,20 @@ public abstract class Renderer { protected ShaderState st = new ShaderState(); protected PMVMatrix pmvMatrix = new PMVMatrix(); protected GLUniformData mgl_PMVMatrix; - protected int regionType = Region.SINGLE_PASS; + protected int renderType; protected int vp_width = 0; protected int vp_height = 0; private boolean vboSupported = false; private boolean initialized = false; - protected Renderer(Vertex.Factory factory, int type) { - this.regionType = type; + /** + * + * @param factory + * @param renderType either {@link com.jogamp.graph.curve.Region#SINGLE_PASS} or {@link com.jogamp.graph.curve.Region#TWO_PASS} + */ + protected Renderer(Vertex.Factory factory, int renderType) { + this.renderType = renderType; this.pointFactory = (null != factory) ? factory : SVertex.factory(); } @@ -52,6 +56,8 @@ public abstract class Renderer { public final boolean isVBOSupported() { return vboSupported; } + public final int getRenderType() { return renderType; } + public final int getWidth() { return vp_width; } public final int getHeight() { return vp_height; } diff --git a/src/com/jogamp/graph/curve/opengl/TextRenderer.java b/src/com/jogamp/graph/curve/opengl/TextRenderer.java index 83f2c93ca..2bb99d27c 100644 --- a/src/com/jogamp/graph/curve/opengl/TextRenderer.java +++ b/src/com/jogamp/graph/curve/opengl/TextRenderer.java @@ -1,5 +1,6 @@ package com.jogamp.graph.curve.opengl; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -15,8 +16,6 @@ import com.jogamp.graph.geom.Vertex; public abstract class TextRenderer extends Renderer { - protected HashMap strings = new HashMap(); - /** * Create a Hardware accelerated Text Renderer. * @param factory optional Point.Factory for Vertex construction. Default is Vertex.Factory. @@ -58,22 +57,47 @@ public abstract class TextRenderer extends Renderer { GlyphString glyphString = new GlyphString(pointFactory, font.getName(), str); glyphString.createfromFontPath(paths, affineTransform); - glyphString.generateRegion(gl.getContext(), sharpness, st, regionType); + glyphString.generateRegion(gl.getContext(), sharpness, st, renderType); return glyphString; } - protected static String getTextHashCode(Font font, String str, int fontSize) { - // FIXME: use integer hash code - return font.getName() + "." + str.hashCode() + "." + fontSize; - } - public void flushCache() { - Iterator iterator = strings.values().iterator(); + Iterator iterator = stringCacheMap.values().iterator(); while(iterator.hasNext()){ GlyphString glyphString = iterator.next(); glyphString.destroy(); } - strings.clear(); - } + stringCacheMap.clear(); + stringCacheArray.clear(); + } + + public final void setCacheMaxSize(int newSize ) { stringCacheMaxSize = newSize; validateCache(0); } + public final int getCacheMaxSize() { return stringCacheMaxSize; } + public final int getCacheSize() { return stringCacheArray.size(); } + + protected void validateCache(int space) { + while ( getCacheSize() + space > getCacheMaxSize() ) { + String key = stringCacheArray.remove(0); + stringCacheMap.remove(key); + } + } + + protected GlyphString getCachedGlyphString(Font font, String str, int fontSize) { + final String key = font.getName() + "." + str.hashCode() + "." + fontSize; + return stringCacheMap.get(key); + } + + protected void addCachedGlyphString(Font font, String str, int fontSize, GlyphString glyphString) { + final String key = font.getName() + "." + str.hashCode() + "." + fontSize; + validateCache(1); + stringCacheMap.put(key, glyphString); + stringCacheArray.add(stringCacheArray.size(), key); + } + + // Cache is adding at the end of the array + public static final int DEFAULT_CACHE_SIZE = 32; + private HashMap stringCacheMap = new HashMap(DEFAULT_CACHE_SIZE); + private ArrayList stringCacheArray = new ArrayList(DEFAULT_CACHE_SIZE); + private int stringCacheMaxSize = DEFAULT_CACHE_SIZE; // -1 unlimited, 0 off, >0 limited } \ No newline at end of file diff --git a/src/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java b/src/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java new file mode 100644 index 000000000..9ad4eb41a --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java @@ -0,0 +1,156 @@ +package com.jogamp.opengl.test.junit.graph; + +import java.io.IOException; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.graph.demos.GPURegionGLListener01; +import com.jogamp.opengl.test.junit.graph.demos.GPURegionGLListener02; +import com.jogamp.opengl.test.junit.graph.demos.GPURegionRendererListenerBase01; + + +public class TestRegionRenderer01 { + + public static void main(String args[]) throws IOException { + String tstname = TestRegionRenderer01.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(true); + NativeWindowFactory.initSingleton(true); + } + + static void destroyWindow(GLWindow window) { + if(null!=window) { + window.destroy(); + } + } + + static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { + Assert.assertNotNull(caps); + + GLWindow window = GLWindow.create(caps); + window.setSize(width, height); + window.setPosition(10, 10); + window.setTitle(title); + Assert.assertNotNull(window); + window.setVisible(true); + + return window; + } + + @Test + public void testRegionRendererR2T01() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + + GLCapabilities caps = new GLCapabilities(glp); + //caps.setOnscreen(false); + caps.setAlphaBits(4); + + GLWindow window = createWindow("shape-r2t1-msaa0", caps, 800,400); + + GPURegionGLListener02 demo02Listener = new GPURegionGLListener02 (Region.TWO_PASS, 1140, false, false); + demo02Listener.attachInputListenerTo(window); + window.addGLEventListener(demo02Listener); + + RegionGLListener listener = new RegionGLListener(demo02Listener, window.getTitle(), "GPURegionNewtDemo02"); + window.addGLEventListener(listener); + + listener.setTech(-20, 00, 0f, -300, 400); + window.display(); + + listener.setTech(-20, 00, 0f, -150, 800); + window.display(); + + listener.setTech(-20, 00, 0f, -50, 1000); + window.display(); + + destroyWindow(window); + } + + @Test + public void testRegionRendererMSAA01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities caps = new GLCapabilities(glp); + // caps.setOnscreen(false); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + + GLWindow window = createWindow("shape-r2t0-msaa1", caps, 800, 400); + + GPURegionGLListener01 demo01Listener = new GPURegionGLListener01 (Region.SINGLE_PASS, 0, false, false); + demo01Listener.attachInputListenerTo(window); + window.addGLEventListener(demo01Listener); + + RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegion01"); + window.addGLEventListener(listener); + + listener.setTech(-20, 00, 0f, -300, 400); + window.display(); + + listener.setTech(-20, 00, 0f, -150, 800); + window.display(); + + listener.setTech(-20, 00, 0f, -50, 1000); + window.display(); + + destroyWindow(window); + } + + private class RegionGLListener implements GLEventListener { + String winTitle; + String name; + GPURegionRendererListenerBase01 impl; + + public RegionGLListener(GPURegionRendererListenerBase01 impl, String title, String name) { + this.impl = impl; + this.winTitle = title; + this.name = name; + } + + public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ + impl.setMatrix(xt, yt, angle, zoom, fboSize); + } + + public void init(GLAutoDrawable drawable) { + impl.init(drawable); + } + + public void display(GLAutoDrawable drawable) { + impl.display(drawable); + + try { + impl.printScreen(drawable, "./", winTitle, name, false); + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void dispose(GLAutoDrawable drawable) { + impl.dispose(drawable); + + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + impl.reshape(drawable, x, y, width, height); + + } + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java b/src/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java new file mode 100755 index 000000000..c954c6aa7 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java @@ -0,0 +1,169 @@ +package com.jogamp.opengl.test.junit.graph; + +import java.io.IOException; + +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.graph.curve.Region; +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.opengl.SVertex; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.graph.demos.GPUTextRendererListenerBase01; + + +public class TestTextRenderer01 { + + public static void main(String args[]) throws IOException { + String tstname = TestTextRenderer01.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + + @BeforeClass + public static void initClass() { + GLProfile.initSingleton(true); + NativeWindowFactory.initSingleton(true); + } + + static void destroyWindow(GLWindow window) { + if(null!=window) { + window.destroy(); + } + } + + static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { + Assert.assertNotNull(caps); + + GLWindow window = GLWindow.create(caps); + window.setSize(width, height); + window.setPosition(10, 10); + window.setTitle(title); + Assert.assertNotNull(window); + window.setVisible(true); + + return window; + } + + @Test + public void testTextRendererR2T01() throws InterruptedException { + GLProfile glp = GLProfile.getGL2ES2(); + + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + + GLWindow window = createWindow("text-r2t1-msaa0", caps, 800,400); + TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, window.getWidth()*2); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, window.getWidth()*3); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, window.getWidth()*4); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, window.getWidth()*2); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, window.getWidth()*3); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, window.getWidth()*4); + window.display(); + + destroyWindow(window); + } + + @Test + public void testTextRendererMSAA01() throws InterruptedException { + GLProfile glp = GLProfile.get(GLProfile.GL2ES2); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + + GLWindow window = createWindow("text-r2t0-msaa1", caps, 800, 400); + TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); + + textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + + textGLListener.setFontSet(FontFactory.JAVA, 0, 0); + textGLListener.setTech(-400, -30, 0f, -1000, 0); + window.display(); + + textGLListener.setTech(-400, -30, 0, -380, 0); + window.display(); + + textGLListener.setTech(-400, -20, 0, -80, 0); + window.display(); + + destroyWindow(window); + } + + private class TextGLListener extends GPUTextRendererListenerBase01 { + String winTitle; + + public TextGLListener(int type) { + super(SVertex.factory(), type, false, false); + } + + public void attachInputListenerTo(GLWindow window) { + super.attachInputListenerTo(window); + winTitle = window.getTitle(); + } + public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ + setMatrix(xt, yt, angle, zoom, fboSize); + } + + public void init(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + super.init(drawable); + gl.setSwapInterval(1); + gl.glEnable(GL.GL_DEPTH_TEST); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + } + + public void display(GLAutoDrawable drawable) { + super.display(drawable); + + try { + printScreen(drawable, "./", winTitle, false); + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java new file mode 100644 index 000000000..bf4bfab71 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener01.java @@ -0,0 +1,124 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.opengl.SVertex; + +/** Demonstrate the rendering of multiple outlines into one region/OutlineShape + * These Outlines are not necessary connected or contained. + * The output of this demo shows two identical shapes but the left one + * has some vertices with off-curve flag set to true, and the right allt he vertices + * are on the curve. Demos the Res. Independent Nurbs based Curve rendering + * + */ +public class GPURegionGLListener01 extends GPURegionRendererListenerBase01 { + OutlineShape outlineShape = null; + + public GPURegionGLListener01 (int numpass, int fbosize, boolean debug, boolean trace) { + super(SVertex.factory(), numpass, debug, trace); + setMatrix(-20, 00, 0f, -50, fbosize); + } + + private void createTestOutline(){ + float offset = 0; + outlineShape = new OutlineShape(getRenderer().getFactory()); + outlineShape.addVertex(0.0f,-10.0f, true); + outlineShape.addVertex(15.0f,-10.0f, true); + outlineShape.addVertex(10.0f,5.0f, false); + outlineShape.addVertex(15.0f,10.0f, true); + outlineShape.addVertex(6.0f,15.0f, false); + outlineShape.addVertex(5.0f,8.0f, false); + outlineShape.addVertex(0.0f,10.0f,true); + outlineShape.closeLastOutline(); + outlineShape.addEmptyOutline(); + outlineShape.addVertex(5.0f,-5.0f,true); + outlineShape.addVertex(10.0f,-5.0f, false); + outlineShape.addVertex(10.0f,0.0f, true); + outlineShape.addVertex(5.0f,0.0f, false); + outlineShape.closeLastOutline(); + + /** Same shape as above but without any off-curve vertices */ + outlineShape.addEmptyOutline(); + offset = 30; + outlineShape.addVertex(offset+0.0f,-10.0f, true); + outlineShape.addVertex(offset+17.0f,-10.0f, true); + outlineShape.addVertex(offset+11.0f,5.0f, true); + outlineShape.addVertex(offset+16.0f,10.0f, true); + outlineShape.addVertex(offset+7.0f,15.0f, true); + outlineShape.addVertex(offset+6.0f,8.0f, true); + outlineShape.addVertex(offset+0.0f,10.0f, true); + outlineShape.closeLastOutline(); + outlineShape.addEmptyOutline(); + outlineShape.addVertex(offset+5.0f,0.0f, true); + outlineShape.addVertex(offset+5.0f,-5.0f, true); + outlineShape.addVertex(offset+10.0f,-5.0f, true); + outlineShape.addVertex(offset+10.0f,0.0f, true); + outlineShape.closeLastOutline(); + } + + public void init(GLAutoDrawable drawable) { + super.init(drawable); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + regionRenderer.init(gl); + regionRenderer.setAlpha(gl, 1.0f); + regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + //gl.glSampleCoverage(0.95f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); + MSAATool.dump(drawable); + + createTestOutline(); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + regionRenderer.resetModelview(null); + regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); + regionRenderer.rotate(gl, getAngle(), 0, 1, 0); + + regionRenderer.renderOutlineShape(gl, outlineShape, getPosition(), getTexSize()); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java new file mode 100644 index 000000000..56db37ebe --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionGLListener02.java @@ -0,0 +1,120 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.opengl.SVertex; + +/** Demonstrate the rendering of multiple OutlineShapes + * into one region + * + */ +public class GPURegionGLListener02 extends GPURegionRendererListenerBase01 { + OutlineShape[] outlineShapes = new OutlineShape[2]; + + public GPURegionGLListener02 (int numpass, int fbosize, boolean debug, boolean trace) { + super(SVertex.factory(), numpass, debug, trace); + setMatrix(-20, 00, 0f, -50, fbosize); + } + + private void createTestOutline(){ + float offset = 0; + outlineShapes[0] = new OutlineShape(SVertex.factory()); + outlineShapes[0].addVertex(0.0f,-10.0f,true); + outlineShapes[0].addVertex(15.0f,-10.0f, true); + outlineShapes[0].addVertex(10.0f,5.0f, false); + outlineShapes[0].addVertex(15.0f,10.0f, true); + outlineShapes[0].addVertex(6.0f,15.0f, false); + outlineShapes[0].addVertex(5.0f,8.0f, false); + outlineShapes[0].addVertex(0.0f,10.0f,true); + outlineShapes[0].closeLastOutline(); + outlineShapes[0].addEmptyOutline(); + outlineShapes[0].addVertex(5.0f,-5.0f,true); + outlineShapes[0].addVertex(10.0f,-5.0f, false); + outlineShapes[0].addVertex(10.0f,0.0f, true); + outlineShapes[0].addVertex(5.0f,0.0f, false); + outlineShapes[0].closeLastOutline(); + + /** Same shape as above but without any off-curve vertices */ + outlineShapes[1] = new OutlineShape(SVertex.factory()); + offset = 30; + outlineShapes[1].addVertex(offset+0.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+17.0f,-10.0f, true); + outlineShapes[1].addVertex(offset+11.0f,5.0f, true); + outlineShapes[1].addVertex(offset+16.0f,10.0f, true); + outlineShapes[1].addVertex(offset+7.0f,15.0f, true); + outlineShapes[1].addVertex(offset+6.0f,8.0f, true); + outlineShapes[1].addVertex(offset+0.0f,10.0f, true); + outlineShapes[1].closeLastOutline(); + outlineShapes[1].addEmptyOutline(); + outlineShapes[1].addVertex(offset+5.0f,0.0f, true); + outlineShapes[1].addVertex(offset+5.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,-5.0f, true); + outlineShapes[1].addVertex(offset+10.0f,0.0f, true); + outlineShapes[1].closeLastOutline(); + } + + public void init(GLAutoDrawable drawable) { + super.init(drawable); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + regionRenderer.init(gl); + regionRenderer.setAlpha(gl, 1.0f); + regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + MSAATool.dump(drawable); + + createTestOutline(); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); + + regionRenderer.resetModelview(null); + regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); + regionRenderer.rotate(gl, getAngle(), 0, 1, 0); + + regionRenderer.renderOutlineShapes(gl, outlineShapes, getPosition(), getTexSize()); + + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java new file mode 100755 index 000000000..dbd5fe158 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo01.java @@ -0,0 +1,75 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +/** Demonstrate the rendering of multiple outlines into one region/OutlineShape + * These Outlines are not necessary connected or contained. + * The output of this demo shows two identical shapes but the left one + * has some vertices with off-curve flag set to true, and the right allt he vertices + * are on the curve. Demos the Res. Independent Nurbs based Curve rendering + * + */ +public class GPURegionNewtDemo01 { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); // 2 samples is not enough .. + System.out.println("Requested: " + caps); + + GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(800, 400); + window.setTitle("GPU Curve Region Newt Demo 01 - r2t0 msaa1"); + + GPURegionGLListener01 regionGLListener = new GPURegionGLListener01 (Region.SINGLE_PASS, 0, DEBUG, TRACE); + regionGLListener.attachInputListenerTo(window); + window.addGLEventListener(regionGLListener); + + window.enablePerfLog(true); + window.setVisible(true); + + //FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); + animator.add(window); + animator.start(); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java new file mode 100644 index 000000000..7ffab59e3 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionNewtDemo02.java @@ -0,0 +1,75 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +/** Demonstrate the rendering of multiple OutlineShapes + * into one region + * + */ +public class GPURegionNewtDemo02 { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GPURegionNewtDemo02 test = new GPURegionNewtDemo02(); + test.testMe(); + } + + public void testMe() { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + System.out.println("Requested: " + caps); + + GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(800, 400); + window.setTitle("GPU Curve Region Newt Demo 02 - r2t1 msaa0"); + + GPURegionGLListener02 regionGLListener = new GPURegionGLListener02 (Region.TWO_PASS, 1140, DEBUG, TRACE); + regionGLListener.attachInputListenerTo(window); + window.addGLEventListener(regionGLListener); + + window.enablePerfLog(true); + window.setVisible(true); + + //FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); + animator.add(window); + animator.start(); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java new file mode 100644 index 000000000..eab5fc8eb --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURegionRendererListenerBase01.java @@ -0,0 +1,52 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + +import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.opengl.RegionRenderer; +import com.jogamp.graph.geom.Vertex; + +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 3/4: font +/- + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - s: toogle draw 'font set' + * - f: toggle draw fps + * - v: toggle v-sync + * - space: toggle font (ubuntu/java) + */ +public abstract class GPURegionRendererListenerBase01 extends GPURendererListenerBase01 { + OutlineShape outlineShape = null; + + public GPURegionRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { + super(RegionRenderer.create(factory, mode), debug, trace); + } +} \ No newline at end of file diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java new file mode 100644 index 000000000..622178bf2 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -0,0 +1,264 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLRunnable; + +import com.jogamp.graph.curve.opengl.Renderer; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; + +/** + * + * Action Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - v: toggle v-sync + * - s: screenshot + */ +public abstract class GPURendererListenerBase01 implements GLEventListener { + private Screenshot screenshot; + private Renderer renderer; + private boolean debug; + private boolean trace; + + private KeyAction keyAction; + + private volatile GLAutoDrawable autoDrawable = null; + + private final float[] position = new float[] {0,0,0}; + + private float xTran = -10; + private float yTran = 10; + private float ang = 0f; + private float zoom = -70f; + private int texSize = 400; + + boolean updateMatrix = true; + boolean ignoreInput = false; + + public GPURendererListenerBase01(Renderer renderer, boolean debug, boolean trace) { + this.renderer = renderer; + this.debug = debug; + this.trace = trace; + this.screenshot = new Screenshot(); + } + + public final Renderer getRenderer() { return renderer; } + public final float getZoom() { return zoom; } + public final float getXTran() { return xTran; } + public final float getYTran() { return yTran; } + public final float getAngle() { return ang; } + public final int getTexSize() { return texSize; } + public final float[] getPosition() { return position; } + + public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) { + this.xTran = xtrans; + this.yTran = ytrans; + this.ang = angle; + this.zoom = zoom; + this.texSize = fbosize; + updateMatrix = true; + } + + public void init(GLAutoDrawable drawable) { + autoDrawable = drawable; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + if(debug) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); + } + if(trace) { + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); + } + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + } + + public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glViewport(xstart, ystart, width, height); + renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f); + + dumpMatrix(); + } + + public void dispose(GLAutoDrawable drawable) { + autoDrawable = null; + GL2ES2 gl = drawable.getGL().getGL2ES2(); + screenshot.dispose(); + renderer.dispose(gl); + } + + public void zoom(int v){ + zoom += v; + updateMatrix = true; + dumpMatrix(); + } + + public void move(float x, float y){ + xTran += x; + yTran += y; + updateMatrix = true; + dumpMatrix(); + } + public void rotate(float delta){ + ang += delta; + ang %= 360.0f; + updateMatrix = true; + dumpMatrix(); + } + + void dumpMatrix() { + System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang); + } + + /** Attach the input listener to the window */ + public void attachInputListenerTo(GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + } + } + + public void detachFrom(GLWindow window) { + if ( null == keyAction ) { + return; + } + window.removeGLEventListener(this); + window.removeKeyListener(keyAction); + } + + public void printScreen(GLAutoDrawable drawable, String dir, String tech, String objName, boolean exportAlpha) throws GLException, IOException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize, objName); + + String filename = dir + tech + sw +".tga"; + screenshot.surface2File(drawable, filename /*, exportAlpha */); + } + + int screenshot_num = 0; + + public void setIgnoreInput(boolean v) { + ignoreInput = v; + } + public boolean getIgnoreInput() { + return ignoreInput; + } + + public class KeyAction implements KeyListener { + public void keyPressed(KeyEvent arg0) { + if(ignoreInput) { + return; + } + + if(arg0.getKeyCode() == KeyEvent.VK_1){ + zoom(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_2){ + zoom(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_UP){ + move(0, -1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ + move(0, 1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ + move(1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ + move(-1, 0); + } + else if(arg0.getKeyCode() == KeyEvent.VK_6){ + texSize -= 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_7){ + texSize += 10; + System.err.println("Tex Size: " + texSize); + } + else if(arg0.getKeyCode() == KeyEvent.VK_0){ + rotate(1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_9){ + rotate(-1); + } + else if(arg0.getKeyCode() == KeyEvent.VK_V) { + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + public void run(GLAutoDrawable drawable) { + GL gl = drawable.getGL(); + int i = gl.getSwapInterval(); + i = i==0 ? 1 : 0; + gl.setSwapInterval(i); + final GLAnimatorControl a = drawable.getAnimator(); + if( null != a ) { + a.resetCounter(); + } + System.err.println("Swap Interval: "+i); + } + }); + } + } + else if(arg0.getKeyCode() == KeyEvent.VK_S){ + rotate(-1); + if(null != autoDrawable) { + autoDrawable.invoke(false, new GLRunnable() { + public void run(GLAutoDrawable drawable) { + try { + final String type = ( 1 == renderer.getRenderType() ) ? "r2t0-msaa1" : "r2t1-msaa0" ; + printScreen(drawable, "./", "demo-"+type, "snap"+screenshot_num, false); + screenshot_num++; + } catch (GLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + } + } + public void keyTyped(KeyEvent arg0) {} + public void keyReleased(KeyEvent arg0) {} + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java new file mode 100644 index 000000000..7290246d1 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextGLListener0A.java @@ -0,0 +1,61 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; + +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.geom.opengl.SVertex; + +public class GPUTextGLListener0A extends GPUTextRendererListenerBase01 { + public GPUTextGLListener0A(int numpass, int fbosize, boolean debug, boolean trace) { + super(SVertex.factory(), numpass, debug, trace); + setMatrix(-400, -30, 0f, -500, fbosize); + } + + public void init(GLAutoDrawable drawable) { + super.init(drawable); + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + + gl.setSwapInterval(1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + textRenderer.init(gl); + textRenderer.setAlpha(gl, 1.0f); + textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); + //gl.glSampleCoverage(0.95f, false); + //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE); + //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); + MSAATool.dump(drawable); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java new file mode 100644 index 000000000..3739f28ea --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo01.java @@ -0,0 +1,67 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +public class GPUTextNewtDemo01 { + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + caps.setSampleBuffers(true); + caps.setNumSamples(4); // 2 samples is not enough .. + System.out.println("Requested: "+caps); + + GLWindow window = GLWindow.create(caps); + window.setPosition(10, 10); + window.setSize(800, 400); + window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); + + GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(Region.SINGLE_PASS, 0, DEBUG, TRACE); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); + + window.enablePerfLog(true); + window.setVisible(true); + // FPSAnimator animator = new FPSAnimator(10); + Animator animator = new Animator(); + animator.add(window); + animator.start(); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java new file mode 100644 index 000000000..40c7d6ac4 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextNewtDemo02.java @@ -0,0 +1,76 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; + +import com.jogamp.graph.curve.Region; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.util.Animator; + +public class GPUTextNewtDemo02 { + /** + * FIXME: + * + * If DEBUG is enabled: + * + * Caused by: javax.media.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer( 0x8D40, 0x1902, 0x8D41, 0x1): GL_INVALID_ENUM ( 1280 0x500), + * at javax.media.opengl.DebugGL4bc.checkGLGetError(DebugGL4bc.java:33961) + * at javax.media.opengl.DebugGL4bc.glFramebufferRenderbuffer(DebugGL4bc.java:33077) + * at jogamp.graph.curve.opengl.VBORegion2PGL3.initFBOTexture(VBORegion2PGL3.java:295) + */ + static final boolean DEBUG = false; + static final boolean TRACE = false; + + public static void main(String[] args) { + GLProfile.initSingleton(true); + GLProfile glp = GLProfile.getGL2ES2(); + + GLCapabilities caps = new GLCapabilities(glp); + caps.setAlphaBits(4); + System.out.println("Requested: "+caps); + + GLWindow window = GLWindow.create(caps); + + window.setPosition(10, 10); + window.setSize(800, 400); + window.setTitle("GPU Text Newt Demo 02 - r2t1 msaa0"); + + GPUTextGLListener0A textGLListener = new GPUTextGLListener0A(Region.TWO_PASS, window.getWidth()*3, DEBUG, TRACE); + textGLListener.attachInputListenerTo(window); + window.addGLEventListener(textGLListener); + + window.enablePerfLog(true); + window.setVisible(true); + // FPSAnimator animator = new FPSAnimator(60); + Animator animator = new Animator(); + animator.add(window); + animator.start(); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java new file mode 100644 index 000000000..909f68b85 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -0,0 +1,229 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + +import java.io.IOException; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLException; +import com.jogamp.graph.curve.opengl.TextRenderer; +import com.jogamp.graph.font.Font; +import com.jogamp.graph.font.FontFactory; +import com.jogamp.graph.geom.AABBox; +import com.jogamp.graph.geom.Vertex; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.opengl.GLWindow; + +/** + * + * GPURendererListenerBase01 Keys: + * - 1/2: zoom in/out + * - 6/7: 2nd pass texture size + * - 0/9: rotate + * - v: toggle v-sync + * - s: screenshot + * + * Additional Keys: + * - 3/4: font +/- + * - h: toogle draw 'font set' + * - f: toggle draw fps + * - space: toggle font (ubuntu/java) + * - i: live input text input (CR ends it, backspace supported) + */ +public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 { + int fontSet = FontFactory.UBUNTU; + Font font; + + boolean drawFontSet = true; + boolean drawFPS = true; + boolean updateFont = true; + int fontSize = 40; + final int fontSizeModulo = 100; + + static final String text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; + static final String text2 = "The quick brown fox jumps over the lazy dog"; + + StringBuffer userString = new StringBuffer(); + boolean userInput = false; + + public GPUTextRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { + super(TextRenderer.create(factory, mode), debug, trace); + this.font = FontFactory.get(fontSet).getDefault(); + } + + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + final TextRenderer textRenderer = (TextRenderer) getRenderer(); + + if(drawFPS || drawFontSet || updateMatrix) { + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + final GLAnimatorControl animator = drawable.getAnimator(); + final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFrames()>10; + + if(_drawFPS || drawFontSet) { + textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f); + } + if(_drawFPS) { + final float fps = ( animator.getTotalFrames() * 1000.0f ) / (float) animator.getDuration() ; + final String fpsS = String.valueOf(fps); + final int fpsSp = fpsS.indexOf('.'); + textRenderer.resetModelview(null); + textRenderer.translate(gl, 0, 0, -6000); + textRenderer.renderString3D(gl, font, fpsS.substring(0, fpsSp+2), getPosition(), fontSize, getTexSize()); + } + if(drawFontSet) { + textRenderer.resetModelview(null); + final AABBox box = font.getStringBounds(font.getName(), fontSize/4); + final int dx = width-(int)box.getWidth()-2; + final int dy = height-(int)box.getHeight()-2; + textRenderer.translate(gl, dx, dy, -6000); + textRenderer.renderString3D(gl, font, font.getName(), getPosition(), fontSize/4, getTexSize()); + textRenderer.translate(gl, -dx, -20, 0); + textRenderer.renderString3D(gl, font, text1, getPosition(), fontSize, getTexSize()); + } + if(_drawFPS || drawFontSet) { + textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f); + } + + textRenderer.resetModelview(null); + textRenderer.translate(null, getXTran(), getYTran(), getZoom()); + textRenderer.rotate(gl, getAngle(), 0, 1, 0); + updateMatrix = false; + } + + if(!userInput) { + textRenderer.renderString3D(gl, font, text2, getPosition(), fontSize, getTexSize()); + } else { + textRenderer.renderString3D(gl, font, userString.toString(), getPosition(), fontSize, getTexSize()); + } + } + + public void fontIncr(int v) { + fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; + updateFont = true; + dumpMatrix(true); + } + + public void nextFontSet() { + fontSet = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; + font = FontFactory.get(fontSet).getDefault(); + } + + public void setFontSet(int set, int family, int stylebits) { + fontSet = set; + font = FontFactory.get(fontSet).get(family, stylebits); + } + + public boolean isUserInputMode() { return userInput; } + + void dumpMatrix(boolean bbox) { + System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZoom() + " @"+getAngle() +" fontSize "+fontSize); + if(bbox) { + System.err.println("bbox: "+font.getStringBounds(text2, fontSize)); + } + } + + KeyAction keyAction = null; + + @Override + public void attachInputListenerTo(GLWindow window) { + if ( null == keyAction ) { + keyAction = new KeyAction(); + window.addKeyListener(keyAction); + super.attachInputListenerTo(window); + } + + } + + @Override + public void detachFrom(GLWindow window) { + super.detachFrom(window); + if ( null == keyAction ) { + return; + } + window.removeKeyListener(keyAction); + } + + public void printScreen(GLAutoDrawable drawable, String dir, String tech, boolean exportAlpha) throws GLException, IOException { + printScreen(drawable, dir, tech, font.getName(), exportAlpha); + } + + public class KeyAction implements KeyListener { + public void keyPressed(KeyEvent arg0) { + if(userInput) { + return; + } + + if(arg0.getKeyCode() == KeyEvent.VK_3){ + fontIncr(10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_4){ + fontIncr(-10); + } + else if(arg0.getKeyCode() == KeyEvent.VK_H) { + drawFontSet = !drawFontSet; + System.err.println("Draw font set: "+drawFontSet); + } + else if(arg0.getKeyCode() == KeyEvent.VK_F){ + drawFPS = !drawFPS; + System.err.println("Draw FPS: "+drawFPS); + } + else if(arg0.getKeyCode() == KeyEvent.VK_SPACE) { + nextFontSet(); + } + else if(arg0.getKeyCode() == KeyEvent.VK_I){ + userInput = true; + setIgnoreInput(true); + } + } + public void keyTyped(KeyEvent arg0) { + if(userInput) { + char c = arg0.getKeyChar(); + + System.err.println(arg0); + if(c == 0x08) { + userString.deleteCharAt(userString.length()-1); + } else if(c == 0x0d) { + userInput = false; + setIgnoreInput(true); + } else { + userString.append(c); + } + } + } + public void keyReleased(KeyEvent arg0) {} + } +} \ No newline at end of file diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java b/src/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java new file mode 100644 index 000000000..5975e096b --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/MSAATool.java @@ -0,0 +1,69 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.graph.demos; + +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilitiesImmutable; + +public class MSAATool { + public static void dump(GLAutoDrawable drawable) { + float[] vf = new float[] { 0f }; + byte[] vb = new byte[] { 0 }; + int[] vi = new int[] { 0, 0 }; + + System.out.println("GL MSAA SETUP:"); + GL2ES2 gl = drawable.getGL().getGL2ES2(); + GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + System.out.println(" Caps realised "+caps); + System.out.println(" Caps sample buffers "+caps.getSampleBuffers()+", samples "+caps.getNumSamples()); + + // default TRUE + System.out.println(" GL MULTISAMPLE "+gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); + // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB + gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0); + // samples min 0 + gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1); + System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); + + System.out.println("GL CSAA SETUP:"); + // default FALSE + System.out.println(" GL SAMPLE COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE)); + // default FALSE + System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE)); + // default FALSE, value 1, invert false + gl.glGetFloatv(GL2GL3.GL_SAMPLE_COVERAGE_VALUE, vf, 0); + gl.glGetBooleanv(GL2GL3.GL_SAMPLE_COVERAGE_INVERT, vb, 0); + System.out.println(" GL SAMPLE_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE) + + ": SAMPLE_COVERAGE_VALUE "+vf[0]+ + ", SAMPLE_COVERAGE_INVERT "+vb[0]); + } +} diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/ReadBufferUtil.java b/src/com/jogamp/opengl/test/junit/graph/demos/ReadBufferUtil.java new file mode 100644 index 000000000..172eef4fc --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/ReadBufferUtil.java @@ -0,0 +1,109 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.graph.demos; + +import com.jogamp.opengl.util.GLBuffers; +import java.nio.*; +import javax.media.opengl.*; + +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureData; + +public class ReadBufferUtil { + protected int readPixelSizeLast = 0; + protected Buffer readPixelBuffer = null; + protected TextureData readTextureData = null; + protected Texture readTexture = new Texture(GL.GL_TEXTURE_2D); + + public Buffer getPixelBuffer() { return readPixelBuffer; } + public void rewindPixelBuffer() { readPixelBuffer.rewind(); } + + public TextureData getTextureData() { return readTextureData; } + public Texture getTexture() { return readTexture; } + + public boolean isValid() { + return null!=readTexture && null!=readTextureData && null!=readPixelBuffer ; + } + + public void fetchOffscreenTexture(GLDrawable drawable, GL gl) { + int readPixelSize = drawable.getWidth() * drawable.getHeight() * 3 ; // RGB + boolean newData = false; + if(readPixelSize>readPixelSizeLast) { + readPixelBuffer = GLBuffers.newDirectGLBuffer(GL.GL_UNSIGNED_BYTE, readPixelSize); + readPixelSizeLast = readPixelSize ; + try { + readTextureData = new TextureData( + gl.getGLProfile(), + // gl.isGL2GL3()?gl.GL_RGBA:gl.GL_RGB, + GL.GL_RGB, + drawable.getWidth(), drawable.getHeight(), + 0, + GL.GL_RGB, + GL.GL_UNSIGNED_BYTE, + false, false, + false /* flip */, + readPixelBuffer, + null /* Flusher */); + newData = true; + } catch (Exception e) { + readTextureData = null; + readPixelBuffer = null; + readPixelSizeLast = 0; + throw new RuntimeException("can not fetch offscreen texture", e); + } + } + if(null!=readPixelBuffer) { + readPixelBuffer.clear(); + gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, readPixelBuffer); + readPixelBuffer.rewind(); + if(newData) { + readTexture.updateImage(readTextureData); + } else { + readTexture.updateSubImage(readTextureData, 0, + 0, 0, // src offset + 0, 0, // dst offset + drawable.getWidth(), drawable.getHeight()); + } + readPixelBuffer.rewind(); + } + } + + @SuppressWarnings("deprecation") + public void dispose() { + readTexture.dispose(); + readTextureData = null; + if(null != readPixelBuffer) { + readPixelBuffer.clear(); + readPixelBuffer = null; + } + readPixelSizeLast = 0; + } + +} + diff --git a/src/com/jogamp/opengl/test/junit/graph/demos/Screenshot.java b/src/com/jogamp/opengl/test/junit/graph/demos/Screenshot.java new file mode 100644 index 000000000..e0c304e49 --- /dev/null +++ b/src/com/jogamp/opengl/test/junit/graph/demos/Screenshot.java @@ -0,0 +1,39 @@ +package com.jogamp.opengl.test.junit.graph.demos; + +import java.io.File; +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; + +import com.jogamp.opengl.util.texture.TextureIO; + +public class Screenshot { + + ReadBufferUtil readBufferUtil = new ReadBufferUtil(); + + public void dispose() { + readBufferUtil.dispose(); + } + + public void surface2File(GLAutoDrawable drawable, String filename) { + GL gl = drawable.getGL(); + // FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec + gl.glFinish(); + readBufferUtil.fetchOffscreenTexture(drawable, gl); + gl.glFinish(); + try { + surface2File(filename); + } catch (IOException ex) { + throw new RuntimeException("can not write survace to file", ex); + } + } + + void surface2File(String filename) throws IOException { + File file = new File(filename); + TextureIO.write(readBufferUtil.getTextureData(), file); + System.err.println("Wrote: " + file.getAbsolutePath() + ", ..."); + readBufferUtil.rewindPixelBuffer(); + } + +} diff --git a/src/demo/GPURegionNewtDemo01.java b/src/demo/GPURegionNewtDemo01.java deleted file mode 100755 index 676621692..000000000 --- a/src/demo/GPURegionNewtDemo01.java +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package demo; - -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.Animator; - -/** Demonstrate the rendering of multiple outlines into one region/OutlineShape - * These Outlines are not necessary connected or contained. - * The output of this demo shows two identical shapes but the left one - * has some vertices with off-curve flag set to true, and the right allt he vertices - * are on the curve. Demos the Res. Independent Nurbs based Curve rendering - * - */ -public class GPURegionNewtDemo01 { - static final boolean DEBUG = false; - static final boolean TRACE = false; - - public static void main(String[] args) { - GPURegionNewtDemo01 test = new GPURegionNewtDemo01(); - test.testMe(); - } - - RegionGLListener regionGLListener = null; - GLWindow window; - - public void testMe() { - GLProfile.initSingleton(true); - GLProfile glp = GLProfile.getGL2ES2(); - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); // 2 samples is not enough .. - System.out.println("Requested: " + caps); - - GLWindow w = GLWindow.create(caps); - w.setPosition(10, 10); - w.setSize(800, 400); - w.setTitle("GPU Curve Region Newt Demo 01 - r2t0 msaa1"); - - regionGLListener = createRegionRendererListener(w); - - window.addGLEventListener(regionGLListener); - - window.enablePerfLog(true); - window.setVisible(true); - - //FPSAnimator animator = new FPSAnimator(60); - Animator animator = new Animator(); - animator.add(window); - animator.start(); - } - - public RegionGLListener createRegionRendererListener(GLWindow w) { - this.window = w; - - RegionGLListener l = new RegionGLListener(); - l.attachInputListenerTo(w); - - return l; - } - - public class RegionGLListener extends GPURegionRendererListenerBase01 { - OutlineShape outlineShape = null; - - public RegionGLListener() { - super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); - setMatrix(-20, 00, 0f, -50, 400); - } - - private void createTestOutline(){ - float offset = 0; - outlineShape = new OutlineShape(getRenderer().getFactory()); - outlineShape.addVertex(0.0f,-10.0f, true); - outlineShape.addVertex(15.0f,-10.0f, true); - outlineShape.addVertex(10.0f,5.0f, false); - outlineShape.addVertex(15.0f,10.0f, true); - outlineShape.addVertex(6.0f,15.0f, false); - outlineShape.addVertex(5.0f,8.0f, false); - outlineShape.addVertex(0.0f,10.0f,true); - outlineShape.closeLastOutline(); - outlineShape.addEmptyOutline(); - outlineShape.addVertex(5.0f,-5.0f,true); - outlineShape.addVertex(10.0f,-5.0f, false); - outlineShape.addVertex(10.0f,0.0f, true); - outlineShape.addVertex(5.0f,0.0f, false); - outlineShape.closeLastOutline(); - - /** Same shape as above but without any off-curve vertices */ - outlineShape.addEmptyOutline(); - offset = 30; - outlineShape.addVertex(offset+0.0f,-10.0f, true); - outlineShape.addVertex(offset+17.0f,-10.0f, true); - outlineShape.addVertex(offset+11.0f,5.0f, true); - outlineShape.addVertex(offset+16.0f,10.0f, true); - outlineShape.addVertex(offset+7.0f,15.0f, true); - outlineShape.addVertex(offset+6.0f,8.0f, true); - outlineShape.addVertex(offset+0.0f,10.0f, true); - outlineShape.closeLastOutline(); - outlineShape.addEmptyOutline(); - outlineShape.addVertex(offset+5.0f,0.0f, true); - outlineShape.addVertex(offset+5.0f,-5.0f, true); - outlineShape.addVertex(offset+10.0f,-5.0f, true); - outlineShape.addVertex(offset+10.0f,0.0f, true); - outlineShape.closeLastOutline(); - } - - public void init(GLAutoDrawable drawable) { - super.init(drawable); - - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); - - gl.setSwapInterval(1); - gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer.init(gl); - regionRenderer.setAlpha(gl, 1.0f); - regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - //gl.glSampleCoverage(0.95f, false); - //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines - //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); - MSAATool.dump(drawable); - - createTestOutline(); - } - - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); - - regionRenderer.resetModelview(null); - regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); - regionRenderer.rotate(gl, getAngle(), 0, 1, 0); - - regionRenderer.renderOutlineShape(gl, outlineShape, getPosition(), getTexSize()); - } - } -} diff --git a/src/demo/GPURegionNewtDemo02.java b/src/demo/GPURegionNewtDemo02.java deleted file mode 100644 index 3d7b60574..000000000 --- a/src/demo/GPURegionNewtDemo02.java +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package demo; - -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.Animator; - -/** Demonstrate the rendering of multiple OutlineShapes - * into one region - * - */ -public class GPURegionNewtDemo02 { - static final boolean DEBUG = false; - static final boolean TRACE = false; - - public static void main(String[] args) { - GPURegionNewtDemo02 test = new GPURegionNewtDemo02(); - test.testMe(); - } - - RegionGLListener regionGLListener = null; - GLWindow window; - public void testMe() { - GLProfile.initSingleton(true); - GLProfile glp = GLProfile.get(GLProfile.GL3); - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - System.out.println("Requested: " + caps); - - GLWindow w = GLWindow.create(caps); - w.setPosition(10, 10); - w.setSize(800, 400); - w.setTitle("GPU Curve Region Newt Demo 02 - r2t1 msaa0"); - - regionGLListener = createRegionRendererListener(w); - window.addGLEventListener(regionGLListener); - - window.enablePerfLog(true); - window.setVisible(true); - - //FPSAnimator animator = new FPSAnimator(60); - Animator animator = new Animator(); - animator.add(window); - animator.start(); - } - - public RegionGLListener createRegionRendererListener(GLWindow w) { - this.window = w; - - RegionGLListener l = new RegionGLListener(); - l.attachInputListenerTo(w); - - return l; - } - - public class RegionGLListener extends GPURegionRendererListenerBase01 { - OutlineShape[] outlineShapes = new OutlineShape[2]; - - public RegionGLListener() { - super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - setMatrix(-20, 00, 0f, -50, 1140); - } - - private void createTestOutline(){ - float offset = 0; - outlineShapes[0] = new OutlineShape(SVertex.factory()); - outlineShapes[0].addVertex(0.0f,-10.0f,true); - outlineShapes[0].addVertex(15.0f,-10.0f, true); - outlineShapes[0].addVertex(10.0f,5.0f, false); - outlineShapes[0].addVertex(15.0f,10.0f, true); - outlineShapes[0].addVertex(6.0f,15.0f, false); - outlineShapes[0].addVertex(5.0f,8.0f, false); - outlineShapes[0].addVertex(0.0f,10.0f,true); - outlineShapes[0].closeLastOutline(); - outlineShapes[0].addEmptyOutline(); - outlineShapes[0].addVertex(5.0f,-5.0f,true); - outlineShapes[0].addVertex(10.0f,-5.0f, false); - outlineShapes[0].addVertex(10.0f,0.0f, true); - outlineShapes[0].addVertex(5.0f,0.0f, false); - outlineShapes[0].closeLastOutline(); - - /** Same shape as above but without any off-curve vertices */ - outlineShapes[1] = new OutlineShape(SVertex.factory()); - offset = 30; - outlineShapes[1].addVertex(offset+0.0f,-10.0f, true); - outlineShapes[1].addVertex(offset+17.0f,-10.0f, true); - outlineShapes[1].addVertex(offset+11.0f,5.0f, true); - outlineShapes[1].addVertex(offset+16.0f,10.0f, true); - outlineShapes[1].addVertex(offset+7.0f,15.0f, true); - outlineShapes[1].addVertex(offset+6.0f,8.0f, true); - outlineShapes[1].addVertex(offset+0.0f,10.0f, true); - outlineShapes[1].closeLastOutline(); - outlineShapes[1].addEmptyOutline(); - outlineShapes[1].addVertex(offset+5.0f,0.0f, true); - outlineShapes[1].addVertex(offset+5.0f,-5.0f, true); - outlineShapes[1].addVertex(offset+10.0f,-5.0f, true); - outlineShapes[1].addVertex(offset+10.0f,0.0f, true); - outlineShapes[1].closeLastOutline(); - } - - public void init(GLAutoDrawable drawable) { - super.init(drawable); - - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); - - gl.setSwapInterval(1); - gl.glEnable(GL2ES2.GL_DEPTH_TEST); - regionRenderer.init(gl); - regionRenderer.setAlpha(gl, 1.0f); - regionRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - MSAATool.dump(drawable); - - createTestOutline(); - } - - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - final RegionRenderer regionRenderer = (RegionRenderer) getRenderer(); - - regionRenderer.resetModelview(null); - regionRenderer.translate(null, getXTran(), getYTran(), getZoom()); - regionRenderer.rotate(gl, getAngle(), 0, 1, 0); - - regionRenderer.renderOutlineShapes(gl, outlineShapes, getPosition(), getTexSize()); - - } - } -} diff --git a/src/demo/GPURegionRendererListenerBase01.java b/src/demo/GPURegionRendererListenerBase01.java deleted file mode 100644 index 39a920656..000000000 --- a/src/demo/GPURegionRendererListenerBase01.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import com.jogamp.graph.curve.OutlineShape; -import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.geom.Vertex; - -/** - * - * Action Keys: - * - 1/2: zoom in/out - * - 3/4: font +/- - * - 6/7: 2nd pass texture size - * - 0/9: rotate - * - s: toogle draw 'font set' - * - f: toggle draw fps - * - v: toggle v-sync - * - space: toggle font (ubuntu/java) - */ -public abstract class GPURegionRendererListenerBase01 extends GPURendererListenerBase01 { - OutlineShape outlineShape = null; - - public GPURegionRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { - super(RegionRenderer.create(factory, mode), debug, trace); - } -} \ No newline at end of file diff --git a/src/demo/GPURendererListenerBase01.java b/src/demo/GPURendererListenerBase01.java deleted file mode 100644 index e8dec4c01..000000000 --- a/src/demo/GPURendererListenerBase01.java +++ /dev/null @@ -1,231 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; - -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLException; -import javax.media.opengl.GLPipelineFactory; -import javax.media.opengl.GLRunnable; - -import com.jogamp.graph.curve.opengl.Renderer; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.opengl.GLWindow; - -/** - * - * Action Keys: - * - 1/2: zoom in/out - * - 6/7: 2nd pass texture size - * - 0/9: rotate - * - v: toggle v-sync - */ -public abstract class GPURendererListenerBase01 implements GLEventListener { - private Screenshot screenshot; - private Renderer renderer; - private boolean debug; - private boolean trace; - - private KeyAction keyAction; - - private volatile GLAutoDrawable autoDrawable = null; - - private final float[] position = new float[] {0,0,0}; - - private float xTran = -10; - private float yTran = 10; - private float ang = 0f; - private float zoom = -70f; - private int texSize = 400; - - boolean updateMatrix = true; - - public GPURendererListenerBase01(Renderer renderer, boolean debug, boolean trace) { - this.renderer = renderer; - this.debug = debug; - this.trace = trace; - this.screenshot = new Screenshot(); - } - - public final Renderer getRenderer() { return renderer; } - public final float getZoom() { return zoom; } - public final float getXTran() { return xTran; } - public final float getYTran() { return yTran; } - public final float getAngle() { return ang; } - public final int getTexSize() { return texSize; } - public final float[] getPosition() { return position; } - - public void setMatrix(float xtrans, float ytrans, float angle, int zoom, int fbosize) { - this.xTran = xtrans; - this.yTran = ytrans; - this.ang = angle; - this.zoom = zoom; - this.texSize = fbosize; - updateMatrix = true; - } - - public void init(GLAutoDrawable drawable) { - autoDrawable = drawable; - GL2ES2 gl = drawable.getGL().getGL2ES2(); - if(debug) { - gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2ES2(); - } - if(trace) { - gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ).getGL2ES2(); - } - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - } - - public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glViewport(xstart, ystart, width, height); - renderer.reshapePerspective(gl, 45.0f, width, height, 0.1f, 7000.0f); - - dumpMatrix(); - } - - public void dispose(GLAutoDrawable drawable) { - autoDrawable = null; - GL2ES2 gl = drawable.getGL().getGL2ES2(); - screenshot.dispose(); - renderer.dispose(gl); - } - - public void zoom(int v){ - zoom += v; - updateMatrix = true; - dumpMatrix(); - } - - public void move(float x, float y){ - xTran += x; - yTran += y; - updateMatrix = true; - dumpMatrix(); - } - public void rotate(float delta){ - ang += delta; - ang %= 360.0f; - updateMatrix = true; - dumpMatrix(); - } - - void dumpMatrix() { - System.err.println("Matrix: " + xTran + "/" + yTran + " x"+zoom + " @"+ang); - } - - /** Attach the input listener to the window */ - public void attachInputListenerTo(GLWindow window) { - if ( null == keyAction ) { - keyAction = new KeyAction(); - window.addKeyListener(keyAction); - } - } - - public void detachFrom(GLWindow window) { - if ( null == keyAction ) { - return; - } - window.removeGLEventListener(this); - window.removeKeyListener(keyAction); - } - - public void printScreen(GLAutoDrawable drawable, String dir, String tech, String objName, boolean exportAlpha) throws GLException, IOException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize, objName); - - String filename = dir + tech + sw +".tga"; - screenshot.surface2File(drawable, filename /*, exportAlpha */); - } - - public class KeyAction implements KeyListener { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_1){ - zoom(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_2){ - zoom(-10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_UP){ - move(0, -1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_DOWN){ - move(0, 1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_LEFT){ - move(1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){ - move(-1, 0); - } - else if(arg0.getKeyCode() == KeyEvent.VK_6){ - texSize -= 10; - System.err.println("Tex Size: " + texSize); - } - else if(arg0.getKeyCode() == KeyEvent.VK_7){ - texSize += 10; - System.err.println("Tex Size: " + texSize); - } - else if(arg0.getKeyCode() == KeyEvent.VK_0){ - rotate(1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_9){ - rotate(-1); - } - else if(arg0.getKeyCode() == KeyEvent.VK_V) { - if(null != autoDrawable) { - autoDrawable.invoke(false, new GLRunnable() { - public void run(GLAutoDrawable drawable) { - GL gl = drawable.getGL(); - int i = gl.getSwapInterval(); - i = i==0 ? 1 : 0; - gl.setSwapInterval(i); - final GLAnimatorControl a = drawable.getAnimator(); - if( null != a ) { - a.resetCounter(); - } - System.err.println("Swap Interval: "+i); - } - }); - } - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - } -} diff --git a/src/demo/GPUTextNewtDemo01.java b/src/demo/GPUTextNewtDemo01.java deleted file mode 100644 index 9a3067548..000000000 --- a/src/demo/GPUTextNewtDemo01.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.opengl.TextRenderer; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.Animator; - -public class GPUTextNewtDemo01 { - static final boolean DEBUG = false; - static final boolean TRACE = false; - - public static void main(String[] args) { - GPUTextNewtDemo01 test = new GPUTextNewtDemo01(); - test.testMe(); - } - - TextGLListener textGLListener = null; - GLWindow window; - public void testMe() { - GLProfile.initSingleton(true); - GLProfile glp = GLProfile.getGL2ES2(); - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); // 2 samples is not enough .. - System.out.println("Requested: "+caps); - - window = GLWindow.create(caps); - window.setPosition(10, 10); - window.setSize(800, 400); - window.setTitle("GPU Text Newt Demo 01 - r2t0 msaa1"); - - textGLListener = new TextGLListener(); - textGLListener.attachInputListenerTo(window); - window.addGLEventListener(textGLListener); - - window.enablePerfLog(true); - window.setVisible(true); - // FPSAnimator animator = new FPSAnimator(10); - Animator animator = new Animator(); - animator.add(window); - animator.start(); - } - - private class TextGLListener extends GPUTextRendererListenerBase01 { - public TextGLListener() { - super(SVertex.factory(), Region.SINGLE_PASS, DEBUG, TRACE); - // FBO size unrelated with 1 pass - //setMatrix(-10, 10, 0f, -70, 0); - // setMatrix(-80, -30, 0f, -100, 0); - setMatrix(-400, -30, 0f, -500, 0); - } - - public void init(GLAutoDrawable drawable) { - super.init(drawable); - - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - final TextRenderer textRenderer = (TextRenderer) getRenderer(); - - gl.setSwapInterval(1); - gl.glEnable(GL2ES2.GL_DEPTH_TEST); - textRenderer.init(gl); - textRenderer.setAlpha(gl, 1.0f); - textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - //gl.glSampleCoverage(0.95f, false); - //gl.glEnable(GL2GL3.GL_SAMPLE_COVERAGE); // sample coverage doesn't really make a difference to lines - //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE); - //gl.glEnable(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE); - MSAATool.dump(drawable); - } - } -} diff --git a/src/demo/GPUTextNewtDemo02.java b/src/demo/GPUTextNewtDemo02.java deleted file mode 100644 index 2078527dc..000000000 --- a/src/demo/GPUTextNewtDemo02.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import javax.media.opengl.GL; -import javax.media.opengl.GL3; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLProfile; - -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.opengl.TextRenderer; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.util.Animator; - -public class GPUTextNewtDemo02 { - /** - * If DEBUG is enabled: - * - * Caused by: javax.media.opengl.GLException: Thread[main-Display-X11_:0.0-1-EDT-1,5,main] glGetError() returned the following error codes after a call to glFramebufferRenderbuffer( 0x8D40, 0x1902, 0x8D41, 0x1): GL_INVALID_ENUM ( 1280 0x500), - * at javax.media.opengl.DebugGL4bc.checkGLGetError(DebugGL4bc.java:33961) - * at javax.media.opengl.DebugGL4bc.glFramebufferRenderbuffer(DebugGL4bc.java:33077) - * at jogamp.graph.curve.opengl.VBORegion2PGL3.initFBOTexture(VBORegion2PGL3.java:295) - */ - static final boolean DEBUG = false; - static final boolean TRACE = false; - - public static void main(String[] args) { - GPUTextNewtDemo02 test = new GPUTextNewtDemo02(); - test.testMe(); - } - - GLWindow window; - TextGLListener textGLListener = null; - - public void testMe() { - GLProfile.initSingleton(true); - GLProfile glp = GLProfile.get(GLProfile.GL3); - - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - System.out.println("Requested: "+caps); - - window = GLWindow.create(caps); - - window.setPosition(10, 10); - window.setSize(800, 400); - - window.setTitle("GPU Text Newt Demo 02 - r2t1 msaa0"); - textGLListener = new TextGLListener(); - textGLListener.attachInputListenerTo(window); - window.addGLEventListener(textGLListener); - - window.enablePerfLog(true); - window.setVisible(true); - - // FPSAnimator animator = new FPSAnimator(60); - Animator animator = new Animator(); - animator.add(window); - animator.start(); - } - - private class TextGLListener extends GPUTextRendererListenerBase01 { - public TextGLListener() { - super(SVertex.factory(), Region.TWO_PASS, DEBUG, TRACE); - // FIXME: Rami will fix FBO size !! - // setMatrix(-10, 10, 0f, -100, 400); - // setMatrix(-80, -30, 0f, -100, window.getWidth()*3); - setMatrix(-400, -30, 0f, -500, window.getWidth()*3); - } - - public void init(GLAutoDrawable drawable) { - super.init(drawable); - - GL3 gl = drawable.getGL().getGL3(); - - final TextRenderer textRenderer = (TextRenderer) getRenderer(); - - gl.setSwapInterval(1); - gl.glEnable(GL3.GL_DEPTH_TEST); - textRenderer.init(gl); - textRenderer.setAlpha(gl, 1.0f); - textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - gl.glDisable(GL.GL_MULTISAMPLE); // this state usually doesn't matter in driver - but document here: no MSAA - //gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL3.GL_NICEST); - MSAATool.dump(drawable); - } - } -} diff --git a/src/demo/GPUTextRendererListenerBase01.java b/src/demo/GPUTextRendererListenerBase01.java deleted file mode 100644 index d3f46ca20..000000000 --- a/src/demo/GPUTextRendererListenerBase01.java +++ /dev/null @@ -1,190 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import java.io.IOException; -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLException; -import com.jogamp.graph.curve.opengl.TextRenderer; -import com.jogamp.graph.font.Font; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.Vertex; -import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.KeyListener; -import com.jogamp.newt.opengl.GLWindow; - -/** - * - * GPURendererListenerBase01 Keys: - * - 1/2: zoom in/out - * - 6/7: 2nd pass texture size - * - 0/9: rotate - * - v: toggle v-sync - * - * Additional Keys: - * - 3/4: font +/- - * - s: toogle draw 'font set' - * - f: toggle draw fps - * - space: toggle font (ubuntu/java) - */ -public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 { - int fontSet = FontFactory.UBUNTU; - Font font; - - boolean drawFontSet = true; - boolean drawFPS = true; - boolean updateFont = true; - int fontSize = 40; - final int fontSizeModulo = 100; - - static final String text1 = "abcdefghijklmnopqrstuvwxyz\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n0123456789.:,;(*!?/\\\")$%^&-+@~#<>{}[]"; - static final String text2 = "The quick brown fox jumps over the lazy dog"; - - public GPUTextRendererListenerBase01(Vertex.Factory factory, int mode, boolean debug, boolean trace) { - super(TextRenderer.create(factory, mode), debug, trace); - this.font = FontFactory.get(fontSet).getDefault(); - } - - public void display(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - - gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Demo02 needs to have this set here as well .. hmm ? - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - - final TextRenderer textRenderer = (TextRenderer) getRenderer(); - - if(drawFPS || drawFontSet || updateMatrix) { - final int width = drawable.getWidth(); - final int height = drawable.getHeight(); - final GLAnimatorControl animator = drawable.getAnimator(); - final boolean _drawFPS = drawFPS && null != animator && animator.getTotalFrames()>10; - - if(_drawFPS || drawFontSet) { - textRenderer.reshapeOrtho(null, width, height, 0.1f, 7000.0f); - } - if(_drawFPS) { - final float fps = ( animator.getTotalFrames() * 1000.0f ) / (float) animator.getDuration() ; - final String fpsS = String.valueOf(fps); - final int fpsSp = fpsS.indexOf('.'); - textRenderer.resetModelview(null); - textRenderer.translate(gl, 0, 0, -6000); - textRenderer.renderString3D(gl, font, fpsS.substring(0, fpsSp+2), getPosition(), fontSize, getTexSize()); - } - if(drawFontSet) { - textRenderer.resetModelview(null); - textRenderer.translate(gl, 0, height-50, -6000); - textRenderer.renderString3D(gl, font, text1, getPosition(), fontSize, getTexSize()); - } - if(_drawFPS || drawFontSet) { - textRenderer.reshapePerspective(null, 45.0f, width, height, 0.1f, 7000.0f); - } - - textRenderer.resetModelview(null); - textRenderer.translate(null, getXTran(), getYTran(), getZoom()); - textRenderer.rotate(gl, getAngle(), 0, 1, 0); - updateMatrix = false; - } - - textRenderer.renderString3D(gl, font, text2, getPosition(), fontSize, getTexSize()); - } - - public void fontIncr(int v) { - fontSize = Math.abs((fontSize + v) % fontSizeModulo) ; - updateFont = true; - dumpMatrix(true); - } - - public void nextFontSet() { - fontSet = ( fontSet == FontFactory.UBUNTU ) ? FontFactory.JAVA : FontFactory.UBUNTU ; - font = FontFactory.get(fontSet).getDefault(); - } - - public void setFontSet(int set, int family, int stylebits) { - fontSet = set; - font = FontFactory.get(fontSet).get(family, stylebits); - } - - void dumpMatrix(boolean bbox) { - System.err.println("Matrix: " + getXTran() + "/" + getYTran() + " x"+getZoom() + " @"+getAngle() +" fontSize "+fontSize); - if(bbox) { - System.err.println("bbox: "+font.getStringBounds(text2, fontSize)); - } - } - - KeyAction keyAction = null; - - @Override - public void attachInputListenerTo(GLWindow window) { - if ( null == keyAction ) { - keyAction = new KeyAction(); - window.addKeyListener(keyAction); - super.attachInputListenerTo(window); - } - - } - - @Override - public void detachFrom(GLWindow window) { - super.detachFrom(window); - if ( null == keyAction ) { - return; - } - window.removeKeyListener(keyAction); - } - - public void printScreen(GLAutoDrawable drawable, String dir, String tech, boolean exportAlpha) throws GLException, IOException { - printScreen(drawable, dir, tech, font.getName(), exportAlpha); - } - - public class KeyAction implements KeyListener { - public void keyPressed(KeyEvent arg0) { - if(arg0.getKeyCode() == KeyEvent.VK_3){ - fontIncr(10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_4){ - fontIncr(-10); - } - else if(arg0.getKeyCode() == KeyEvent.VK_S) { - drawFontSet = !drawFontSet; - System.err.println("Draw font set: "+drawFontSet); - } - else if(arg0.getKeyCode() == KeyEvent.VK_F){ - drawFPS = !drawFPS; - System.err.println("Draw FPS: "+drawFPS); - } - else if(arg0.getKeyCode() == KeyEvent.VK_SPACE) { - nextFontSet(); - } - } - public void keyTyped(KeyEvent arg0) {} - public void keyReleased(KeyEvent arg0) {} - } -} \ No newline at end of file diff --git a/src/demo/MSAATool.java b/src/demo/MSAATool.java deleted file mode 100644 index e357a3239..000000000 --- a/src/demo/MSAATool.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package demo; - -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GL2GL3; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilitiesImmutable; - -public class MSAATool { - public static void dump(GLAutoDrawable drawable) { - float[] vf = new float[] { 0f }; - byte[] vb = new byte[] { 0 }; - int[] vi = new int[] { 0, 0 }; - - System.out.println("GL MSAA SETUP:"); - GL2ES2 gl = drawable.getGL().getGL2ES2(); - GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); - System.out.println(" Caps realised "+caps); - System.out.println(" Caps sample buffers "+caps.getSampleBuffers()+", samples "+caps.getNumSamples()); - - // default TRUE - System.out.println(" GL MULTISAMPLE "+gl.glIsEnabled(GL2ES2.GL_MULTISAMPLE)); - // sample buffers min 0, same as GLX_SAMPLE_BUFFERS_ARB or WGL_SAMPLE_BUFFERS_ARB - gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, vi, 0); - // samples min 0 - gl.glGetIntegerv(GL2GL3.GL_SAMPLES, vi, 1); - System.out.println(" GL SAMPLE_BUFFERS "+vi[0]+", SAMPLES "+vi[1]); - - System.out.println("GL CSAA SETUP:"); - // default FALSE - System.out.println(" GL SAMPLE COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE)); - // default FALSE - System.out.println(" GL SAMPLE_ALPHA_TO_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_COVERAGE)); - // default FALSE - System.out.println(" GL SAMPLE_ALPHA_TO_ONE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_ALPHA_TO_ONE)); - // default FALSE, value 1, invert false - gl.glGetFloatv(GL2GL3.GL_SAMPLE_COVERAGE_VALUE, vf, 0); - gl.glGetBooleanv(GL2GL3.GL_SAMPLE_COVERAGE_INVERT, vb, 0); - System.out.println(" GL SAMPLE_COVERAGE "+gl.glIsEnabled(GL2GL3.GL_SAMPLE_COVERAGE) + - ": SAMPLE_COVERAGE_VALUE "+vf[0]+ - ", SAMPLE_COVERAGE_INVERT "+vb[0]); - } -} diff --git a/src/demo/ReadBufferUtil.java b/src/demo/ReadBufferUtil.java deleted file mode 100644 index 9a2da0d7e..000000000 --- a/src/demo/ReadBufferUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package demo; - -import com.jogamp.opengl.util.GLBuffers; -import java.nio.*; -import javax.media.opengl.*; - -import com.jogamp.opengl.util.texture.Texture; -import com.jogamp.opengl.util.texture.TextureData; - -public class ReadBufferUtil { - protected int readPixelSizeLast = 0; - protected Buffer readPixelBuffer = null; - protected TextureData readTextureData = null; - protected Texture readTexture = new Texture(GL.GL_TEXTURE_2D); - - public Buffer getPixelBuffer() { return readPixelBuffer; } - public void rewindPixelBuffer() { readPixelBuffer.rewind(); } - - public TextureData getTextureData() { return readTextureData; } - public Texture getTexture() { return readTexture; } - - public boolean isValid() { - return null!=readTexture && null!=readTextureData && null!=readPixelBuffer ; - } - - public void fetchOffscreenTexture(GLDrawable drawable, GL gl) { - int readPixelSize = drawable.getWidth() * drawable.getHeight() * 3 ; // RGB - boolean newData = false; - if(readPixelSize>readPixelSizeLast) { - readPixelBuffer = GLBuffers.newDirectGLBuffer(GL.GL_UNSIGNED_BYTE, readPixelSize); - readPixelSizeLast = readPixelSize ; - try { - readTextureData = new TextureData( - gl.getGLProfile(), - // gl.isGL2GL3()?gl.GL_RGBA:gl.GL_RGB, - GL.GL_RGB, - drawable.getWidth(), drawable.getHeight(), - 0, - GL.GL_RGB, - GL.GL_UNSIGNED_BYTE, - false, false, - false /* flip */, - readPixelBuffer, - null /* Flusher */); - newData = true; - } catch (Exception e) { - readTextureData = null; - readPixelBuffer = null; - readPixelSizeLast = 0; - throw new RuntimeException("can not fetch offscreen texture", e); - } - } - if(null!=readPixelBuffer) { - readPixelBuffer.clear(); - gl.glReadPixels(0, 0, drawable.getWidth(), drawable.getHeight(), GL.GL_RGB, GL.GL_UNSIGNED_BYTE, readPixelBuffer); - readPixelBuffer.rewind(); - if(newData) { - readTexture.updateImage(readTextureData); - } else { - readTexture.updateSubImage(readTextureData, 0, - 0, 0, // src offset - 0, 0, // dst offset - drawable.getWidth(), drawable.getHeight()); - } - readPixelBuffer.rewind(); - } - } - - @SuppressWarnings("deprecation") - public void dispose() { - readTexture.dispose(); - readTextureData = null; - if(null != readPixelBuffer) { - readPixelBuffer.clear(); - readPixelBuffer = null; - } - readPixelSizeLast = 0; - } - -} - diff --git a/src/demo/Screenshot.java b/src/demo/Screenshot.java deleted file mode 100644 index 8e05b17ea..000000000 --- a/src/demo/Screenshot.java +++ /dev/null @@ -1,39 +0,0 @@ -package demo; - -import java.io.File; -import java.io.IOException; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; - -import com.jogamp.opengl.util.texture.TextureIO; - -public class Screenshot { - - ReadBufferUtil readBufferUtil = new ReadBufferUtil(); - - public void dispose() { - readBufferUtil.dispose(); - } - - public void surface2File(GLAutoDrawable drawable, String filename) { - GL gl = drawable.getGL(); - // FIXME glFinish() is an expensive paranoia sync, should not be necessary due to spec - gl.glFinish(); - readBufferUtil.fetchOffscreenTexture(drawable, gl); - gl.glFinish(); - try { - surface2File(filename); - } catch (IOException ex) { - throw new RuntimeException("can not write survace to file", ex); - } - } - - void surface2File(String filename) throws IOException { - File file = new File(filename); - TextureIO.write(readBufferUtil.getTextureData(), file); - System.err.println("Wrote: " + file.getAbsolutePath() + ", ..."); - readBufferUtil.rewindPixelBuffer(); - } - -} diff --git a/src/jogamp/graph/curve/opengl/TextRendererImpl01.java b/src/jogamp/graph/curve/opengl/TextRendererImpl01.java index aa3202805..cebe7a19e 100644 --- a/src/jogamp/graph/curve/opengl/TextRendererImpl01.java +++ b/src/jogamp/graph/curve/opengl/TextRendererImpl01.java @@ -176,11 +176,10 @@ public class TextRendererImpl01 extends TextRenderer { if(!isInitialized()){ throw new GLException("TextRendererImpl01: not initialized!"); } - String fontStrHash = getTextHashCode(font, str, fontSize); - GlyphString glyphString = strings.get(fontStrHash); + GlyphString glyphString = getCachedGlyphString(font, str, fontSize); if(null == glyphString) { glyphString = createString(gl, font, fontSize, str, mgl_sharpness.floatValue()); - strings.put(fontStrHash, glyphString); + addCachedGlyphString(font, str, fontSize, glyphString); } glyphString.renderString3D(pmvMatrix, vp_width, vp_height, texSize); diff --git a/src/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogamp/graph/curve/opengl/VBORegion2PES2.java index c424c4ddd..c7c370f6d 100644 --- a/src/jogamp/graph/curve/opengl/VBORegion2PES2.java +++ b/src/jogamp/graph/curve/opengl/VBORegion2PES2.java @@ -192,12 +192,12 @@ public class VBORegion2PES2 implements Region{ gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(0)); - gl.glEnableVertexAttribArray(VERTEX_POS_INDX); - gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(VERTEX_ATTR_IDX); + gl.glVertexAttribPointer(VERTEX_ATTR_IDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, t_vboIds.get(1)); - gl.glEnableVertexAttribArray(TEX_COORD); - gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(TEXCOORD_ATTR_IDX); + gl.glVertexAttribPointer(TEXCOORD_ATTR_IDX, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, t_vboIds.get(2)); gl.glDrawElements(GL2ES2.GL_TRIANGLES, 2 * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); @@ -332,12 +332,12 @@ public class VBORegion2PES2 implements Region{ GL2ES2 gl = context.getGL().getGL2ES2(); gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); - gl.glEnableVertexAttribArray(VERTEX_POS_INDX); - gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(VERTEX_ATTR_IDX); + gl.glVertexAttribPointer(VERTEX_ATTR_IDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); - gl.glEnableVertexAttribArray(TEX_COORD); - gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(TEXCOORD_ATTR_IDX); + gl.glVertexAttribPointer(TEXCOORD_ATTR_IDX, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); gl.glDrawElements(GL2ES2.GL_TRIANGLES, triangles.size() * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); diff --git a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java index f509dbd58..701549d46 100644 --- a/src/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -134,12 +134,12 @@ public class VBORegionSPES2 implements Region{ GL2ES2 gl = context.getGL().getGL2ES2(); gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(0)); - gl.glEnableVertexAttribArray(VERTEX_POS_INDX); - gl.glVertexAttribPointer(VERTEX_POS_INDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(VERTEX_ATTR_IDX); + gl.glVertexAttribPointer(VERTEX_ATTR_IDX, 3, GL2ES2.GL_FLOAT, false, 3 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER, vboIds.get(1)); - gl.glEnableVertexAttribArray(TEX_COORD); - gl.glVertexAttribPointer(TEX_COORD, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); + gl.glEnableVertexAttribArray(TEXCOORD_ATTR_IDX); + gl.glVertexAttribPointer(TEXCOORD_ATTR_IDX, 2, GL2ES2.GL_FLOAT, false, 2 * Buffers.SIZEOF_FLOAT, 0); gl.glBindBuffer(GL2ES2.GL_ELEMENT_ARRAY_BUFFER, vboIds.get(2)); gl.glDrawElements(GL2ES2.GL_TRIANGLES, triangles.size() * 3, GL2ES2.GL_UNSIGNED_SHORT, 0); diff --git a/src/jogamp/graph/font/JavaFontLoader.java b/src/jogamp/graph/font/JavaFontLoader.java index 6769a691a..33505e797 100644 --- a/src/jogamp/graph/font/JavaFontLoader.java +++ b/src/jogamp/graph/font/JavaFontLoader.java @@ -58,8 +58,13 @@ public class JavaFontLoader implements FontSet { javaFontPath = System.getProperty("java.home") + "/lib/fonts/"; } + // FIXME: Add cache size to limit memory usage static final IntObjectHashMap fontMap = new IntObjectHashMap(); + static boolean is(int bits, int bit) { + return 0 != ( bits & bit ) ; + } + public Font getDefault() { return get(FAMILY_REGULAR, 0) ; // Sans Serif Regular } @@ -71,12 +76,13 @@ public class JavaFontLoader implements FontSet { } // 1st process Sans Serif (2 fonts) - if( 0 == ( style & STYLE_SERIF ) ) { - if( 0 != ( style & STYLE_BOLD ) ) { - font = abspath(availableFontFileNames[5]); + if( is(style, STYLE_SERIF) ) { + if( is(style, STYLE_BOLD) ) { + font = abspath(availableFontFileNames[5], family, style); } else { - font = abspath(availableFontFileNames[4]); + font = abspath(availableFontFileNames[4], family, style); } + fontMap.put( ( family << 8 ) | style, font ); return font; } @@ -86,24 +92,24 @@ public class JavaFontLoader implements FontSet { case FAMILY_MEDIUM: case FAMILY_CONDENSED: case FAMILY_REGULAR: - if( 0 != ( style & STYLE_BOLD ) ) { - if( 0 != ( style & STYLE_ITALIC ) ) { - font = abspath(availableFontFileNames[3]); + if( is(style, STYLE_BOLD) ) { + if( is(style, STYLE_ITALIC) ) { + font = abspath(availableFontFileNames[3], family, style); } else { - font = abspath(availableFontFileNames[2]); + font = abspath(availableFontFileNames[2], family, style); } - } else if( 0 != ( style & STYLE_ITALIC ) ) { - font = abspath(availableFontFileNames[1]); + } else if( is(style, STYLE_ITALIC) ) { + font = abspath(availableFontFileNames[1], family, style); } else { - font = abspath(availableFontFileNames[0]); + font = abspath(availableFontFileNames[0], family, style); } break; case FAMILY_MONOSPACED: - if( 0 != ( style & STYLE_BOLD ) ) { - font = abspath(availableFontFileNames[7]); + if( is(style, STYLE_BOLD) ) { + font = abspath(availableFontFileNames[7], family, style); } else { - font = abspath(availableFontFileNames[6]); + font = abspath(availableFontFileNames[6], family, style); } break; } @@ -111,8 +117,13 @@ public class JavaFontLoader implements FontSet { return font; } - Font abspath(String fname) { - return FontFactory.getFontConstr().create(javaFontPath+fname); + Font abspath(String fname, int family, int style) { + final Font f = FontFactory.getFontConstr().create(javaFontPath+fname); + if(null != f) { + fontMap.put( ( family << 8 ) | style, f ); + } + return f; + } } diff --git a/src/jogamp/graph/font/UbuntuFontLoader.java b/src/jogamp/graph/font/UbuntuFontLoader.java index 77d2cea03..e09ea85e5 100644 --- a/src/jogamp/graph/font/UbuntuFontLoader.java +++ b/src/jogamp/graph/font/UbuntuFontLoader.java @@ -27,6 +27,7 @@ */ package jogamp.graph.font; +import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontSet; import com.jogamp.graph.font.FontFactory; @@ -58,6 +59,9 @@ public class UbuntuFontLoader implements FontSet { private UbuntuFontLoader() { } + // FIXME: Add cache size to limit memory usage + static final IntObjectHashMap fontMap = new IntObjectHashMap(); + static boolean is(int bits, int bit) { return 0 != ( bits & bit ) ; } @@ -68,7 +72,10 @@ public class UbuntuFontLoader implements FontSet { public Font get(int family, int style) { - Font font = null; + Font font = (Font)fontMap.get( ( family << 8 ) | style ); + if (font != null) { + return font; + } switch (family) { case FAMILY_MONOSPACED: @@ -76,30 +83,30 @@ public class UbuntuFontLoader implements FontSet { case FAMILY_REGULAR: if( is(style, STYLE_BOLD) ) { if( is(style, STYLE_ITALIC) ) { - font = abspath(availableFontFileNames[3]); + font = abspath(availableFontFileNames[3], family, style); } else { - font = abspath(availableFontFileNames[2]); + font = abspath(availableFontFileNames[2], family, style); } } else if( is(style, STYLE_ITALIC) ) { - font = abspath(availableFontFileNames[1]); + font = abspath(availableFontFileNames[1], family, style); } else { - font = abspath(availableFontFileNames[0]); + font = abspath(availableFontFileNames[0], family, style); } break; case FAMILY_LIGHT: if( is(style, STYLE_ITALIC) ) { - font = abspath(availableFontFileNames[5]); + font = abspath(availableFontFileNames[5], family, style); } else { - font = abspath(availableFontFileNames[4]); + font = abspath(availableFontFileNames[4], family, style); } break; case FAMILY_MEDIUM: if( is(style, STYLE_ITALIC) ) { - font = abspath(availableFontFileNames[6]); + font = abspath(availableFontFileNames[6], family, style); } else { - font = abspath(availableFontFileNames[7]); + font = abspath(availableFontFileNames[7], family, style); } break; } @@ -110,6 +117,16 @@ public class UbuntuFontLoader implements FontSet { Font abspath(String fname) { return FontFactory.getFontConstr().create( Locator.getResource(UbuntuFontLoader.class, relPath+fname).getPath() ); + } + + Font abspath(String fname, int family, int style) { + final Font f = FontFactory.getFontConstr().create( + Locator.getResource(UbuntuFontLoader.class, relPath+fname).getPath() ); + if(null != f) { + fontMap.put( ( family << 8 ) | style, f ); + } + return f; } + } diff --git a/src/jogamp/graph/font/typecast/TypecastFont.java b/src/jogamp/graph/font/typecast/TypecastFont.java index 546eb85e3..0d018a314 100644 --- a/src/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogamp/graph/font/typecast/TypecastFont.java @@ -49,6 +49,8 @@ class TypecastFont implements FontInt { TypecastHMetrics metrics; final CmapFormat cmapFormat; int cmapentries; + + // FIXME: Add cache size to limit memory usage ?? IntObjectHashMap char2Glyph; public TypecastFont(OTFontCollection fontset) { diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java deleted file mode 100644 index 52892e646..000000000 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestRegionRenderer01.java +++ /dev/null @@ -1,152 +0,0 @@ -package test.com.jogamp.opengl.test.junit.graph; - -import java.io.IOException; - -import javax.media.nativewindow.NativeWindowFactory; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLException; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jogamp.newt.opengl.GLWindow; - -import demo.GPURegionNewtDemo01; -import demo.GPURegionNewtDemo02; -import demo.GPURegionRendererListenerBase01; - -public class TestRegionRenderer01 { - - public static void main(String args[]) throws IOException { - String tstname = TestRegionRenderer01.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - - @BeforeClass - public static void initClass() { - GLProfile.initSingleton(true); - NativeWindowFactory.initSingleton(true); - } - - static void destroyWindow(GLWindow window) { - if(null!=window) { - window.destroy(); - } - } - - static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { - Assert.assertNotNull(caps); - - GLWindow window = GLWindow.create(caps); - window.setSize(width, height); - window.setPosition(10, 10); - window.setTitle(title); - Assert.assertNotNull(window); - window.setVisible(true); - - return window; - } - - @Test - public void testRegionRendererR2T01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL3); - GLCapabilities caps = new GLCapabilities(glp); - //caps.setOnscreen(false); - caps.setAlphaBits(4); - - GLWindow window = createWindow("shape-r2t1-msaa0", caps, 800,400); - - GPURegionNewtDemo02 demo02 = new GPURegionNewtDemo02(); - GPURegionNewtDemo02.RegionGLListener demo02Listener = demo02.createRegionRendererListener(window); - - RegionGLListener listener = new RegionGLListener(demo02Listener, window.getTitle(), "GPURegionNewtDemo02"); - window.addGLEventListener(listener); - - listener.setTech(-20, 00, 0f, -300, 400); - window.display(); - - listener.setTech(-20, 00, 0f, -150, 800); - window.display(); - - listener.setTech(-20, 00, 0f, -50, 1000); - window.display(); - - destroyWindow(window); - } - - @Test - public void testRegionRendererMSAA01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL2ES2); - GLCapabilities caps = new GLCapabilities(glp); - // caps.setOnscreen(false); - caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - - GLWindow window = createWindow("shape-r2t0-msaa1", caps, 800, 400); - - GPURegionNewtDemo01 demo01 = new GPURegionNewtDemo01(); - GPURegionNewtDemo01.RegionGLListener demo01Listener = demo01.createRegionRendererListener(window); - - RegionGLListener listener = new RegionGLListener(demo01Listener, window.getTitle(), "GPURegionNewtDemo01"); - window.addGLEventListener(listener); - - listener.setTech(-20, 00, 0f, -300, 400); - window.display(); - - listener.setTech(-20, 00, 0f, -150, 800); - window.display(); - - listener.setTech(-20, 00, 0f, -50, 1000); - window.display(); - - destroyWindow(window); - } - - private class RegionGLListener implements GLEventListener { - String winTitle; - String name; - GPURegionRendererListenerBase01 impl; - - public RegionGLListener(GPURegionRendererListenerBase01 impl, String title, String name) { - this.impl = impl; - this.winTitle = title; - this.name = name; - } - - public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ - impl.setMatrix(xt, yt, angle, zoom, fboSize); - } - - public void init(GLAutoDrawable drawable) { - impl.init(drawable); - } - - public void display(GLAutoDrawable drawable) { - impl.display(drawable); - - try { - impl.printScreen(drawable, "./", winTitle, name, false); - } catch (GLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public void dispose(GLAutoDrawable drawable) { - impl.dispose(drawable); - - } - - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - impl.reshape(drawable, x, y, width, height); - - } - } -} diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java deleted file mode 100755 index acfde7e1f..000000000 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRenderer01.java +++ /dev/null @@ -1,168 +0,0 @@ -package test.com.jogamp.opengl.test.junit.graph; - -import java.io.IOException; - -import javax.media.nativewindow.NativeWindowFactory; -import javax.media.opengl.GL; -import javax.media.opengl.GL2ES2; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLException; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jogamp.graph.curve.Region; -import com.jogamp.graph.curve.opengl.TextRenderer; -import com.jogamp.graph.font.FontFactory; -import com.jogamp.graph.geom.opengl.SVertex; -import com.jogamp.newt.opengl.GLWindow; - -import demo.GPUTextRendererListenerBase01; - -public class TestTextRenderer01 { - - public static void main(String args[]) throws IOException { - String tstname = TestRegionRenderer01.class.getName(); - org.junit.runner.JUnitCore.main(tstname); - } - - @BeforeClass - public static void initClass() { - GLProfile.initSingleton(true); - NativeWindowFactory.initSingleton(true); - } - - static void destroyWindow(GLWindow window) { - if(null!=window) { - window.destroy(); - } - } - - static GLWindow createWindow(String title, GLCapabilitiesImmutable caps, int width, int height) { - Assert.assertNotNull(caps); - - GLWindow window = GLWindow.create(caps); - window.setSize(width, height); - window.setPosition(10, 10); - window.setTitle(title); - Assert.assertNotNull(window); - window.setVisible(true); - - return window; - } - - @Test - public void testTextRendererR2T01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL3); - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - - GLWindow window = createWindow("text-r2t1-msaa0", caps, 800,400); - TextGLListener textGLListener = new TextGLListener(Region.TWO_PASS); - textGLListener.attachInputListenerTo(window); - window.addGLEventListener(textGLListener); - - textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 400); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 1100); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 2500); - window.display(); - - textGLListener.setFontSet(FontFactory.JAVA, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 400); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 1100); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 2500); - window.display(); - - destroyWindow(window); - } - - @Test - public void testTextRendererMSAA01() throws InterruptedException { - GLProfile glp = GLProfile.get(GLProfile.GL2ES2); - GLCapabilities caps = new GLCapabilities(glp); - caps.setAlphaBits(4); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - - GLWindow window = createWindow("text-r2t0-msaa1", caps, 800, 400); - TextGLListener textGLListener = new TextGLListener(Region.SINGLE_PASS); - textGLListener.attachInputListenerTo(window); - window.addGLEventListener(textGLListener); - - textGLListener.setFontSet(FontFactory.UBUNTU, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 0); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 0); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 0); - window.display(); - - textGLListener.setFontSet(FontFactory.JAVA, 0, 0); - textGLListener.setTech(-400, -30, 0f, -1000, 0); - window.display(); - - textGLListener.setTech(-400, -30, 0, -380, 0); - window.display(); - - textGLListener.setTech(-400, -20, 0, -80, 0); - window.display(); - - destroyWindow(window); - } - - private class TextGLListener extends GPUTextRendererListenerBase01 { - String winTitle; - - public TextGLListener(int type) { - super(SVertex.factory(), type, false, false); - } - - public void attachInputListenerTo(GLWindow window) { - super.attachInputListenerTo(window); - winTitle = window.getTitle(); - } - public void setTech(float xt, float yt, float angle, int zoom, int fboSize){ - setMatrix(xt, yt, angle, zoom, fboSize); - } - - public void init(GLAutoDrawable drawable) { - GL2ES2 gl = drawable.getGL().getGL2ES2(); - super.init(drawable); - gl.setSwapInterval(1); - gl.glEnable(GL.GL_DEPTH_TEST); - - final TextRenderer textRenderer = (TextRenderer) getRenderer(); - - textRenderer.init(gl); - textRenderer.setAlpha(gl, 1.0f); - textRenderer.setColor(gl, 0.0f, 0.0f, 0.0f); - } - - public void display(GLAutoDrawable drawable) { - super.display(drawable); - - try { - printScreen(drawable, "./", winTitle, false); - } catch (GLException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } -} -- cgit v1.2.3