Added methods to SkTypeface to read the actual name of the typeface family and to retrieve ttf tables

This commit is contained in:
adrian gallero 2016-05-01 03:02:27 -03:00
Родитель 638668b4c9
Коммит 50e3914721
7 изменённых файлов: 210 добавлений и 18 удалений

Просмотреть файл

@ -7,6 +7,7 @@
// Copyright 2016 Xamarin Inc
//
using System;
using System.Runtime.InteropServices;
namespace SkiaSharp
{
@ -16,6 +17,7 @@ namespace SkiaSharp
internal SKTypeface (IntPtr handle)
: base (handle)
{
if (handle == IntPtr.Zero) throw new Exception("Invalid typeface");
}
protected override void Dispose (bool disposing)
@ -108,6 +110,46 @@ namespace SkiaSharp
}
}
}
}
public string FamilyName {
get {
var r = SkiaApi.sk_string_new_empty();
try {
SkiaApi.sk_typeface_get_family_name(Handle, r);
var cstr = SkiaApi.sk_string_get_c_str(r);
var clen = SkiaApi.sk_string_get_size(r);
return Util.GetString(cstr, (int)clen, SKTextEncoding.Utf8);
} finally {
SkiaApi.sk_string_destructor(r);
}
}
}
public UInt32[] GetTableTags()
{
int tableCount = SkiaApi.sk_typeface_count_tables(Handle);
UInt32[] result = new UInt32[tableCount];
int r = SkiaApi.sk_typeface_get_table_tags(Handle, result);
if (r == 0) {
throw new Exception("Unable to read the tables for the file.");
}
return result;
}
public byte[] GetTableData(UInt32 tag)
{
IntPtr dataSize = SkiaApi.sk_typeface_get_table_size(Handle, tag);
byte[] result = new byte[(int)dataSize];
IntPtr r = SkiaApi.sk_typeface_get_table_data(Handle, tag, IntPtr.Zero, dataSize, result);
if (r == IntPtr.Zero)
{
throw new Exception("Unable to read the data table.");
}
return result;
}
}
}

Просмотреть файл

@ -18,8 +18,10 @@ using sk_maskfilter_t = System.IntPtr;
using sk_path_t = System.IntPtr;
using sk_picture_t = System.IntPtr;
using sk_data_t = System.IntPtr;
using sk_string_t = System.IntPtr;
using sk_picture_recorder_t = System.IntPtr;
using sk_typeface_t = System.IntPtr;
using sk_font_table_tag_t = System.UInt32;
using sk_stream_t = System.IntPtr;
using sk_stream_filestream_t = System.IntPtr;
using sk_stream_memorystream_t = System.IntPtr;
@ -458,6 +460,18 @@ namespace SkiaSharp
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_data_get_data(sk_data_t d);
// SkString
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_string_t sk_string_new_empty();
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_string_t sk_string_new_with_copy(byte[] src, IntPtr length);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_string_destructor(sk_string_t skstring);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_string_get_size(sk_string_t skstring);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_string_get_c_str(sk_string_t skstring);
// SkPicture
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_picture_recorder_delete(sk_picture_recorder_t r);
@ -540,9 +554,19 @@ namespace SkiaSharp
public extern static void sk_typeface_unref(sk_typeface_t t);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static int sk_typeface_chars_to_glyphs(sk_typeface_t t, IntPtr chars, SKEncoding encoding, IntPtr glyphPtr, int glyphCount);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static int sk_typeface_get_family_name(sk_typeface_t typeface, sk_string_t familyName);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static int sk_typeface_count_tables(sk_typeface_t typeface);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static int sk_typeface_get_table_tags(sk_typeface_t typeface, sk_font_table_tag_t[] tags);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_typeface_get_table_size(sk_typeface_t typeface, sk_font_table_tag_t tag);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_typeface_get_table_data(sk_typeface_t typeface, sk_font_table_tag_t tag, IntPtr offset, IntPtr length, byte[] data);
// Streams
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
// Streams
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_stream_read(sk_stream_t stream, IntPtr buffer, IntPtr size);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static IntPtr sk_stream_skip(sk_stream_t stream, IntPtr size);

Просмотреть файл

@ -1,25 +1,43 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace SkiaSharp
{
static class Util
{
public static byte[] GetEncodedText(string text, SKTextEncoding encoding)
{
switch (encoding)
{
case SKTextEncoding.Utf8:
return Encoding.UTF8.GetBytes(text);
case SKTextEncoding.Utf16:
return Encoding.Unicode.GetBytes(text);
case SKTextEncoding.Utf32:
return Encoding.UTF32.GetBytes(text);
default:
throw new ArgumentException($"Encoding {encoding} is not supported");
}
}
public static byte[] GetEncodedText(string text, SKTextEncoding encoding)
{
switch (encoding)
{
case SKTextEncoding.Utf8:
return Encoding.UTF8.GetBytes(text);
case SKTextEncoding.Utf16:
return Encoding.Unicode.GetBytes(text);
case SKTextEncoding.Utf32:
return Encoding.UTF32.GetBytes(text);
default:
throw new ArgumentException($"Encoding {encoding} is not supported");
}
}
public static string GetString(IntPtr data, int dataLength, SKTextEncoding encoding)
{
if (data == IntPtr.Zero || dataLength <= 0) return "";
byte[] result = new byte[dataLength];
Marshal.Copy(data, result, 0, dataLength);
switch (encoding)
{
case SKTextEncoding.Utf8:
return Encoding.UTF8.GetString(result);
case SKTextEncoding.Utf16:
return Encoding.Unicode.GetString(result);
case SKTextEncoding.Utf32:
return Encoding.UTF32.GetString(result);
default:
throw new ArgumentException($"Encoding {encoding} is not supported");
}
}
}
}

Просмотреть файл

@ -33,6 +33,7 @@
#include "xamarin/sk_x_shader.h"
#include "xamarin/sk_x_stream.h"
#include "xamarin/sk_x_typeface.h"
#include "xamarin/sk_x_string.h"
// Xamarin
#include "sk_managedstream.h"
@ -70,6 +71,7 @@ void** KeepSkiaCSymbols ()
(void*)sk_memorystream_new,
(void*)sk_stream_read,
(void*)sk_typeface_create_from_name,
(void*)sk_string_new_empty,
// Xamarin
(void*)sk_managedstream_new,

2
skia

@ -1 +1 @@
Subproject commit 44f28d5b1c12e311735ba1283bbe28cff351ebbc
Subproject commit 653e2a73b7da23613696aac3b0c7b49c7c759457

Просмотреть файл

@ -90,6 +90,9 @@
</Compile>
<Compile Include="..\Tests\SKTest.cs">
<Link>SKTest.cs</Link>
</Compile>
<Compile Include="..\Tests\SKTypefaceTest.cs" >
<Link>SKTypefaceTest.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -0,0 +1,103 @@
using System;
using NUnit.Framework;
using System.IO;
namespace SkiaSharp.Tests
{
[TestFixture]
public class SKTypefaceTest
{
const string PathToFonts = @"../../../../../skia/resources/fonts";
static readonly string[] ExpectedTablesSpiderFont = new string[] {
"FFTM", "GDEF", "OS/2", "cmap", "cvt ", "gasp", "glyf", "head",
"hhea", "hmtx", "loca", "maxp", "name", "post",
};
static readonly int[] ExpectedTableLengthsReallyBigAFont = new int[] {
28, 30, 96, 330, 4, 8, 236, 54, 36, 20, 12, 32, 13665, 44,
};
static readonly byte[] ExpectedTableDataPostReallyBigAFont = new byte[] {
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF1, 0x00, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x24, 0x00, 0x44,
};
[Test]
public void ExceptionInWrongFileName()
{
Assert.Throws<Exception>(() => SKTypeface.FromFile(Path.Combine(PathToFonts, "font that doesn't exist.ttf")));
}
[Test]
public void TestFamilyName()
{
using (var typeface = SKTypeface.FromFile(Path.Combine(PathToFonts, "Roboto2-Regular_NoEmbed.ttf")))
{
Assert.AreEqual("Roboto2", typeface.FamilyName, "Family name must be Roboto2.");
}
}
private static string GetReadableTag(uint v)
{
return
((char)((v >> 24) & 0xFF)).ToString() +
((char)((v >> 16) & 0xFF)).ToString() +
((char)((v >> 08) & 0xFF)).ToString() +
((char)((v >> 00) & 0xFF)).ToString();
}
private static uint GetIntTag(string v)
{
return
(UInt32)(v[0]) << 24 |
(UInt32)(v[1]) << 16 |
(UInt32)(v[2]) << 08 |
(UInt32)(v[3]) << 00;
}
[Test]
public void TestGetTableTags()
{
using (var typeface = SKTypeface.FromFile(Path.Combine(PathToFonts, "SpiderSymbol.ttf")))
{
Assert.AreEqual("SpiderSymbol", typeface.FamilyName, "Family name must be SpiderSymbol");
var tables = typeface.GetTableTags();
Assert.AreEqual(ExpectedTablesSpiderFont.Length, tables.Length, "The font doesn't have the expected number of tables.");
for (int i = 0; i < tables.Length; i++) {
Assert.AreEqual(ExpectedTablesSpiderFont[i], GetReadableTag(tables[i]), "Unexpected Font tag.");
}
}
}
[Test]
public void TestGetTableData()
{
using (var typeface = SKTypeface.FromFile(Path.Combine(PathToFonts, "ReallyBigA.ttf")))
{
Assert.AreEqual("ReallyBigA", typeface.FamilyName, "Family name must be ReallyBigA");
var tables = typeface.GetTableTags();
for (int i = 0; i < tables.Length; i++) {
byte[] tableData = typeface.GetTableData(tables[i]);
Assert.AreEqual(ExpectedTableLengthsReallyBigAFont[i], tableData.Length, "Unexpected length for table: " + GetReadableTag(tables[i]));
}
Assert.AreEqual(ExpectedTableDataPostReallyBigAFont, typeface.GetTableData(GetIntTag("post")));
}
}
[Test]
public void ExceptionInInvalidGetTableData()
{
using (var typeface = SKTypeface.FromFile(Path.Combine(PathToFonts, "Distortable.ttf")))
{
Assert.Throws<System.Exception>(() => typeface.GetTableData(8));
}
}
}
}