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

com.adobe.fontengine.inlineformatting.infontformatting.InFontFormatter Maven / Gradle / Ivy

/*
*
*	File: InFontFormatter.java
*
*
*	ADOBE CONFIDENTIAL
*	___________________
*
*	Copyright 2004-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.infontformatting;

import java.util.HashSet;
import java.util.Set;

import com.adobe.agl.lang.UScript;
import com.adobe.fontengine.font.FontData;
import com.adobe.fontengine.font.FontLoadingException;
import com.adobe.fontengine.font.InvalidFontException;
import com.adobe.fontengine.font.UnsupportedFontException;
import com.adobe.fontengine.inlineformatting.AttributedRun;
import com.adobe.fontengine.inlineformatting.ElementAttribute;

/** Interprets the styling constraints which are implement by in-font processing. */
final public class InFontFormatter {
  private InFontFormatter () {
    // this class only hold static methods and data
  }
  
  private static final BaseFormatter[] scriptFormatters = new BaseFormatter [UScript.CODE_LIMIT];
  private static final BaseFormatter glyphFormatter = new GlyphFormatter ();
  
   static {
     BaseFormatter genericFormatter = new GenericFormatter ();
     for (int i = 0; i < scriptFormatters.length; i++) {
       scriptFormatters [i] = genericFormatter; }
     
     scriptFormatters [UScript.ARABIC] = new ArabicFormatter ();
     scriptFormatters [UScript.BENGALI] =  new BengaliFormatter ();
     scriptFormatters [UScript.DEVANAGARI] = new DevanagariFormatter ();
     scriptFormatters [UScript.GUJARATI] = new GujaratiFormatter ();
     scriptFormatters [UScript.GURMUKHI] = new GurmukhiFormatter ();
     scriptFormatters [UScript.HANGUL] = new HangulFormatter ();
     scriptFormatters [UScript.KANNADA] = new KannadaFormatter ();
     scriptFormatters [UScript.LAO] = new LaoFormatter ();
//     scriptFormatters [UScript.MYANMAR] = new MyanmarFormatter ();
     scriptFormatters [UScript.ORIYA] = new OriyaFormatter ();
     scriptFormatters [UScript.TAMIL] = new TamilFormatter ();
     scriptFormatters [UScript.TELUGU] = new TeluguFormatter ();
     scriptFormatters [UScript.THAI] = new ThaiFormatter ();
     scriptFormatters [UScript.TIBETAN] = new TibetanFormatter ();

     BaseFormatter hanKanaFormatter = new HanKanaFormatter ();
     scriptFormatters [UScript.HIRAGANA] = hanKanaFormatter;
     scriptFormatters [UScript.KATAKANA] = hanKanaFormatter;
     scriptFormatters [UScript.KATAKANA_OR_HIRAGANA] = hanKanaFormatter;
     scriptFormatters [UScript.HAN] = hanKanaFormatter;
   }
                      
  
  /** the resolved Unicode script of an element.
   * The value is a {@link com.adobe.agl.lang.UScript}, which is neither
   * INHERITED nor COMMON. */
  public static final ElementAttribute scriptAttribute = new ElementAttribute ("script");

  protected static final Set /**/ typographicSystem;
  static {
    typographicSystem = new HashSet ();
    typographicSystem.add (scriptAttribute);
    typographicSystem.add (ElementAttribute.locale);
    typographicSystem.add (ElementAttribute.isGlyph);
  }
  
  protected static final Set /**/ fontAtts; 
  static {
    fontAtts = new HashSet ();
    fontAtts.add (ElementAttribute.font);
  }


  /** Set the script attribute. 
   */
  static void resolveScript (AttributedRun run, int first, int limit) {
    int ambientScriptNumber = UScript.COMMON;
    Integer ambientScript = null;
    int lastToFix = first-1;
    
    for (int i = first; i < limit; i++) {
      if (run.getElementStyle (i, ElementAttribute.isGlyph) != Boolean.TRUE) {
        int script = UScript.getScript (run.elementAt (i));
        if (script == UScript.COMMON || script == UScript.INHERITED) {
          if (ambientScript != null) {
            run.setElementStyle (i, scriptAttribute, ambientScript); }
          else {
            lastToFix = i; }}
        else {
          if (script != ambientScriptNumber) {
            ambientScriptNumber = script;
            ambientScript = new Integer (script);
            if (lastToFix != first-1) {
              for (int k = first; k <= lastToFix; k++) {
                run.setElementStyle (k, scriptAttribute, ambientScript); }
              lastToFix = first - 1;}}
          run.setElementStyle (i, scriptAttribute, ambientScript); }}}
    
    if (lastToFix != first-1) {
      for (int k = first; k <= lastToFix; k++) {
        run.setElementStyle (k, scriptAttribute, new Integer (UScript.LATIN)); }}
  }

  public static int preFormat (AttributedRun run, int start, int limit) {
    
    while (start < limit) {
      int glyphLimit = run.getSubrunLimit (start, limit, ElementAttribute.isGlyph);
      boolean isGlyph = ((Boolean) run.getElementStyle (start, ElementAttribute.isGlyph)).booleanValue ();
      
      if (isGlyph) {
        start = glyphLimit; }
      
      else {
        resolveScript (run, start, glyphLimit); 
        start = glyphLimit; }}

    return limit;
  }
  
  public static int firstPass (AttributedRun run, int start, int limit) {
    
    while (start < limit) {
      int glyphLimit = run.getSubrunLimit (start, limit, ElementAttribute.isGlyph);
      boolean isGlyph = ((Boolean) run.getElementStyle (start, ElementAttribute.isGlyph)).booleanValue ();
      
      if (isGlyph) {
        start = glyphLimit; }
      
      else {
        while (start < glyphLimit) {
          int scriptLimit = run.getSubrunLimit (start, glyphLimit, scriptAttribute);
          int script = ((Integer) run.getElementStyle (start, scriptAttribute)).intValue ();
          int newScriptLimit = scriptFormatters [script].firstPass (run, start, scriptLimit);
          start = newScriptLimit;
          glyphLimit += (newScriptLimit - scriptLimit);
          limit += (newScriptLimit - scriptLimit); }}}
    return limit;
  }
  
  /**
   * Indentify a minimum character sequence and determine if it can be rendered
   * using a given font.
   * 
   * When rendering characters, some sequences of characters should be
   * considered atomic, in the sense that it is not meaningfull to break the
   * rendering of those sequences across fonts. For example, a combining
   * sequence can hardly be rendered by rendering separately the base and the
   * combining character(s). Similarly, a Hangul jamo sequence can hardly be
   * rendered by handling separately the jamos. The first step of this method is
   * to identify the atomic sequence which starts at start in the
   * run, and extends at most to limit.
   * 
   * The second step is to determine if that atomic sequence can be rendered
   * without .notdef by font. If that is not possible, this
   * method returns 0. If that is possible, this method return the number of
   * characters in the atomic sequence.
   * 
   * It may be necessary to determine the length of an atomic sequence, even
   * if its rendering will produce  one or more.notdef. To do this, set
   * the notdefOK parameter to true.
   * 
   * When this method is called, at least the element at index 
   * start must be a character.
   * 
   * This method does not modify the run. In particular, it is up to the 
   * caller to put the ElementAttribute.font attribute if desired.
   */
  public static int canRenderWithFont (FontData font, AttributedRun run, int start, int limit)
      throws InvalidFontException, UnsupportedFontException, FontLoadingException {

    int script = ((Integer) run.getElementStyle (start, scriptAttribute)).intValue ();
    return scriptFormatters [script].canRenderWithFont (font, run, start, limit); 
  }
 
  public static int canRenderWithNotdef (AttributedRun run, int start, int limit)
  throws InvalidFontException, UnsupportedFontException, FontLoadingException {
    
    int script = ((Integer) run.getElementStyle (start, scriptAttribute)).intValue ();
    return scriptFormatters [script].canRenderWithNotdef (run, start, limit); 
  }
  
  /** Format the run. 
   * 
   * The run can contain a mixture of characters and glyphs; the latter are
   * not changed, but are positioned.
   */
  public static int format (AttributedRun run, int start, int limit, boolean shouldKern) 
      throws InvalidFontException, UnsupportedFontException, FontLoadingException {

    while (start < limit) {
      int typographicSystemLimit = run.getSubrunLimit (start, limit, typographicSystem);
      int newTypographicSystemLimit;
      
      boolean isGlyph = ((Boolean) run.getElementStyle (start, ElementAttribute.isGlyph)).booleanValue ();
      
      if (isGlyph) {
        newTypographicSystemLimit = glyphFormatter.format (run, start, typographicSystemLimit, shouldKern); }
      
      else {         
        int script = ((Integer) run.getElementStyle (start, scriptAttribute)).intValue ();
        newTypographicSystemLimit = scriptFormatters [script].format (run, start, typographicSystemLimit, shouldKern); }

      start = newTypographicSystemLimit;
      limit += (newTypographicSystemLimit - typographicSystemLimit); }
    
    return limit;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy