Save This Page
Home » openjdk-7 » java » awt » font » [javadoc | source]
    1   /*
    2    * Copyright 1997-1999 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   /*
   27    * (C) Copyright Taligent, Inc. 1996 - 1997, All Rights Reserved
   28    * (C) Copyright IBM Corp. 1996 - 1998, All Rights Reserved
   29    *
   30    * The original version of this source code and documentation is
   31    * copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary
   32    * of IBM. These materials are provided under terms of a License
   33    * Agreement between Taligent and Sun. This technology is protected
   34    * by multiple US and International patents.
   35    *
   36    * This notice and attribution to Taligent may not be removed.
   37    * Taligent is a registered trademark of Taligent, Inc.
   38    *
   39    */
   40   
   41   package java.awt.font;
   42   
   43   /*
   44    * one info for each side of each glyph
   45    * separate infos for grow and shrink case
   46    * !!! this doesn't really need to be a separate class.  If we keep it
   47    * separate, probably the newJustify code from TextLayout belongs here as well.
   48    */
   49   
   50   class TextJustifier {
   51       private GlyphJustificationInfo[] info;
   52       private int start;
   53       private int limit;
   54   
   55       static boolean DEBUG = false;
   56   
   57       /**
   58        * Initialize the justifier with an array of infos corresponding to each
   59        * glyph. Start and limit indicate the range of the array to examine.
   60        */
   61       TextJustifier(GlyphJustificationInfo[] info, int start, int limit) {
   62           this.info = info;
   63           this.start = start;
   64           this.limit = limit;
   65   
   66           if (DEBUG) {
   67               System.out.println("start: " + start + ", limit: " + limit);
   68               for (int i = start; i < limit; i++) {
   69                   GlyphJustificationInfo gji = info[i];
   70                   System.out.println("w: " + gji.weight + ", gp: " +
   71                                      gji.growPriority + ", gll: " +
   72                                      gji.growLeftLimit + ", grl: " +
   73                                      gji.growRightLimit);
   74               }
   75           }
   76       }
   77   
   78       public static final int MAX_PRIORITY = 3;
   79   
   80       /**
   81        * Return an array of deltas twice as long as the original info array,
   82        * indicating the amount by which each side of each glyph should grow
   83        * or shrink.
   84        *
   85        * Delta should be positive to expand the line, and negative to compress it.
   86        */
   87       public float[] justify(float delta) {
   88           float[] deltas = new float[info.length * 2];
   89   
   90           boolean grow = delta > 0;
   91   
   92           if (DEBUG)
   93               System.out.println("delta: " + delta);
   94   
   95           // make separate passes through glyphs in order of decreasing priority
   96           // until justifyDelta is zero or we run out of priorities.
   97           int fallbackPriority = -1;
   98           for (int p = 0; delta != 0; p++) {
   99               /*
  100                * special case 'fallback' iteration, set flag and recheck
  101                * highest priority
  102                */
  103               boolean lastPass = p > MAX_PRIORITY;
  104               if (lastPass)
  105                   p = fallbackPriority;
  106   
  107               // pass through glyphs, first collecting weights and limits
  108               float weight = 0;
  109               float gslimit = 0;
  110               float absorbweight = 0;
  111               for (int i = start; i < limit; i++) {
  112                   GlyphJustificationInfo gi = info[i];
  113                   if ((grow ? gi.growPriority : gi.shrinkPriority) == p) {
  114                       if (fallbackPriority == -1) {
  115                           fallbackPriority = p;
  116                       }
  117   
  118                       if (i != start) { // ignore left of first character
  119                           weight += gi.weight;
  120                           if (grow) {
  121                               gslimit += gi.growLeftLimit;
  122                               if (gi.growAbsorb) {
  123                                   absorbweight += gi.weight;
  124                               }
  125                           } else {
  126                               gslimit += gi.shrinkLeftLimit;
  127                               if (gi.shrinkAbsorb) {
  128                                   absorbweight += gi.weight;
  129                               }
  130                           }
  131                       }
  132   
  133                       if (i + 1 != limit) { // ignore right of last character
  134                           weight += gi.weight;
  135                           if (grow) {
  136                               gslimit += gi.growRightLimit;
  137                               if (gi.growAbsorb) {
  138                                   absorbweight += gi.weight;
  139                               }
  140                           } else {
  141                               gslimit += gi.shrinkRightLimit;
  142                               if (gi.shrinkAbsorb) {
  143                                   absorbweight += gi.weight;
  144                               }
  145                           }
  146                       }
  147                   }
  148               }
  149   
  150               // did we hit the limit?
  151               if (!grow) {
  152                   gslimit = -gslimit; // negative for negative deltas
  153               }
  154               boolean hitLimit = (weight == 0) || (!lastPass && ((delta < 0) == (delta < gslimit)));
  155               boolean absorbing = hitLimit && absorbweight > 0;
  156   
  157               // predivide delta by weight
  158               float weightedDelta = delta / weight; // not used if weight == 0
  159   
  160               float weightedAbsorb = 0;
  161               if (hitLimit && absorbweight > 0) {
  162                   weightedAbsorb = (delta - gslimit) / absorbweight;
  163               }
  164   
  165               if (DEBUG) {
  166                   System.out.println("pass: " + p +
  167                       ", d: " + delta +
  168                       ", l: " + gslimit +
  169                       ", w: " + weight +
  170                       ", aw: " + absorbweight +
  171                       ", wd: " + weightedDelta +
  172                       ", wa: " + weightedAbsorb +
  173                       ", hit: " + (hitLimit ? "y" : "n"));
  174               }
  175   
  176               // now allocate this based on ratio of weight to total weight
  177               int n = start * 2;
  178               for (int i = start; i < limit; i++) {
  179                   GlyphJustificationInfo gi = info[i];
  180                   if ((grow ? gi.growPriority : gi.shrinkPriority) == p) {
  181                       if (i != start) { // ignore left
  182                           float d;
  183                           if (hitLimit) {
  184                               // factor in sign
  185                               d = grow ? gi.growLeftLimit : -gi.shrinkLeftLimit;
  186                               if (absorbing) {
  187                                   // sign factored in already
  188                                  d += gi.weight * weightedAbsorb;
  189                               }
  190                           } else {
  191                               // sign factored in already
  192                               d = gi.weight * weightedDelta;
  193                           }
  194   
  195                           deltas[n] += d;
  196                       }
  197                       n++;
  198   
  199                       if (i + 1 != limit) { // ignore right
  200                           float d;
  201                           if (hitLimit) {
  202                               d = grow ? gi.growRightLimit : -gi.shrinkRightLimit;
  203                               if (absorbing) {
  204                                   d += gi.weight * weightedAbsorb;
  205                               }
  206                           } else {
  207                               d = gi.weight * weightedDelta;
  208                           }
  209   
  210                           deltas[n] += d;
  211                       }
  212                       n++;
  213                   } else {
  214                       n += 2;
  215                   }
  216               }
  217   
  218               if (!lastPass && hitLimit && !absorbing) {
  219                   delta -= gslimit;
  220               } else {
  221                   delta = 0; // stop iteration
  222               }
  223           }
  224   
  225           if (DEBUG) {
  226               float total = 0;
  227               for (int i = 0; i < deltas.length; i++) {
  228                   total += deltas[i];
  229                   System.out.print(deltas[i] + ", ");
  230                   if (i % 20 == 9) {
  231                       System.out.println();
  232                   }
  233               }
  234               System.out.println("\ntotal: " + total);
  235               System.out.println();
  236           }
  237   
  238           return deltas;
  239       }
  240   }

Save This Page
Home » openjdk-7 » java » awt » font » [javadoc | source]