< prev index next >

src/java.desktop/share/classes/sun/font/TrueTypeFont.java

Print this page
rev 60064 : 8248802: Add log helper methods to FontUtilities.java


 227             }
 228         }
 229         Disposer.addObjectRecord(this, disposerRecord);
 230     }
 231 
 232     private synchronized FileChannel open() throws FontFormatException {
 233         return open(true);
 234     }
 235 
 236     /* This is intended to be called, and the returned value used,
 237      * from within a block synchronized on this font object.
 238      * ie the channel returned may be nulled out at any time by "close()"
 239      * unless the caller holds a lock.
 240      * Deadlock warning: FontManager.addToPool(..) acquires a global lock,
 241      * which means nested locks may be in effect.
 242      */
 243     private synchronized FileChannel open(boolean usePool)
 244                                      throws FontFormatException {
 245         if (disposerRecord.channel == null) {
 246             if (FontUtilities.isLogging()) {
 247                 FontUtilities.getLogger().info("open TTF: " + platName);
 248             }
 249             try {
 250                 RandomAccessFile raf = AccessController.doPrivileged(
 251                     new PrivilegedExceptionAction<RandomAccessFile>() {
 252                         public RandomAccessFile run() throws FileNotFoundException {
 253                             return new RandomAccessFile(platName, "r");
 254                     }
 255                 });
 256                 disposerRecord.channel = raf.getChannel();
 257                 fileSize = (int)disposerRecord.channel.size();
 258                 if (usePool) {
 259                     FontManager fm = FontManagerFactory.getInstance();
 260                     if (fm instanceof SunFontManager) {
 261                         ((SunFontManager) fm).addToPool(this);
 262                     }
 263                 }
 264             } catch (PrivilegedActionException e) {
 265                 close();
 266                 Throwable reason = e.getCause();
 267                 if (reason == null) {


 295         try {
 296             synchronized (this) {
 297                 if (disposerRecord.channel == null) {
 298                     open();
 299                 }
 300                 if (offset + length > fileSize) {
 301                     if (offset >= fileSize) {
 302                         /* Since the caller ensures that offset is < fileSize
 303                          * this condition suggests that fileSize is now
 304                          * different than the value we originally provided
 305                          * to native when the scaler was created.
 306                          * Also fileSize is updated every time we
 307                          * open() the file here, but in native the value
 308                          * isn't updated. If the file has changed whilst we
 309                          * are executing we want to bail, not spin.
 310                          */
 311                         if (FontUtilities.isLogging()) {
 312                             String msg = "Read offset is " + offset +
 313                                 " file size is " + fileSize+
 314                                 " file is " + platName;
 315                             FontUtilities.getLogger().severe(msg);
 316                         }
 317                         return -1;
 318                     } else {
 319                         length = fileSize - offset;
 320                     }
 321                 }
 322                 buffer.clear();
 323                 disposerRecord.channel.position(offset);
 324                 while (bread < length) {
 325                     int cnt = disposerRecord.channel.read(buffer);
 326                     if (cnt == -1) {
 327                         String msg = "Unexpected EOF " + this;
 328                         int currSize = (int)disposerRecord.channel.size();
 329                         if (currSize != fileSize) {
 330                             msg += " File size was " + fileSize +
 331                                 " and now is " + currSize;
 332                         }
 333                         if (FontUtilities.isLogging()) {
 334                             FontUtilities.getLogger().severe(msg);
 335                         }
 336                         // We could still flip() the buffer here because
 337                         // it's possible that we did read some data in
 338                         // an earlier loop, and we probably should
 339                         // return that to the caller. Although if
 340                         // the caller expected 8K of data and we return
 341                         // only a few bytes then maybe it's better instead to
 342                         // set bread = -1 to indicate failure.
 343                         // The following is therefore using arbitrary values
 344                         // but is meant to allow cases where enough
 345                         // data was read to probably continue.
 346                         if (bread > length/2 || bread > 16384) {
 347                             buffer.flip();
 348                             if (FontUtilities.isLogging()) {
 349                                 msg = "Returning " + bread +
 350                                     " bytes instead of " + length;
 351                                 FontUtilities.getLogger().severe(msg);
 352                             }
 353                         } else {
 354                             bread = -1;
 355                         }
 356                         throw new IOException(msg);
 357                     }
 358                     bread += cnt;
 359                 }
 360                 buffer.flip();
 361                 if (bread > length) { // possible if buffer.size() > length
 362                     bread = length;
 363                 }
 364             }
 365         } catch (FontFormatException e) {
 366             if (FontUtilities.isLogging()) {
 367                 FontUtilities.getLogger().severe(
 368                                        "While reading " + platName, e);
 369             }
 370             bread = -1; // signal EOF
 371             deregisterFontAndClearStrikeCache();
 372         } catch (ClosedChannelException e) {
 373             /* NIO I/O is interruptible, recurse to retry operation.
 374              * Clear interrupts before recursing in case NIO didn't.
 375              */
 376             Thread.interrupted();
 377             close();
 378             return readBlock(buffer, offset, length);
 379         } catch (IOException e) {
 380             /* If we did not read any bytes at all and the exception is
 381              * not a recoverable one (ie is not ClosedChannelException) then
 382              * we should indicate that there is no point in re-trying.
 383              * Other than an attempt to read past the end of the file it
 384              * seems unlikely this would occur as problems opening the
 385              * file are handled as a FontFormatException.
 386              */
 387             if (FontUtilities.isLogging()) {
 388                 FontUtilities.getLogger().severe(
 389                                        "While reading " + platName, e);
 390             }
 391             if (bread == 0) {
 392                 bread = -1; // signal EOF
 393                 deregisterFontAndClearStrikeCache();
 394             }
 395         }
 396         return bread;
 397     }
 398 
 399     ByteBuffer readBlock(int offset, int length) {
 400 
 401         ByteBuffer buffer = ByteBuffer.allocate(length);
 402         try {
 403             synchronized (this) {
 404                 if (disposerRecord.channel == null) {
 405                     open();
 406                 }
 407                 if (offset + length > fileSize) {
 408                     if (offset > fileSize) {
 409                         return null; // assert?


 506                 table.offset = ibuffer.get();
 507                 table.length = ibuffer.get();
 508                 if (table.offset + table.length > fileSize) {
 509                     throw new FontFormatException("bad table, tag="+table.tag);
 510                 }
 511             }
 512 
 513             if (getDirectoryEntry(headTag) == null) {
 514                 throw new FontFormatException("missing head table");
 515             }
 516             if (getDirectoryEntry(maxpTag) == null) {
 517                 throw new FontFormatException("missing maxp table");
 518             }
 519             if (getDirectoryEntry(hmtxTag) != null
 520                     && getDirectoryEntry(hheaTag) == null) {
 521                 throw new FontFormatException("missing hhea table");
 522             }
 523             initNames();
 524         } catch (Exception e) {
 525             if (FontUtilities.isLogging()) {
 526                 FontUtilities.getLogger().severe(e.toString());
 527             }
 528             if (e instanceof FontFormatException) {
 529                 throw (FontFormatException)e;
 530             } else {
 531                 throw new FontFormatException(e.toString());
 532             }
 533         }
 534         if (familyName == null || fullName == null) {
 535             throw new FontFormatException("Font name not found");
 536         }
 537         /* The os2_Table is needed to gather some info, but we don't
 538          * want to keep it around (as a field) so obtain it once and
 539          * pass it to the code that needs it.
 540          */
 541         ByteBuffer os2_Table = getTableBuffer(os_2Tag);
 542         setStyle(os2_Table);
 543         setCJKSupport(os2_Table);
 544     }
 545 
 546     /* The array index corresponds to a bit offset in the TrueType


1056              }
1057          }
1058 
1059         String charset;
1060         switch (encoding) {
1061             case -1: charset = "US-ASCII";break;
1062             case 1:  charset = "UTF-16";  break; // most common case first.
1063             case 0:  charset = "UTF-16";  break; // symbol uses this
1064             case 2:  charset = "SJIS";    break;
1065             case 3:  charset = "GBK";     break;
1066             case 4:  charset = "MS950";   break;
1067             case 5:  charset = "EUC_KR";  break;
1068             case 6:  charset = "Johab";   break;
1069             default: charset = "UTF-16";  break;
1070         }
1071 
1072         try {
1073             return new String(bytes, 0, len, charset);
1074         } catch (UnsupportedEncodingException e) {
1075             if (FontUtilities.isLogging()) {
1076                 FontUtilities.getLogger().warning(e + " EncodingID=" + encoding);
1077             }
1078             return new String(bytes, 0, len);
1079         } catch (Throwable t) {
1080             return null;
1081         }
1082     }
1083 
1084     protected void initNames() {
1085 
1086         byte[] name = new byte[256];
1087         ByteBuffer buffer = getTableBuffer(nameTag);
1088 
1089         if (buffer != null) {
1090             ShortBuffer sbuffer = buffer.asShortBuffer();
1091             sbuffer.get(); // format - not needed.
1092             short numRecords = sbuffer.get();
1093             /* The name table uses unsigned shorts. Many of these
1094              * are known small values that fit in a short.
1095              * The values that are sizes or offsets into the table could be
1096              * greater than 32767, so read and store those as ints




 227             }
 228         }
 229         Disposer.addObjectRecord(this, disposerRecord);
 230     }
 231 
 232     private synchronized FileChannel open() throws FontFormatException {
 233         return open(true);
 234     }
 235 
 236     /* This is intended to be called, and the returned value used,
 237      * from within a block synchronized on this font object.
 238      * ie the channel returned may be nulled out at any time by "close()"
 239      * unless the caller holds a lock.
 240      * Deadlock warning: FontManager.addToPool(..) acquires a global lock,
 241      * which means nested locks may be in effect.
 242      */
 243     private synchronized FileChannel open(boolean usePool)
 244                                      throws FontFormatException {
 245         if (disposerRecord.channel == null) {
 246             if (FontUtilities.isLogging()) {
 247                 FontUtilities.logInfo("open TTF: " + platName);
 248             }
 249             try {
 250                 RandomAccessFile raf = AccessController.doPrivileged(
 251                     new PrivilegedExceptionAction<RandomAccessFile>() {
 252                         public RandomAccessFile run() throws FileNotFoundException {
 253                             return new RandomAccessFile(platName, "r");
 254                     }
 255                 });
 256                 disposerRecord.channel = raf.getChannel();
 257                 fileSize = (int)disposerRecord.channel.size();
 258                 if (usePool) {
 259                     FontManager fm = FontManagerFactory.getInstance();
 260                     if (fm instanceof SunFontManager) {
 261                         ((SunFontManager) fm).addToPool(this);
 262                     }
 263                 }
 264             } catch (PrivilegedActionException e) {
 265                 close();
 266                 Throwable reason = e.getCause();
 267                 if (reason == null) {


 295         try {
 296             synchronized (this) {
 297                 if (disposerRecord.channel == null) {
 298                     open();
 299                 }
 300                 if (offset + length > fileSize) {
 301                     if (offset >= fileSize) {
 302                         /* Since the caller ensures that offset is < fileSize
 303                          * this condition suggests that fileSize is now
 304                          * different than the value we originally provided
 305                          * to native when the scaler was created.
 306                          * Also fileSize is updated every time we
 307                          * open() the file here, but in native the value
 308                          * isn't updated. If the file has changed whilst we
 309                          * are executing we want to bail, not spin.
 310                          */
 311                         if (FontUtilities.isLogging()) {
 312                             String msg = "Read offset is " + offset +
 313                                     " file size is " + fileSize+
 314                                     " file is " + platName;
 315                             FontUtilities.logSevere(msg);
 316                         }
 317                         return -1;
 318                     } else {
 319                         length = fileSize - offset;
 320                     }
 321                 }
 322                 buffer.clear();
 323                 disposerRecord.channel.position(offset);
 324                 while (bread < length) {
 325                     int cnt = disposerRecord.channel.read(buffer);
 326                     if (cnt == -1) {
 327                         String msg = "Unexpected EOF " + this;
 328                         int currSize = (int)disposerRecord.channel.size();
 329                         if (currSize != fileSize) {
 330                             msg += " File size was " + fileSize +
 331                                 " and now is " + currSize;
 332                         }
 333                         if (FontUtilities.isLogging()) {
 334                             FontUtilities.logSevere(msg);
 335                         }
 336                         // We could still flip() the buffer here because
 337                         // it's possible that we did read some data in
 338                         // an earlier loop, and we probably should
 339                         // return that to the caller. Although if
 340                         // the caller expected 8K of data and we return
 341                         // only a few bytes then maybe it's better instead to
 342                         // set bread = -1 to indicate failure.
 343                         // The following is therefore using arbitrary values
 344                         // but is meant to allow cases where enough
 345                         // data was read to probably continue.
 346                         if (bread > length/2 || bread > 16384) {
 347                             buffer.flip();
 348                             if (FontUtilities.isLogging()) {
 349                                 msg = "Returning " + bread + " bytes instead of " + length;
 350                                 FontUtilities.logSevere(msg);

 351                             }
 352                         } else {
 353                             bread = -1;
 354                         }
 355                         throw new IOException(msg);
 356                     }
 357                     bread += cnt;
 358                 }
 359                 buffer.flip();
 360                 if (bread > length) { // possible if buffer.size() > length
 361                     bread = length;
 362                 }
 363             }
 364         } catch (FontFormatException e) {
 365             if (FontUtilities.isLogging()) {
 366                 FontUtilities.getLogger().severe("While reading " + platName, e);

 367             }
 368             bread = -1; // signal EOF
 369             deregisterFontAndClearStrikeCache();
 370         } catch (ClosedChannelException e) {
 371             /* NIO I/O is interruptible, recurse to retry operation.
 372              * Clear interrupts before recursing in case NIO didn't.
 373              */
 374             Thread.interrupted();
 375             close();
 376             return readBlock(buffer, offset, length);
 377         } catch (IOException e) {
 378             /* If we did not read any bytes at all and the exception is
 379              * not a recoverable one (ie is not ClosedChannelException) then
 380              * we should indicate that there is no point in re-trying.
 381              * Other than an attempt to read past the end of the file it
 382              * seems unlikely this would occur as problems opening the
 383              * file are handled as a FontFormatException.
 384              */
 385             if (FontUtilities.isLogging()) {
 386                 FontUtilities.getLogger().severe("While reading " + platName, e);

 387             }
 388             if (bread == 0) {
 389                 bread = -1; // signal EOF
 390                 deregisterFontAndClearStrikeCache();
 391             }
 392         }
 393         return bread;
 394     }
 395 
 396     ByteBuffer readBlock(int offset, int length) {
 397 
 398         ByteBuffer buffer = ByteBuffer.allocate(length);
 399         try {
 400             synchronized (this) {
 401                 if (disposerRecord.channel == null) {
 402                     open();
 403                 }
 404                 if (offset + length > fileSize) {
 405                     if (offset > fileSize) {
 406                         return null; // assert?


 503                 table.offset = ibuffer.get();
 504                 table.length = ibuffer.get();
 505                 if (table.offset + table.length > fileSize) {
 506                     throw new FontFormatException("bad table, tag="+table.tag);
 507                 }
 508             }
 509 
 510             if (getDirectoryEntry(headTag) == null) {
 511                 throw new FontFormatException("missing head table");
 512             }
 513             if (getDirectoryEntry(maxpTag) == null) {
 514                 throw new FontFormatException("missing maxp table");
 515             }
 516             if (getDirectoryEntry(hmtxTag) != null
 517                     && getDirectoryEntry(hheaTag) == null) {
 518                 throw new FontFormatException("missing hhea table");
 519             }
 520             initNames();
 521         } catch (Exception e) {
 522             if (FontUtilities.isLogging()) {
 523                 FontUtilities.logSevere(e.toString());
 524             }
 525             if (e instanceof FontFormatException) {
 526                 throw (FontFormatException)e;
 527             } else {
 528                 throw new FontFormatException(e.toString());
 529             }
 530         }
 531         if (familyName == null || fullName == null) {
 532             throw new FontFormatException("Font name not found");
 533         }
 534         /* The os2_Table is needed to gather some info, but we don't
 535          * want to keep it around (as a field) so obtain it once and
 536          * pass it to the code that needs it.
 537          */
 538         ByteBuffer os2_Table = getTableBuffer(os_2Tag);
 539         setStyle(os2_Table);
 540         setCJKSupport(os2_Table);
 541     }
 542 
 543     /* The array index corresponds to a bit offset in the TrueType


1053              }
1054          }
1055 
1056         String charset;
1057         switch (encoding) {
1058             case -1: charset = "US-ASCII";break;
1059             case 1:  charset = "UTF-16";  break; // most common case first.
1060             case 0:  charset = "UTF-16";  break; // symbol uses this
1061             case 2:  charset = "SJIS";    break;
1062             case 3:  charset = "GBK";     break;
1063             case 4:  charset = "MS950";   break;
1064             case 5:  charset = "EUC_KR";  break;
1065             case 6:  charset = "Johab";   break;
1066             default: charset = "UTF-16";  break;
1067         }
1068 
1069         try {
1070             return new String(bytes, 0, len, charset);
1071         } catch (UnsupportedEncodingException e) {
1072             if (FontUtilities.isLogging()) {
1073                 FontUtilities.logWarning(e + " EncodingID=" + encoding);
1074             }
1075             return new String(bytes, 0, len);
1076         } catch (Throwable t) {
1077             return null;
1078         }
1079     }
1080 
1081     protected void initNames() {
1082 
1083         byte[] name = new byte[256];
1084         ByteBuffer buffer = getTableBuffer(nameTag);
1085 
1086         if (buffer != null) {
1087             ShortBuffer sbuffer = buffer.asShortBuffer();
1088             sbuffer.get(); // format - not needed.
1089             short numRecords = sbuffer.get();
1090             /* The name table uses unsigned shorts. Many of these
1091              * are known small values that fit in a short.
1092              * The values that are sizes or offsets into the table could be
1093              * greater than 32767, so read and store those as ints


< prev index next >