// ...on the way to handle Indices... private void WriteGlyphsInternal(Glyphs glyphs, string text) { var complexity = GlyphIndicesComplexity.None; var indices = new GlyphIndices(glyphs.Indices); if (glyphs.Indices != null) { complexity = indices.Complexity; } complexity = GlyphIndicesComplexity.ClusterMapping; switch (complexity) { case GlyphIndicesComplexity.None: break; case GlyphIndicesComplexity.DistanceOnly: WriteGlyphs_DistanceOnly(glyphs); break; case GlyphIndicesComplexity.GlyphIndicesAndDistanceOnly: break; case GlyphIndicesComplexity.ClusterMapping: WriteGlyphs_ClusterMapping(glyphs); break; } }
/// <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); }