summaryrefslogtreecommitdiff
path: root/graphics/java/android
diff options
context:
space:
mode:
author Seigo Nonaka <nona@google.com> 2018-07-18 15:53:48 -0700
committer Seigo Nonaka <nona@google.com> 2018-07-19 10:37:33 -0700
commitfc09c9ee91a0418099a92d5565ff6a4d4abe7ec2 (patch)
treebec7ecdc6083932a520bad81488985a38723e52a /graphics/java/android
parentedf3e1fa2effc158d3be00a6e75fc06a6925362b (diff)
Introduce FontFileUtil
FontFileUtil provides style analysis of font file. This CL also introduce a basic test functionality of font families. Test: atest android.graphics.FontFileUtilTest Bug: 72665240 Change-Id: I967d56eb37ee0e4c6d59f59c301a4a6f009fad2d
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/graphics/fonts/FontFileUtil.java127
1 files changed, 127 insertions, 0 deletions
diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java
new file mode 100644
index 000000000000..d15f581f918c
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontFileUtil.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.fonts;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Provides a utility for font file operations.
+ * @hide
+ */
+public class FontFileUtil {
+
+ private FontFileUtil() {} // Do not instanciate
+
+ /**
+ * Unpack the weight value from packed integer.
+ */
+ public static int unpackWeight(int packed) {
+ return packed & 0xFFFF;
+ }
+
+ /**
+ * Unpack the italic value from packed integer.
+ */
+ public static boolean unpackItalic(int packed) {
+ return (packed & 0x10000) != 0;
+ }
+
+ private static int pack(@IntRange(from = 0, to = 1000) int weight, boolean italic) {
+ return weight | (italic ? 0x10000 : 0);
+ }
+
+ private static final int SFNT_VERSION_1 = 0x00010000;
+ private static final int SFNT_VERSION_OTTO = 0x4F54544F;
+ private static final int TTC_TAG = 0x74746366;
+ private static final int OS2_TABLE_TAG = 0x4F532F32;
+
+ /**
+ * Analyze the font file returns packed style info
+ */
+ public static final int analyzeStyle(@NonNull ByteBuffer buffer,
+ @IntRange(from = 0) int ttcIndex, @Nullable FontVariationAxis[] varSettings)
+ throws IOException {
+ int weight = -1;
+ int italic = -1;
+ if (varSettings != null) {
+ for (FontVariationAxis axis :varSettings) {
+ if ("wght".equals(axis.getTag())) {
+ weight = (int) axis.getStyleValue();
+ } else if ("ital".equals(axis.getTag())) {
+ italic = (axis.getStyleValue() == 1.0f) ? 1 : 0;
+ }
+ }
+ }
+
+ if (weight != -1 && italic != -1) {
+ // Both weight/italic style are specifeid by variation settings.
+ // No need to look into OS/2 table.
+ // TODO: Good to look HVAR table to check if this font supports wght/ital axes.
+ return pack(weight, italic == 1);
+ }
+
+ ByteOrder originalOrder = buffer.order();
+ buffer.order(ByteOrder.BIG_ENDIAN);
+ try {
+ int fontFileOffset = 0;
+ int magicNumber = buffer.getInt(0);
+ if (magicNumber == TTC_TAG) {
+ // TTC file.
+ if (ttcIndex >= buffer.getInt(8 /* offset to number of fonts in TTC */)) {
+ throw new IOException("Font index out of bounds");
+ }
+ fontFileOffset = buffer.getInt(
+ 12 /* offset to array of offsets of font files */ + 4 * ttcIndex);
+ }
+ int sfntVersion = buffer.getInt(fontFileOffset);
+
+ if (sfntVersion != SFNT_VERSION_1 && sfntVersion != SFNT_VERSION_OTTO) {
+ throw new IOException("Unknown font file format");
+ }
+
+ int numTables = buffer.getShort(fontFileOffset + 4 /* offset to number of tables */);
+ int os2TableOffset = -1;
+ for (int i = 0; i < numTables; ++i) {
+ int tableOffset = fontFileOffset + 12 /* size of offset table */
+ + i * 16 /* size of table record */;
+ if (buffer.getInt(tableOffset) == OS2_TABLE_TAG) {
+ os2TableOffset = buffer.getInt(tableOffset + 8 /* offset to the table */);
+ break;
+ }
+ }
+
+ if (os2TableOffset == -1) {
+ // Couldn't find OS/2 table. use regular style
+ return pack(400, false);
+ }
+
+ int weightFromOS2 = buffer.getShort(os2TableOffset + 4 /* offset to weight class */);
+ boolean italicFromOS2 =
+ (buffer.getShort(os2TableOffset + 62 /* offset to fsSelection */) & 1) != 0;
+ return pack(weight == -1 ? weightFromOS2 : weight,
+ italic == -1 ? italicFromOS2 : italic == 1);
+ } finally {
+ buffer.order(originalOrder);
+ }
+ }
+}