blob: 1ed3972ed309e5671516f38e0dd08bb354d60e9a [file] [log] [blame]
/*
* Copyright (C) 2021 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 com.android.server.graphics.fonts;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontFileUtil;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.DirectByteBuffer;
import java.nio.NioUtils;
import java.nio.channels.FileChannel;
/* package */ class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
@Override
public String getPostScriptName(File file) throws IOException {
ByteBuffer buffer = mmap(file);
try {
return FontFileUtil.getPostScriptName(buffer, 0);
} finally {
unmap(buffer);
}
}
@Override
public String buildFontFileName(File file) throws IOException {
ByteBuffer buffer = mmap(file);
try {
String psName = FontFileUtil.getPostScriptName(buffer, 0);
int isType1Font = FontFileUtil.isPostScriptType1Font(buffer, 0);
int isCollection = FontFileUtil.isCollectionFont(buffer);
if (TextUtils.isEmpty(psName) || isType1Font == -1 || isCollection == -1) {
return null;
}
String extension;
if (isCollection == 1) {
extension = isType1Font == 1 ? ".otc" : ".ttc";
} else {
extension = isType1Font == 1 ? ".otf" : ".ttf";
}
return psName + extension;
} finally {
unmap(buffer);
}
}
@Override
public long getRevision(File file) throws IOException {
ByteBuffer buffer = mmap(file);
try {
return FontFileUtil.getRevision(buffer, 0);
} finally {
unmap(buffer);
}
}
@Override
public void tryToCreateTypeface(File file) throws Throwable {
ByteBuffer buffer = mmap(file);
try {
Font font = new Font.Builder(buffer).build();
FontFamily family = new FontFamily.Builder(font).build();
Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
TextPaint p = new TextPaint();
p.setTextSize(24f);
p.setTypeface(typeface);
// Test string to try with the passed font.
// TODO: Good to extract from font file.
String testTextToDraw = "abcXYZ@- "
+ "\uD83E\uDED6" // Emoji E13.0
+ "\uD83C\uDDFA\uD83C\uDDF8" // Emoji Flags
+ "\uD83D\uDC8F\uD83C\uDFFB" // Emoji Skin tone Sequence
// ZWJ Sequence
+ "\uD83D\uDC68\uD83C\uDFFC\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D"
+ "\uD83D\uDC68\uD83C\uDFFF";
int width = (int) Math.ceil(Layout.getDesiredWidth(testTextToDraw, p));
StaticLayout layout = StaticLayout.Builder.obtain(
testTextToDraw, 0, testTextToDraw.length(), p, width).build();
Bitmap bmp = Bitmap.createBitmap(
layout.getWidth(), layout.getHeight(), Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(bmp);
layout.draw(canvas);
} finally {
unmap(buffer);
}
}
private static ByteBuffer mmap(File file) throws IOException {
try (FileInputStream in = new FileInputStream(file)) {
FileChannel fileChannel = in.getChannel();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
}
}
private static void unmap(ByteBuffer buffer) {
if (buffer instanceof DirectByteBuffer) {
NioUtils.freeDirectBuffer(buffer);
}
}
}