GlyphIndices.GlyphMapping ParsePart(string parts) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(42); //mapping.ClusterCodeUnitCount = 1; //mapping.ClusterGlyphCount = 1; //mapping.GlyphIndex = -1; //mapping.AdvanceWidth = Double.NaN; //mapping.UOffset = Double.NaN; //mapping.VOffset = Double.NaN; string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (!String.IsNullOrEmpty(commaSeparated[0])) { // Just split the numbers // (a:b)c // (a)c // c // (a:b) - not possible // (a) - not possible string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); // Last number is always the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); // First and second (if available) are the code unit count and glyph count if (tempStr.Length > 1) { mapping.ClusterCodeUnitCount = int.Parse(tempStr[0]); } if (tempStr.Length > 2) { mapping.ClusterGlyphCount = int.Parse(tempStr[1]); } } if (commaSeparated.Length > 1 && !String.IsNullOrEmpty(commaSeparated[1])) { mapping.AdvanceWidth = ParseDouble(commaSeparated[1]); } if (commaSeparated.Length > 2 && !String.IsNullOrEmpty(commaSeparated[2])) { mapping.UOffset = ParseDouble(commaSeparated[2]); } if (commaSeparated.Length > 3 && !String.IsNullOrEmpty(commaSeparated[3])) { mapping.VOffset = ParseDouble(commaSeparated[3]); } } return(mapping); }
GlyphIndices.GlyphMapping[] Parse() { string[] parts = this.indices.Split(new char[] { ';' }); int count = parts.Length; GlyphIndices.GlyphMapping[] glyphMapping = new GlyphIndices.GlyphMapping[count]; for (int idx = 0; idx < count; idx++) { glyphMapping[idx] = ParsePart(parts[idx]); } return(glyphMapping); }
GlyphIndices.GlyphMapping ParsePart(string parts) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(42); //mapping.ClusterCodeUnitCount = 1; //mapping.ClusterGlyphCount = 1; //mapping.GlyphIndex = -1; //mapping.AdvanceWidth = Double.NaN; //mapping.UOffset = Double.NaN; //mapping.VOffset = Double.NaN; #if true string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (!String.IsNullOrEmpty(commaSeparated[0])) { // Just split the numbers // (a:b)c // (a)c // c // (a:b) - not possible // (a) - not possible string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); // Last number is always the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); // First and second (if available) are the code unit count and glyph count if (tempStr.Length > 1) { mapping.ClusterCodeUnitCount = int.Parse(tempStr[0]); } if (tempStr.Length > 2) { mapping.ClusterGlyphCount = int.Parse(tempStr[1]); } } if (commaSeparated.Length > 1 && !String.IsNullOrEmpty(commaSeparated[1])) { mapping.AdvanceWidth = XpsParser.ParseDouble(commaSeparated[1]); } if (commaSeparated.Length > 2 && !String.IsNullOrEmpty(commaSeparated[2])) { mapping.UOffset = XpsParser.ParseDouble(commaSeparated[2]); } if (commaSeparated.Length > 3 && !String.IsNullOrEmpty(commaSeparated[3])) { mapping.VOffset = XpsParser.ParseDouble(commaSeparated[3]); } } #else string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (commaSeparated[0] != "") { // Just split the numbers string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); // Last number is the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); // First and second (if available) are the code unit count and glyph count) if (tempStr.Length > 1) { int.TryParse(tempStr[0], out mapping.ClusterCodeUnitCount); } if (tempStr.Length > 2) { int.TryParse(tempStr[1], out mapping.ClusterGlyphCount); } } if (commaSeparated.Length > 1) { double.TryParse(commaSeparated[1], out mapping.AdvanceWidth); // BUG: InvariantCulture not used! } if (commaSeparated.Length > 2) { double.TryParse(commaSeparated[2], out mapping.UOffset); // <-- must not be zero if not defined, but must keep NaN } if (commaSeparated.Length > 3) { double.TryParse(commaSeparated[3], out mapping.VOffset); } } #endif return(mapping); }
GlyphIndices.GlyphMapping ParsePart(string parts) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(42); //mapping.ClusterCodeUnitCount = 1; //mapping.ClusterGlyphCount = 1; //mapping.GlyphIndex = -1; //mapping.AdvanceWidth = Double.NaN; //mapping.UOffset = Double.NaN; //mapping.VOffset = Double.NaN; #if true string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (!String.IsNullOrEmpty(commaSeparated[0])) { // Just split the numbers // (a:b)c // (a)c // c // (a:b) - not possible // (a) - not possible string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); // Last number is always the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); // First and second (if available) are the code unit count and glyph count if (tempStr.Length > 1) mapping.ClusterCodeUnitCount = int.Parse(tempStr[0]); if (tempStr.Length > 2) mapping.ClusterGlyphCount = int.Parse(tempStr[1]); } if (commaSeparated.Length > 1 && !String.IsNullOrEmpty(commaSeparated[1])) mapping.AdvanceWidth = XpsParser.ParseDouble(commaSeparated[1]); if (commaSeparated.Length > 2 && !String.IsNullOrEmpty(commaSeparated[2])) mapping.UOffset = XpsParser.ParseDouble(commaSeparated[2]); if (commaSeparated.Length > 3 && !String.IsNullOrEmpty(commaSeparated[3])) mapping.VOffset = XpsParser.ParseDouble(commaSeparated[3]); } #else string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (commaSeparated[0] != "") { // Just split the numbers string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); // Last number is the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); // First and second (if available) are the code unit count and glyph count) if (tempStr.Length > 1) int.TryParse(tempStr[0], out mapping.ClusterCodeUnitCount); if (tempStr.Length > 2) int.TryParse(tempStr[1], out mapping.ClusterGlyphCount); } if (commaSeparated.Length > 1) double.TryParse(commaSeparated[1],out mapping.AdvanceWidth); // BUG: InvariantCulture not used! if (commaSeparated.Length > 2) double.TryParse(commaSeparated[2], out mapping.UOffset); // <-- must not be zero if not defined, but must keep NaN if (commaSeparated.Length > 3) double.TryParse(commaSeparated[3], out mapping.VOffset); } #endif return mapping; }
GlyphIndices.GlyphMapping[] Parse() { string[] parts = this.indices.Split(new char[] { ';' }); int count = parts.Length; GlyphIndices.GlyphMapping[] glyphMapping = new GlyphIndices.GlyphMapping[count]; for (int idx = 0; idx < count; idx++) glyphMapping[idx] = ParsePart(parts[idx]); return glyphMapping; }
GlyphIndices.GlyphMapping ParsePart(string parts) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(); mapping.ClusterCodeUnitCount = 1; mapping.ClusterGlyphCount = 1; string[] commaSeparated = parts.Split(','); if (commaSeparated.Length > 0) { if (commaSeparated[0] != "") { //Just split the numbers string[] tempStr = commaSeparated[0].Split(new char[] { '(', ')', ':' }, StringSplitOptions.RemoveEmptyEntries); //Last number is the index mapping.GlyphIndex = int.Parse(tempStr[tempStr.Length - 1]); //First and second (if available) are the code unit count and glyph count) if (tempStr.Length > 1) int.TryParse(tempStr[0], out mapping.ClusterCodeUnitCount); if (tempStr.Length > 2) int.TryParse(tempStr[1], out mapping.ClusterGlyphCount); } if (commaSeparated.Length > 1) double.TryParse(commaSeparated[1], out mapping.AdvanceWidth); if (commaSeparated.Length > 2) double.TryParse(commaSeparated[2], out mapping.uOffset); if (commaSeparated.Length > 3) double.TryParse(commaSeparated[3], out mapping.vOffset); } return mapping; }
/// <summary> /// This is just a draft to see what to do in detail. /// </summary> private void WriteGlyphs_ClusterMapping(Glyphs glyphs) { string unicodeString = glyphs.UnicodeString; #if DEBUG_ if (!String.IsNullOrEmpty(unicodeString)) { if (unicodeString.StartsWith("abc")) GetType(); } #endif bool boldSimulation = (glyphs.StyleSimulations & StyleSimulations.BoldSimulation) == StyleSimulations.BoldSimulation; double boldSimulationFactor = 1; if (boldSimulation) boldSimulationFactor = 1; bool RightToLeft = glyphs.BidiLevel % 2 == 1; // TODOWPF: why is this a level?? what means "bidirectional nesting"? GlyphIndices indices = glyphs.Indices; if (indices == null) indices = new GlyphIndices(); int codeIdx = 0; int codeCount = String.IsNullOrEmpty(unicodeString) ? 0 : unicodeString.Length; int glyphCount = indices.Count; int glyphIdx = 0; bool stop = false; PdfFont realizedFont = this.graphicsState.realizedFont; OpenTypeDescriptor descriptor = realizedFont.FontDescriptor.descriptor; int glyphIndex; double x = glyphs.OriginX; double y = glyphs.OriginY; XPoint pos = new XPoint(x, y); // accumulation may lead to rounding error -> check it! double uOffset = 0; double vOffset = 0; StringBuilder outputText = new StringBuilder(); double accumulatedWidth = 0; int outputGlyphCount = 0; bool mustRender = false; bool hasOffset = false; do { GlyphIndices.GlyphMapping clusterMapping = new GlyphIndices.GlyphMapping(42); if (glyphIdx < glyphCount) clusterMapping = indices[glyphIdx]; for (int clusterGlyphIdx = 0; clusterGlyphIdx < clusterMapping.ClusterGlyphCount; clusterGlyphIdx++) { GlyphIndices.GlyphMapping mapping = new GlyphIndices.GlyphMapping(42); if (glyphIdx + clusterGlyphIdx < glyphCount) mapping = indices[glyphIdx + clusterGlyphIdx]; Debug.Assert(mustRender == false); // Determine whether to render accumulated glyphs if (outputGlyphCount > 0 && (hasOffset || mapping.HasAdvanceWidthOrOffset)) { outputText.Append('>'); WriteLiteral("{0:0.####} {1:0.####} Td {2}Tj\n", pos.x, pos.y, outputText.ToString()); //double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); //if (!PdfSharp.Internal.DoubleUtil.IsNaN(mapping.AdvanceWidth)) // width = mapping.AdvanceWidth * 10; //pos = new XPoint(accumulatedWidth + width / 1000 * glyphs.FontRenderingEmSize, 0); pos = new XPoint(accumulatedWidth, 0); // reset values accumulatedWidth = 0; outputGlyphCount = 0; outputText.Length = 0; mustRender = false; } mustRender = mapping.HasAdvanceWidth; //mustRender = true; // Adjust former uOffset if (uOffset != 0) { pos.x -= uOffset; uOffset = 0; mustRender = true; } // Adjust position by current former uOffset if (mapping.HasUOffset) { uOffset = mapping.UOffset * glyphs.FontRenderingEmSize / 100; pos.x += uOffset; mustRender = true; hasOffset = true; } // Adjust former vOffset if (vOffset != 0) { pos.y += vOffset; vOffset = 0; mustRender = true; } // Adjust position by current former vOffset if (mapping.HasVOffset) { vOffset = mapping.VOffset * glyphs.FontRenderingEmSize / 100; pos.y -= vOffset; mustRender = true; hasOffset = true; } // get index of current glyph if (mapping.HasGlyphIndex) glyphIndex = mapping.GlyphIndex; else glyphIndex = descriptor.CharCodeToGlyphIndex(unicodeString[codeIdx]); // add glyph index to the fonts 'used glyph table' realizedFont.AddGlyphIndices(new string((char)glyphIndex, 1)); #if true if (outputGlyphCount == 0) outputText.Append('<'); outputText.AppendFormat("{0:X2}{1:X2}", (byte)(glyphIndex >> 8), (byte)glyphIndex); #else byte[] bytes = new byte[2] { (byte)(glyphIndex >> 8), (byte)glyphIndex }; bytes = PdfEncoders.FormatStringLiteral(bytes, true, false, true, null); string output = PdfEncoders.RawEncoding.GetString(bytes); #endif // At the end of the glyph run we must always render if (!mustRender) mustRender = codeIdx + clusterMapping.ClusterCodeUnitCount >= codeCount // is it the last code unit cluster && glyphIdx + clusterGlyphIdx + 1 >= glyphCount; // is it the last glyph index //mustRender = true; if (mustRender) { outputText.Append('>'); WriteLiteral("{0:0.####} {1:0.####} Td {2}Tj\n", pos.x, pos.y, outputText.ToString()); double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); if (!PdfSharp.Internal.DoubleUtil.IsNaN(mapping.AdvanceWidth)) width = mapping.AdvanceWidth * 10; pos = new XPoint(accumulatedWidth + width * boldSimulationFactor / 1000 * glyphs.FontRenderingEmSize, 0); // reset values accumulatedWidth = 0; outputGlyphCount = 0; outputText.Length = 0; mustRender = false; } else // deferred rendering { // accumulate width Debug.Assert(DoubleUtil.IsNaN(mapping.AdvanceWidth)); double width = descriptor.GlyphIndexToPdfWidth(glyphIndex); width = width * boldSimulationFactor / 1000 * glyphs.FontRenderingEmSize; accumulatedWidth += width; outputGlyphCount++; } } codeIdx += clusterMapping.ClusterCodeUnitCount; glyphIdx += clusterMapping.ClusterGlyphCount; if (codeIdx >= codeCount && glyphIdx >= glyphCount) stop = true; } while (!stop); }