All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.fontengine.inlineformatting.PDF16PlainTextFormatter Maven / Gradle / Ivy

/*
 * File: PDF16PlainTextFormatter.java
 * 
 *	ADOBE CONFIDENTIAL
 *	___________________
 *
 *	Copyright 2005 Adobe Systems Incorporated
 *	All Rights Reserved.
 *
 *	NOTICE: All information contained herein is, and remains the property of
 *	Adobe Systems Incorporated and its suppliers, if any. The intellectual
 *	and technical concepts contained herein are proprietary to Adobe Systems
 *	Incorporated and its suppliers and may be covered by U.S. and Foreign
 *	Patents, patents in process, and are protected by trade secret or
 *	copyright law. Dissemination of this information or reproduction of this
 *	material is strictly forbidden unless prior written permission is
 *      obtained from Adobe Systems Incorporated.
 *
 */

package com.adobe.fontengine.inlineformatting;

import java.util.Iterator;

import com.adobe.agl.util.ULocale;
import com.adobe.fontengine.CharUtil;
import com.adobe.fontengine.font.Base14;
import com.adobe.fontengine.font.Font;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontException;
import com.adobe.fontengine.font.FontImpl;
import com.adobe.fontengine.fontmanagement.postscript.PostscriptFontDescription;
import com.adobe.fontengine.inlineformatting.infontformatting.InFontFormatter;
import com.adobe.fontengine.inlineformatting.infontformatting.ZapfDingbatsEncoding;

/**
 * Inline formatter for PDF 1.6 plain text form fields.
 *
 * 

The client must first pass a run corresponding to a whole paragraph to the * {@link #preFormat} method. It can then pass fragments of the run to the * {@link #format(AttributedRun, int, int, boolean)} or {@link #format(AttributedRun, int, int, boolean, boolean)} method. */ final public class PDF16PlainTextFormatter { private final FallbackFontSet fallbackFontSet; private PDF16PlainTextFormatter (FallbackFontSet fallbackFontSet) { // all instances created view getFormatterInstance () this.fallbackFontSet = fallbackFontSet; } /** * Create a PDF16PlainTextFormatter for formatting text. * *

Concurrency

* * The PDF16PlainTextFormatter instance that is returned from this * method is not in general thread safe. * * @param fallbackFontSet the fonts to use for character fallback * @return A PDF16PlainTextFormatter to be used for formatting text */ public static PDF16PlainTextFormatter getFormatterInstance (FallbackFontSet fallbackFontSet) { return new PDF16PlainTextFormatter (fallbackFontSet); } /** Interelement attribute to mark comb boundaries. * The value of this attribute is a {@link Boolean}. The preceding and * following elements should be in the same comb iff this attribute * has the value {@link Boolean#FALSE} */ final public static InterElementAttribute newComb = new InterElementAttribute ("newComb"); /** * Preformat an {@link AttributedRun}. * * This method should be called on a portion of an AttributedRun * corresponding to a whole paragraph, before the {@link #format(AttributedRun, int, int, boolean)} * or {@link #format(AttributedRun, int, int, boolean, boolean)} method. * * @param run an AttributedRun that contains the text to be formatted * @param start the index in the AttributedRun to start formatting from * @param limit the index in the AttributedRun at which formatting should cease (one * more than the last position that formatting should done to) * @return The new limit of the original range in the AttributedRun after the formatting operation. */ public int preFormat (AttributedRun run, int start, int limit) throws FontException, FormattingException { limit = InFontFormatter.preFormat (run, start, limit); return limit; } /** * Format an {@link AttributedRun} by resolving the styling constraints * to glyphs and positions for those glyphs. * *

This method should be called after the {@link #preFormat} method. * *

* On input: *

    * *
  • each element must be a character, i.e. must have the * {@link ElementAttribute#isGlyph} attribute set to {@link Boolean#FALSE} * *
  • each element must have {@link ElementAttribute#locale} set * *
  • each element must have {@link ElementAttribute#bidiLevel} set * *
  • each element must have {@link ElementAttribute#font} set to the * desired font * *
  • each element must have {@link ElementAttribute#pointSize} set to * the desired point size * *
  • each character element can have {@link ElementAttribute#fontStyle} set; * if not set, equivalent to {@link FontStyle#NORMAL} * *
  • each character element can have {@link ElementAttribute#typographicCase} set; * if not set, interpreted as {@link TypographicCase#NONE}. * *
  • each character element can have {@link ElementAttribute#digitCase} set; * if not set, equivalent to {@link DigitCase#DEFAULT} * *
  • each character element can have {@link ElementAttribute#digitWidth} set; * if not set, equivalent to {@link DigitWidth#DEFAULT} * *
  • each interelement can have {@link InterElementAttribute#ligatureLevel} set; * if not set, equivalent to {@link LigatureLevel#COMMON} * *
* *

* At some point during formatting, * {@link AttributedRun#startWorkingWithPositions startWorkingWithPositions} * will be called on the run. * *

* On output: *

    *
  • each element in the run will be a glyph, i.e. * {@link ElementAttribute#isGlyph} will be {@link Boolean#TRUE} * *
  • each element will have a placement and advance vector * *
  • each element will have {@link ElementAttribute#font} set to the * actual font to use * *
  • each element will have {@link ElementAttribute#pointSize} set to * the actual point size to use * *
  • if onComb is true, then each interelement will have * the {@link #newComb} attribute set *
* * @param run an AttributedRun that contains the text to be formatted * @param start the index in the AttributedRun to start formatting from * @param limit the index in the AttributedRun at which formatting should cease (one * more than the last position that formatting should done to) * @param onComb true iff the attributed run is displayed in a comb * * @return The new limit of the original range in the AttributedRun after the formatting operation. * @throws FontException * @throws FormattingException */ public int format (AttributedRun run, int start, int limit, boolean onComb) throws FontException, FormattingException { return format(run, start, limit, onComb, true /*kern*/); } /** * Format an {@link AttributedRun} by resolving the styling constraints * to glyphs and positions for those glyphs. * *

This method should be called after the {@link #preFormat} method. * *

* On input: *

    * *
  • each element must be a character, i.e. must have the * {@link ElementAttribute#isGlyph} attribute set to {@link Boolean#FALSE} * *
  • each element must have {@link ElementAttribute#locale} set * *
  • each element must have {@link ElementAttribute#bidiLevel} set * *
  • each element must have {@link ElementAttribute#font} set to the * desired font * *
  • each element must have {@link ElementAttribute#pointSize} set to * the desired point size * *
  • each character element can have {@link ElementAttribute#fontStyle} set; * if not set, equivalent to {@link FontStyle#NORMAL} * *
  • each character element can have {@link ElementAttribute#typographicCase} set; * if not set, interpreted as {@link TypographicCase#NONE}. * *
  • each character element can have {@link ElementAttribute#digitCase} set; * if not set, equivalent to {@link DigitCase#DEFAULT} * *
  • each character element can have {@link ElementAttribute#digitWidth} set; * if not set, equivalent to {@link DigitWidth#DEFAULT} * *
  • each interelement can have {@link InterElementAttribute#ligatureLevel} set; * if not set, equivalent to {@link LigatureLevel#COMMON} * *
* *

* At some point during formatting, * {@link AttributedRun#startWorkingWithPositions startWorkingWithPositions} * will be called on the run. * *

* On output: *

    *
  • each element in the run will be a glyph, i.e. * {@link ElementAttribute#isGlyph} will be {@link Boolean#TRUE} * *
  • each element will have a placement and advance vector * *
  • each element will have {@link ElementAttribute#font} set to the * actual font to use * *
  • each element will have {@link ElementAttribute#pointSize} set to * the actual point size to use * *
  • if onComb is true, then each interelement will have * the {@link #newComb} attribute set *
* * @param run an AttributedRun that contains the text to be formatted * @param start the index in the AttributedRun to start formatting from * @param limit the index in the AttributedRun at which formatting should cease (one * more than the last position that formatting should done to) * @param onComb true iff the attributed run is displayed in a comb * @param shouldKern whether or not kerning should be applied to the glyphs * @return The new limit of the original range in the AttributedRun after the formatting operation. * @throws FontException * @throws FormattingException */ public int format (AttributedRun run, int start, int limit, boolean onComb, boolean shouldKern) throws FontException, FormattingException { if (start >= limit) { return limit; } Font desiredFont = (Font) run.getElementStyle (start, ElementAttribute.font); //------------------------------------------------ Adobe Pi Std handling --- if (desiredFont != null) { PostscriptFontDescription[] fd = desiredFont.getPostscriptFontDescription (); for (int i = 0; i < fd.length; i++) { if ("AdobePiStd".equals (fd [i].getPSName ())) { ZapfDingbatsEncoding.remap (run, start, limit); break; }}} //----------------------------------------------------------- first pass --- limit = InFontFormatter.firstPass (run, start, limit); //------------------------------------------------------- font selection --- ULocale locale = (ULocale) run.getElementStyle (start, ElementAttribute.locale); if (desiredFont == null) { Iterator it = fallbackFontSet.getFallbackFonts (locale); if (it.hasNext ()) { desiredFont = (Font) it.next (); } else { // no font to format and no font in fallback set // it may be slightly better to go with a font that only contains .notdeff desiredFont = Base14.courierRegular; }} FontData desiredFontData = ((FontImpl) desiredFont).getFontData (); Font tentativeFont = null; try { int s = start; while (s < limit) { int consumed; // try the desired font tentativeFont = desiredFont; consumed = InFontFormatter.canRenderWithFont (desiredFontData, run, s, limit); // try the fallback fonts if (consumed == 0) { Iterator it = fallbackFontSet.getFallbackFonts (locale); while (consumed == 0 && it.hasNext ()) { tentativeFont = (Font) it.next(); consumed = InFontFormatter.canRenderWithFont (((FontImpl) tentativeFont).getFontData (), run, s, limit); }} // ok, no way to avoid .notdef, just use the desired font if (consumed == 0) { tentativeFont = desiredFont; consumed = InFontFormatter.canRenderWithNotdef (run, s, limit); } // at this point, c > 0, ensured by canRenderWithNotdef postcondition run.setElementStyle (s, s + consumed, ElementAttribute.font, tentativeFont); s += consumed; }} catch (FontException e) { e.initFont (tentativeFont); throw e; } //-------------------------------------------------------------------------- if (onComb) { run.setInterElementStyleBefore (start, newComb, Boolean.TRUE); int graphemeStart = start; int i = start + 1; while (i < limit) { if (! CharUtil.isCombining (run.elementAt (i))) { run.setInterElementStyleBefore (i, newComb, Boolean.TRUE); int newI = InFontFormatter.format (run, graphemeStart, i, shouldKern); limit += (newI - i); graphemeStart = newI; i = newI + 1; } else { run.setInterElementStyleBefore (i, newComb, Boolean.FALSE); i++; }} return InFontFormatter.format (run, graphemeStart, limit, shouldKern); } else { return InFontFormatter.format (run, start, limit, shouldKern); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy