mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-12 18:39:45 +00:00
237 lines
10 KiB
C#
237 lines
10 KiB
C#
//MIT, 2020-present, WinterDev
|
|
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace Typography.OpenFont.Tables
|
|
{
|
|
//https://docs.microsoft.com/en-us/typography/opentype/spec/meta
|
|
//meta — Metadata Table
|
|
|
|
|
|
//NOTE: readmore about language tag, https://tools.ietf.org/html/bcp47
|
|
//...The language of an information item or a user's language preferences
|
|
//often need to be identified so that appropriate processing can be
|
|
//applied.
|
|
//...
|
|
//...
|
|
//One means of indicating the language used is by labeling the
|
|
//information content with an identifier or "tag". These tags can also
|
|
//be used to specify the user's preferences when selecting information
|
|
//content or to label additional attributes of content and associated
|
|
//resources.
|
|
|
|
//..
|
|
//..The Language Tag
|
|
//..
|
|
|
|
//Language tags are used to help identify languages, whether spoken,
|
|
//written, signed, or otherwise signaled, for the purpose of
|
|
//communication.This includes constructed and artificial languages
|
|
//but excludes languages not intended primarily for human
|
|
//communication, such as programming languages.
|
|
|
|
|
|
|
|
|
|
|
|
class Meta : TableEntry
|
|
{
|
|
//The metadata table contains various metadata values for the font.
|
|
//Different categories of metadata are identified by four-character tags.
|
|
//Values for different categories can be either binary or text.
|
|
|
|
public const string _N = "meta";
|
|
public override string Name => _N;
|
|
public Meta() { }
|
|
/// <summary>
|
|
/// dlng tags
|
|
/// </summary>
|
|
public string[] DesignLanguageTags { get; private set; }
|
|
/// <summary>
|
|
/// slng tags
|
|
/// </summary>
|
|
public string[] SupportedLanguageTags { get; private set; }
|
|
protected override void ReadContentFrom(BinaryReader reader)
|
|
{
|
|
//found in some fonts (eg tahoma)
|
|
|
|
//Table Formats
|
|
//The metadata table begins with a header, structured as follows.
|
|
|
|
//Metadata header:
|
|
//Type Name Description
|
|
//uint32 version Version number of the metadata table — set to 1.
|
|
//uint32 flags Flags — currently unused; set to 0.
|
|
//uint32 (reserved) Not used; should be set to 0.
|
|
//uint32 dataMapsCount The number of data maps in the table.
|
|
//DataMap dataMaps[dataMapsCount] Array of data map records.
|
|
|
|
|
|
long tableStartsAt = reader.BaseStream.Position;//***
|
|
|
|
uint version = reader.ReadUInt32();
|
|
uint flags = reader.ReadUInt32();
|
|
uint reserved = reader.ReadUInt32();
|
|
uint dataMapsCount = reader.ReadUInt32();
|
|
#if DEBUG
|
|
if (version != 1 || flags != 0)
|
|
{
|
|
throw new OpenFontNotSupportedException();
|
|
}
|
|
#endif
|
|
|
|
DataMapRecord[] dataMaps = new DataMapRecord[dataMapsCount];
|
|
for (int i = 0; i < dataMaps.Length; ++i)
|
|
{
|
|
dataMaps[i] = new DataMapRecord(reader.ReadUInt32(),
|
|
reader.ReadUInt32(),
|
|
reader.ReadUInt32());
|
|
}
|
|
|
|
//Metadata tags identify the category of information provided and representation format used for a given metadata value.
|
|
//A registry of commonly - used tags is maintained,
|
|
//but private, vendor-determined tags can also be used.
|
|
|
|
//Like other OpenType tags,
|
|
//metadata tags are four unsigned bytes that can equivalently be interpreted as a string of four ASCII characters.
|
|
//Metadata tags must begin with a letter (0x41 to 0x5A, 0x61 to 0x7A) and
|
|
//must use only letters, digits (0x30 to 0x39) or space (0x20).
|
|
//Space characters must only occur as trailing characters in tags that have fewer than four letters or digits.
|
|
|
|
//Privately - defined axis tags must begin with an uppercase letter(0x41 to 0x5A),
|
|
//and must use only uppercase letters or digits.
|
|
//Registered axis tags must not use that pattern, but can be any other valid pattern.
|
|
|
|
//The data for a given record may be either textual or binary.
|
|
//The representation format is specified for each tag.
|
|
//Depending on the tag, multiple records for a given tag or multiple,
|
|
//delimited values in a record may or may not be permitted, as specified for each tag.
|
|
//If only one record or value is permitted for a tag,
|
|
//then any instances after the first may be ignored.
|
|
|
|
//translate data for each tags
|
|
//The following registered tags are defined or reserved at this time:
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------------
|
|
//IMPORTANT:
|
|
//Note: OpenType Layout script and language system tags are not the same as
|
|
//those used in BCP 47 and should not be referenced when creating or processing ScriptLangTags.
|
|
//------------------------------------------------------------------------------------
|
|
//... In most cases, however, generic tags should be used,
|
|
//and it is anticipated that most tags used in 'dlng' and 'slng' metadata declarations will consist only of a script subtag.
|
|
//Language or other subtags can be included, however, and may be appropriate in some cases.
|
|
//Implementations must allow for ScriptLangTags that include additional subtags,
|
|
//but they may also choose to interpret only the script subtag and ignore other subtags.
|
|
|
|
|
|
for (int i = 0; i < dataMaps.Length; ++i)
|
|
{
|
|
DataMapRecord record = dataMaps[i];
|
|
|
|
switch (record.GetTagString())
|
|
{
|
|
#if DEBUG
|
|
default:
|
|
System.Diagnostics.Debug.WriteLine("openfont-meta: unknown tag:" + record.GetTagString());
|
|
break;
|
|
#endif
|
|
case "apple": //Reserved — used by Apple.
|
|
case "bild"://Reserved — used by Apple.
|
|
break;
|
|
case "dlng":
|
|
{
|
|
//The values for 'dlng' and 'slng' are comprised of a series of comma-separated ScriptLangTags,
|
|
//which are described in detail below.
|
|
//Spaces may follow the comma delimiters and are ignored.
|
|
//Each ScriptLangTag identifies a language or script.
|
|
|
|
//A list of tags is interpreted to imply that all of the languages or scripts are included.
|
|
|
|
//dlng Design languages Text,
|
|
//using only Basic Latin (ASCII) characters.
|
|
//Indicates languages and/or scripts for the user audiences that the font was primarily designed for.
|
|
|
|
//Only one instance is used.
|
|
|
|
//dlng Design languages Text,
|
|
//The 'dlng' value is used to indicate the languages or scripts of the primary user audiences for which the font was designed.
|
|
|
|
//This value may be useful for selecting default font formatting based on content language,
|
|
//for presenting filtered font options based on user language preferences,
|
|
//or similar applications involving the language or script of content or user settings.
|
|
|
|
if (DesignLanguageTags == null)
|
|
{
|
|
//Only one instance is used.
|
|
reader.BaseStream.Position = tableStartsAt + record.dataOffset;
|
|
DesignLanguageTags = ReadCommaSepData(reader.ReadBytes((int)record.dataLength));
|
|
}
|
|
}
|
|
break;
|
|
case "slng":
|
|
{
|
|
//slng Supported languages Text, using only Basic Latin(ASCII) characters.
|
|
//Indicates languages and / or scripts that the font is declared to be capable of supporting.
|
|
|
|
//Only one instance is used.
|
|
|
|
//slng Supported languages Text
|
|
//The 'slng' value is used to declare languages or scripts that the font is capable of supported.
|
|
|
|
//This value may be useful for font fallback mechanisms or other applications involving the language or
|
|
//script of content or user settings.
|
|
//Note: Implementations that use 'slng' values in a font may choose to ignore Unicode - range bits set in the OS/ 2 table.
|
|
|
|
if (SupportedLanguageTags == null)
|
|
{ //Only one instance is used.
|
|
reader.BaseStream.Position = tableStartsAt + record.dataOffset;
|
|
SupportedLanguageTags = ReadCommaSepData(reader.ReadBytes((int)record.dataLength));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
static string[] ReadCommaSepData(byte[] data)
|
|
{
|
|
string[] tags = System.Text.Encoding.UTF8.GetString(data).Split(',');
|
|
for (int i = 0; i < tags.Length; ++i)
|
|
{
|
|
tags[i] = tags[i].Trim();
|
|
|
|
#if DEBUG
|
|
if (tags[i].Contains("-"))
|
|
{
|
|
|
|
}
|
|
#endif
|
|
|
|
}
|
|
return tags;
|
|
}
|
|
readonly struct DataMapRecord
|
|
{
|
|
public readonly uint tag;
|
|
public readonly uint dataOffset;
|
|
public readonly uint dataLength;
|
|
public DataMapRecord(uint tag, uint dataOffset, uint dataLength)
|
|
{
|
|
this.tag = tag;
|
|
this.dataOffset = dataOffset;
|
|
this.dataLength = dataLength;
|
|
}
|
|
public string GetTagString() => Utils.TagToString(tag);
|
|
#if DEBUG
|
|
public override string ToString()
|
|
{
|
|
return GetTagString() + ":" + dataOffset + "," + dataLength;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
} |