jdk/src/share/native/sun/font/FontInstanceAdapter.cpp
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Portions Copyright 1999-2007 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 IBM Corp. 1998-2001 - All Rights Reserved
       
    28  *
       
    29  * The original version of this source code and documentation is
       
    30  * copyrighted and owned by IBM. These materials are provided
       
    31  * under terms of a License Agreement between IBM and Sun.
       
    32  * This technology is protected by multiple US and International
       
    33  * patents. This notice and attribution to IBM may not be removed.
       
    34  */
       
    35 
       
    36 #include "FontInstanceAdapter.h"
       
    37 
       
    38 FontInstanceAdapter::FontInstanceAdapter(JNIEnv *theEnv,
       
    39                                          jobject theFont2D,
       
    40                                          jobject theFontStrike,
       
    41                                          float *matrix,
       
    42                                          le_int32 xRes, le_int32 yRes,
       
    43                                          le_int32 theUPEM,
       
    44                                          TTLayoutTableCache *ltables)
       
    45     : env(theEnv), font2D(theFont2D), fontStrike(theFontStrike),
       
    46       xppem(0), yppem(0),
       
    47       xScaleUnitsToPoints(0), yScaleUnitsToPoints(0),
       
    48       xScalePixelsToUnits(0), yScalePixelsToUnits(0),
       
    49       upem(theUPEM), layoutTables(ltables)
       
    50 {
       
    51     xPointSize = euclidianDistance(matrix[0], matrix[1]);
       
    52     yPointSize = euclidianDistance(matrix[2], matrix[3]);
       
    53 
       
    54     txMat[0] = matrix[0]/xPointSize;
       
    55     txMat[1] = matrix[1]/xPointSize;
       
    56     txMat[2] = matrix[2]/yPointSize;
       
    57     txMat[3] = matrix[3]/yPointSize;
       
    58 
       
    59     xppem = ((float) xRes / 72) * xPointSize;
       
    60     yppem = ((float) yRes / 72) * yPointSize;
       
    61 
       
    62     xScaleUnitsToPoints = xPointSize / upem;
       
    63     yScaleUnitsToPoints = yPointSize / upem;
       
    64 
       
    65     xScalePixelsToUnits = upem / xppem;
       
    66     yScalePixelsToUnits = upem / yppem;
       
    67 };
       
    68 
       
    69 const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
       
    70 {
       
    71   if (!layoutTables) { // t1 font
       
    72     return 0;
       
    73   }
       
    74 
       
    75   // cache in font's pscaler object
       
    76   // font disposer will handle for us
       
    77 
       
    78   switch(tableTag) {
       
    79   case GSUB_TAG: if (layoutTables->gsub_len != -1) return (void*)layoutTables->gsub; break;
       
    80   case GPOS_TAG: if (layoutTables->gpos_len != -1) return (void*)layoutTables->gpos; break;
       
    81   case GDEF_TAG: if (layoutTables->gdef_len != -1) return (void*)layoutTables->gdef; break;
       
    82   case MORT_TAG: if (layoutTables->mort_len != -1) return (void*)layoutTables->mort; break;
       
    83   case KERN_TAG: if (layoutTables->kern_len != -1) return (void*)layoutTables->kern; break;
       
    84   default:
       
    85    //fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
       
    86     return 0;
       
    87   }
       
    88 
       
    89   jbyte* result = 0;
       
    90   jsize  len = 0;
       
    91   jbyteArray tableBytes = (jbyteArray)
       
    92     env->CallObjectMethod(font2D, sunFontIDs.getTableBytesMID, tableTag);
       
    93   if (!IS_NULL(tableBytes)) {
       
    94     len = env->GetArrayLength(tableBytes);
       
    95     result = new jbyte[len];
       
    96     env->GetByteArrayRegion(tableBytes, 0, len, result);
       
    97   }
       
    98 
       
    99   switch(tableTag) {
       
   100   case GSUB_TAG: layoutTables->gsub = (void*)result; layoutTables->gsub_len = len; break;
       
   101   case GPOS_TAG: layoutTables->gpos = (void*)result; layoutTables->gpos_len = len; break;
       
   102   case GDEF_TAG: layoutTables->gdef = (void*)result; layoutTables->gdef_len = len; break;
       
   103   case MORT_TAG: layoutTables->mort = (void*)result; layoutTables->mort_len = len; break;
       
   104   case KERN_TAG: layoutTables->kern = (void*)result; layoutTables->kern_len = len; break;
       
   105   default: break;
       
   106   }
       
   107 
       
   108   return (void*)result;
       
   109 };
       
   110 
       
   111 LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
       
   112 {
       
   113     LEUnicode32 mappedChar = mapper->mapChar(ch);
       
   114 
       
   115     if (mappedChar == 0xFFFF || mappedChar == 0xFFFE) {
       
   116         return 0xFFFF;
       
   117     }
       
   118 
       
   119     if (mappedChar == 0x200C || mappedChar == 0x200D) {
       
   120         return 1;
       
   121     }
       
   122 
       
   123     LEGlyphID id = (LEGlyphID)env->CallIntMethod(font2D, sunFontIDs.f2dCharToGlyphMID, (jint)mappedChar);
       
   124     return id;
       
   125 }
       
   126 
       
   127 LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch) const
       
   128 {
       
   129     LEGlyphID id = (LEGlyphID)env->CallIntMethod(font2D, sunFontIDs.f2dCharToGlyphMID, ch);
       
   130     return id;
       
   131 }
       
   132 
       
   133 void FontInstanceAdapter::mapCharsToWideGlyphs(const LEUnicode chars[],
       
   134     le_int32 offset, le_int32 count, le_bool reverse,
       
   135     const LECharMapper *mapper, le_uint32 glyphs[]) const
       
   136 {
       
   137     le_int32 i, out = 0, dir = 1;
       
   138 
       
   139     if (reverse) {
       
   140         out = count - 1;
       
   141         dir = -1;
       
   142     }
       
   143 
       
   144     for (i = offset; i < offset + count; i += 1, out += dir) {
       
   145                 LEUnicode16 high = chars[i];
       
   146                 LEUnicode32 code = high;
       
   147 
       
   148                 if (i < offset + count - 1 && high >= 0xD800 && high <= 0xDBFF) {
       
   149                         LEUnicode16 low = chars[i + 1];
       
   150 
       
   151                         if (low >= 0xDC00 && low <= 0xDFFF) {
       
   152                                 code = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000;
       
   153                         }
       
   154                 }
       
   155 
       
   156         glyphs[out] = mapCharToWideGlyph(code, mapper);
       
   157 
       
   158                 if (code >= 0x10000) {
       
   159                         i += 1;
       
   160                         glyphs[out += dir] = 0xFFFF;
       
   161                 }
       
   162     }
       
   163 }
       
   164 
       
   165 le_uint32 FontInstanceAdapter::mapCharToWideGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
       
   166 {
       
   167     LEUnicode32 mappedChar = mapper->mapChar(ch);
       
   168 
       
   169     if (mappedChar == 0xFFFF) {
       
   170         return 0xFFFF;
       
   171     }
       
   172 
       
   173     if (mappedChar == 0x200C || mappedChar == 0x200D) {
       
   174         return 1;
       
   175     }
       
   176 
       
   177     return (LEGlyphID)env->CallIntMethod(font2D, sunFontIDs.charToGlyphMID,
       
   178                                          mappedChar);
       
   179 }
       
   180 
       
   181 void FontInstanceAdapter::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const
       
   182 {
       
   183     getWideGlyphAdvance((le_uint32)glyph, advance);
       
   184 }
       
   185 
       
   186 void FontInstanceAdapter::getKerningAdjustment(LEPoint &adjustment) const
       
   187 {
       
   188     float xx, xy, yx, yy;
       
   189     le_bool isIdentityMatrix;
       
   190 
       
   191     isIdentityMatrix = (txMat[0] == 1 && txMat[1] == 0 &&
       
   192                         txMat[2] == 0 && txMat[3] == 1);
       
   193 
       
   194     if (!isIdentityMatrix) {
       
   195       xx = adjustment.fX;
       
   196       xy = xx * txMat[1];
       
   197       xx = xx * txMat[0];
       
   198 
       
   199       yy = adjustment.fY;
       
   200       yx = yy * txMat[2];
       
   201       yy = yy * txMat[3];
       
   202 
       
   203       adjustment.fX = xx + yx;
       
   204       adjustment.fY = xy + yy;
       
   205     }
       
   206 
       
   207     jobject pt = env->NewObject(sunFontIDs.pt2DFloatClass,
       
   208                                 sunFontIDs.pt2DFloatCtr,
       
   209                                 adjustment.fX, adjustment.fY);
       
   210     env->CallObjectMethod(fontStrike, sunFontIDs.adjustPointMID, pt);
       
   211     adjustment.fX = env->GetFloatField(pt, sunFontIDs.xFID);
       
   212     adjustment.fY = env->GetFloatField(pt, sunFontIDs.yFID);
       
   213 }
       
   214 
       
   215 void FontInstanceAdapter::getWideGlyphAdvance(le_uint32 glyph, LEPoint &advance) const
       
   216 {
       
   217     if ((glyph & 0xfffe) == 0xfffe) {
       
   218         advance.fX = 0;
       
   219         advance.fY = 0;
       
   220         return;
       
   221     }
       
   222     jobject pt = env->CallObjectMethod(fontStrike,
       
   223                                        sunFontIDs.getGlyphMetricsMID, glyph);
       
   224     if (pt != NULL) {
       
   225         advance.fX = env->GetFloatField(pt, sunFontIDs.xFID);
       
   226         advance.fY = env->GetFloatField(pt, sunFontIDs.yFID);
       
   227     }
       
   228 }
       
   229 
       
   230 le_bool FontInstanceAdapter::getGlyphPoint(LEGlyphID glyph,
       
   231                                            le_int32 pointNumber,
       
   232                                            LEPoint &point) const
       
   233 {
       
   234   /* This upcall is not ideal, since it will make another down call.
       
   235    * The intention is to move up some of this code into Java. But
       
   236    * a HashMap has been added to the Java PhysicalStrike object to cache
       
   237    * these points so that they don't need to be repeatedly recalculated
       
   238    * which is expensive as it needs the font scaler to re-generate the
       
   239    * hinted glyph outline. This turns out to be a huge win over 1.4.x
       
   240    */
       
   241      jobject pt = env->CallObjectMethod(fontStrike,
       
   242                                         sunFontIDs.getGlyphPointMID,
       
   243                                         glyph, pointNumber);
       
   244      if (pt != NULL) {
       
   245        /* point is a java.awt.geom.Point2D.Float */
       
   246         point.fX = env->GetFloatField(pt, sunFontIDs.xFID);
       
   247         /* convert from java coordinate system to internal '+y up' coordinate system */
       
   248         point.fY = -env->GetFloatField(pt, sunFontIDs.yFID);
       
   249         return true;
       
   250      } else {
       
   251         return false;
       
   252      }
       
   253 }
       
   254 
       
   255 void FontInstanceAdapter::transformFunits(float xFunits, float yFunits, LEPoint &pixels) const
       
   256 {
       
   257     float xx, xy, yx, yy;
       
   258     le_bool isIdentityMatrix;
       
   259 
       
   260     isIdentityMatrix = (txMat[0] == 1 && txMat[1] == 0 &&
       
   261                         txMat[2] == 0 && txMat[3] == 1);
       
   262 
       
   263     xx = xFunits * xScaleUnitsToPoints;
       
   264     xy = 0;
       
   265     if (!isIdentityMatrix) {
       
   266         xy = xx * txMat[1];
       
   267         xx = xx * txMat[0];
       
   268     };
       
   269 
       
   270     yx = 0;
       
   271     yy = yFunits * yScaleUnitsToPoints;
       
   272     if (!isIdentityMatrix) {
       
   273         yx = yy * txMat[2];
       
   274         yy = yy * txMat[3];
       
   275     };
       
   276     pixels.fX = xx + yx;
       
   277     pixels.fY = xy + yy;
       
   278 }
       
   279 
       
   280 
       
   281 float FontInstanceAdapter::euclidianDistance(float a, float b)
       
   282 {
       
   283     if (a < 0) {
       
   284         a = -a;
       
   285     }
       
   286 
       
   287     if (b < 0) {
       
   288         b = -b;
       
   289     }
       
   290 
       
   291     if (a == 0) {
       
   292         return b;
       
   293     }
       
   294 
       
   295     if (b == 0) {
       
   296         return a;
       
   297     }
       
   298 
       
   299     float root = a > b ? a + (b / 2) : b + (a / 2); /* Do an initial approximation, in root */
       
   300 
       
   301         /* An unrolled Newton-Raphson iteration sequence */
       
   302     root = (root + (a * (a / root)) + (b * (b / root)) + 1) / 2;
       
   303     root = (root + (a * (a / root)) + (b * (b / root)) + 1) / 2;
       
   304     root = (root + (a * (a / root)) + (b * (b / root)) + 1) / 2;
       
   305 
       
   306     return root;
       
   307 }