public int addCharacter(char data, LinkSet ls, bool ul) { WordArea ia = null; int remainingWidth = this.getRemainingWidth(); int width = this.currentFontState.GetWidth(currentFontState.MapCharacter(data)); if (width > remainingWidth) { return Character.DOESNOT_FIT; } else { if (Char.IsWhiteSpace(data) && whiteSpaceCollapse == WhiteSpaceCollapse.TRUE) { return Character.OK; } ia = new WordArea(currentFontState, this.red, this.green, this.blue, data.ToString(), width); ia.setYOffset(placementOffset); ia.setUnderlined(ul); pendingAreas.Add(ia); if (Char.IsWhiteSpace(data)) { this.spaceWidth = +width; prev = LineArea.WHITESPACE; } else { pendingWidth += width; prev = LineArea.TEXT; } return Character.OK; } }
private void addWord(char startChar, StringBuilder wordBuf) { string word = (wordBuf != null) ? wordBuf.ToString() : ""; WordArea hia; int startCharWidth = getCharWidth(startChar); if (isAnySpace(startChar)) { this.addChild(new InlineSpace(startCharWidth)); } else { hia = new WordArea(currentFontState, this.red, this.green, this.blue, startChar.ToString(), 1); hia.setYOffset(placementOffset); this.addChild(hia); } int wordWidth = this.getWordWidth(word); hia = new WordArea(currentFontState, this.red, this.green, this.blue, word, word.Length); hia.setYOffset(placementOffset); this.addChild(hia); finalWidth += startCharWidth + wordWidth; }
private InlineArea buildSimpleLeader(char c, int leaderLength) { int width = this.currentFontState.GetWidth(currentFontState.MapCharacter(c)); if (width == 0) { FonetDriver.ActiveDriver.FireFonetError( "char '" + c + "' has width 0. Using width 100 instead."); width = 100; } int factor = (int)Math.Floor((decimal)leaderLength / width); char[] leaderChars = new char[factor]; for (int i = 0; i < factor; i++) { leaderChars[i] = c; } WordArea leaderPatternArea = new WordArea(currentFontState, this.red, this.green, this.blue, new String(leaderChars), leaderLength); leaderPatternArea.setYOffset(placementOffset); return leaderPatternArea; }
public void AddLeader(int leaderPattern, int leaderLengthMinimum, int leaderLengthOptimum, int leaderLengthMaximum, int ruleStyle, int ruleThickness, int leaderPatternWidth, int leaderAlignment) { WordArea leaderPatternArea; int leaderLength = 0; char dotIndex = '.'; int dotWidth = currentFontState.GetWidth(currentFontState.MapCharacter(dotIndex)); char whitespaceIndex = ' '; int whitespaceWidth = currentFontState.GetWidth(currentFontState.MapCharacter(whitespaceIndex)); int remainingWidth = this.getRemainingWidth(); if ((remainingWidth <= leaderLengthOptimum) || (remainingWidth <= leaderLengthMaximum)) { leaderLength = remainingWidth; } else if ((remainingWidth > leaderLengthOptimum) && (remainingWidth > leaderLengthMaximum)) { leaderLength = leaderLengthMaximum; } else if ((leaderLengthOptimum > leaderLengthMaximum) && (leaderLengthOptimum < remainingWidth)) { leaderLength = leaderLengthOptimum; } if (leaderLength <= 0) { return; } switch (leaderPattern) { case LeaderPattern.SPACE: InlineSpace spaceArea = new InlineSpace(leaderLength); pendingAreas.Add(spaceArea); break; case LeaderPattern.RULE: LeaderArea leaderArea = new LeaderArea(fontState, red, green, blue, "", leaderLength, leaderPattern, ruleThickness, ruleStyle); leaderArea.setYOffset(placementOffset); pendingAreas.Add(leaderArea); break; case LeaderPattern.DOTS: if (leaderPatternWidth < dotWidth) { leaderPatternWidth = 0; } if (leaderPatternWidth == 0) { pendingAreas.Add(this.buildSimpleLeader(dotIndex, leaderLength)); } else { if (leaderAlignment == LeaderAlignment.REFERENCE_AREA) { int spaceBeforeLeader = this.getLeaderAlignIndent(leaderLength, leaderPatternWidth); if (spaceBeforeLeader != 0) { pendingAreas.Add(new InlineSpace(spaceBeforeLeader, false)); pendingWidth += spaceBeforeLeader; leaderLength -= spaceBeforeLeader; } } InlineSpace spaceBetweenDots = new InlineSpace(leaderPatternWidth - dotWidth, false); leaderPatternArea = new WordArea(currentFontState, this.red, this.green, this.blue, ".", dotWidth); leaderPatternArea.setYOffset(placementOffset); int dotsFactor = (int)Math.Floor(((double)leaderLength) / ((double)leaderPatternWidth)); for (int i = 0; i < dotsFactor; i++) { pendingAreas.Add(leaderPatternArea); pendingAreas.Add(spaceBetweenDots); } pendingAreas.Add(new InlineSpace(leaderLength - dotsFactor * leaderPatternWidth)); } break; case LeaderPattern.USECONTENT: FonetDriver.ActiveDriver.FireFonetError( "leader-pattern=\"use-content\" not supported by this version of FO.NET"); return; } pendingWidth += leaderLength; prev = TEXT; }
private void addSpacedWord(string word, LinkSet ls, int startw, int spacew, TextState textState, bool addToPending) { /* * Split string based on four delimeters: * \u00A0 - Latin1 NBSP (Non breaking space) * \u202F - unknown reserved character according to Unicode Standard * \u3000 - CJK IDSP (Ideographic space) * \uFEFF - Arabic ZWN BSP (Zero width no break space) */ StringTokenizer st = new StringTokenizer(word, "\u00A0\u202F\u3000\uFEFF", true); int extraw = 0; while (st.MoveNext()) { string currentWord = (string)st.Current; if (currentWord.Length == 1 && (isNBSP(currentWord[0]))) { // Add an InlineSpace int spaceWidth = getCharWidth(currentWord[0]); if (spaceWidth > 0) { InlineSpace ispace = new InlineSpace(spaceWidth); extraw += spaceWidth; if (prevUlState) { ispace.setUnderlined(textState.getUnderlined()); } if (prevOlState) { ispace.setOverlined(textState.getOverlined()); } if (prevLTState) { ispace.setLineThrough(textState.getLineThrough()); } if (addToPending) { pendingAreas.Add(ispace); pendingWidth += spaceWidth; } else { addChild(ispace); } } } else { WordArea ia = new WordArea(currentFontState, this.red, this.green, this.blue, currentWord, getWordWidth(currentWord)); ia.setYOffset(placementOffset); ia.setUnderlined(textState.getUnderlined()); prevUlState = textState.getUnderlined(); ia.setOverlined(textState.getOverlined()); prevOlState = textState.getOverlined(); ia.setLineThrough(textState.getLineThrough()); prevLTState = textState.getLineThrough(); ia.setVerticalAlign(vAlign); if (addToPending) { pendingAreas.Add(ia); pendingWidth += getWordWidth(currentWord); } else { addChild(ia); } if (ls != null) { Rectangle lr = new Rectangle(startw + extraw, spacew, ia.getContentWidth(), fontState.FontSize); ls.addRect(lr, this, ia); } } } }
/** * render inline area to PDF * * @param area inline area to render */ public void RenderWordArea(WordArea area) { // TODO: I don't understand why we are locking the private member // _wordAreaPDF. Maybe this string buffer was originally static? (MG) lock (_wordAreaPDF) { StringBuilder pdf = _wordAreaPDF; pdf.Length = 0; GdiKerningPairs kerning = null; bool kerningAvailable = false; // If no options are supplied, by default we do not enable kerning if (options != null && options.Kerning) { kerning = area.GetFontState().Kerning; if (kerning != null && (kerning.Count > 0)) { kerningAvailable = true; } } String name = area.GetFontState().FontName; int size = area.GetFontState().FontSize; // This assumes that *all* CIDFonts use a /ToUnicode mapping Font font = (Font) area.GetFontState().FontInfo.GetFontByName(name); bool useMultiByte = font.MultiByteFont; string startText = useMultiByte ? "<" : "("; string endText = useMultiByte ? "> " : ") "; if ((!name.Equals(this.currentFontName)) || (size != this.currentFontSize)) { CloseText(); this.currentFontName = name; this.currentFontSize = size; pdf = pdf.Append("/" + name + " " + PdfNumber.doubleOut(size/1000f) + " Tf\n"); } // Do letter spacing (must be outside of [...] TJ] float letterspacing = ((float) area.GetFontState().LetterSpacing)/1000f; if (letterspacing != this.currentLetterSpacing) { this.currentLetterSpacing = letterspacing; CloseText(); pdf.Append(PdfNumber.doubleOut(letterspacing)); pdf.Append(" Tc\n"); } PdfColor areaColor = this.currentFill; if (areaColor == null || areaColor.getRed() != (double) area.getRed() || areaColor.getGreen() != (double) area.getGreen() || areaColor.getBlue() != (double) area.getBlue()) { areaColor = new PdfColor((double) area.getRed(), (double) area.getGreen(), (double) area.getBlue()); CloseText(); this.currentFill = areaColor; pdf.Append(this.currentFill.getColorSpaceOut(true)); } int rx = this.currentXPosition; int bl = this.currentYPosition; AddWordLines(area, rx, bl, size, areaColor); if (!textOpen || bl != prevWordY) { CloseText(); pdf.Append("1 0 0 1 " + PdfNumber.doubleOut(rx/1000f) + " " + PdfNumber.doubleOut(bl/1000f) + " Tm [" + startText); prevWordY = bl; textOpen = true; } else { // express the space between words in thousandths of an em int space = prevWordX - rx + prevWordWidth; float emDiff = (float) space/(float) currentFontSize*1000f; // this prevents a problem in Acrobat Reader where large // numbers cause text to disappear or default to a limit if (emDiff < -33000) { CloseText(); pdf.Append("1 0 0 1 " + PdfNumber.doubleOut(rx/1000f) + " " + PdfNumber.doubleOut(bl/1000f) + " Tm [" + startText); textOpen = true; } else { pdf.Append(PdfNumber.doubleOut(emDiff)); pdf.Append(" "); pdf.Append(startText); } } prevWordWidth = area.getContentWidth(); prevWordX = rx; string s; if (area.getPageNumberID() != null) { // This text is a page number, so resolve it s = idReferences.getPageNumber(area.getPageNumberID()); if (s == null) { s = String.Empty; } } else { s = area.getText(); } int wordLength = s.Length; for (int index = 0; index < wordLength; index++) { ushort ch = area.GetFontState().MapCharacter(s[index]); if (!useMultiByte) { if (ch > 127) { pdf.Append("\\"); pdf.Append(Convert.ToString((int) ch, 8)); } else { switch (ch) { case '(': case ')': case '\\': pdf.Append("\\"); break; } pdf.Append((char) ch); } } else { pdf.Append(GetUnicodeString(ch)); } if (kerningAvailable && (index + 1) < wordLength) { ushort ch2 = area.GetFontState().MapCharacter(s[index + 1]); AddKerning(pdf, ch, ch2, kerning, startText, endText); } } pdf.Append(endText); currentStream.Write(pdf.ToString()); this.currentXPosition += area.getContentWidth(); } }
private void AddWordLines(WordArea area, int rx, int bl, int size, PdfColor theAreaColor) { if (area.getUnderlined()) { int yPos = bl - size/10; AddLine(rx, yPos, rx + area.getContentWidth(), yPos, size/14, theAreaColor); // save position for underlining a following InlineSpace prevUnderlineXEndPos = rx + area.getContentWidth(); prevUnderlineYEndPos = yPos; prevUnderlineSize = size/14; prevUnderlineColor = theAreaColor; } if (area.getOverlined()) { int yPos = bl + area.GetFontState().Ascender + size/10; AddLine(rx, yPos, rx + area.getContentWidth(), yPos, size/14, theAreaColor); prevOverlineXEndPos = rx + area.getContentWidth(); prevOverlineYEndPos = yPos; prevOverlineSize = size/14; prevOverlineColor = theAreaColor; } if (area.getLineThrough()) { int yPos = bl + area.GetFontState().Ascender*3/8; AddLine(rx, yPos, rx + area.getContentWidth(), yPos, size/14, theAreaColor); prevLineThroughXEndPos = rx + area.getContentWidth(); prevLineThroughYEndPos = yPos; prevLineThroughSize = size/14; prevLineThroughColor = theAreaColor; } }