Add support for kEmbeddedBitmapText_Flag to DirectWrite.

R=reed@google.com

Review URL: https://codereview.chromium.org/263503004

git-svn-id: http://skia.googlecode.com/svn/trunk@14518 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2014-05-01 20:39:14 +00:00
Родитель 1d146d431a
Коммит 058670b1e5
4 изменённых файлов: 547 добавлений и 64 удалений

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

@ -22,7 +22,10 @@
#include "SkGlyph.h"
#include "SkHRESULT.h"
#include "SkMaskGamma.h"
#include "SkMatrix22.h"
#include "SkOnce.h"
#include "SkOTTable_EBLC.h"
#include "SkOTTable_EBSC.h"
#include "SkOTTable_head.h"
#include "SkOTTable_hhea.h"
#include "SkOTTable_OS_2.h"
@ -449,7 +452,22 @@ private:
const void* drawDWMask(const SkGlyph& glyph);
SkTDArray<uint8_t> fBits;
/** The total matrix without the text height scale. */
SkMatrix fSkXform;
/** The total matrix without the text height scale. */
DWRITE_MATRIX fXform;
/** The non-rotational part of total matrix without the text height scale.
* This is used to find the magnitude of gdi compatible advances.
*/
DWRITE_MATRIX fGsA;
/** The inverse of the rotational part of the total matrix.
* This is used to find the direction of gdi compatible advances.
*/
SkMatrix fG_inv;
/** The text size to render with. */
SkScalar fTextSizeRender;
/** The text size to measure with. */
SkScalar fTextSizeMeasure;
SkAutoTUnref<DWriteFontTypeface> fTypeface;
int fGlyphCount;
DWRITE_RENDERING_MODE fRenderingMode;
@ -570,32 +588,224 @@ static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle,
wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
}
class AutoDWriteTable {
public:
AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
// Any errors are ignored, user must check fExists anyway.
fontFace->TryGetFontTable(beTag,
reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
}
~AutoDWriteTable() {
if (fExists) {
fFontFace->ReleaseFontTable(fLock);
}
}
const uint8_t* fData;
UINT32 fSize;
BOOL fExists;
private:
// Borrowed reference, the user must ensure the fontFace stays alive.
IDWriteFontFace* fFontFace;
void* fLock;
};
template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
public:
static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
const T* get() const { return reinterpret_cast<const T*>(fData); }
const T* operator->() const { return reinterpret_cast<const T*>(fData); }
};
static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) {
{
AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWriteFontFace.get());
if (!eblc.fExists) {
return false;
}
if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) {
return false;
}
if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) {
return false;
}
uint32_t numSizes = SkEndianSwap32(eblc->numSizes);
if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation) +
sizeof(SkOTTableEmbeddedBitmapLocation::BitmapSizeTable) * numSizes)
{
return false;
}
const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable* sizeTable =
SkTAfter<const SkOTTableEmbeddedBitmapLocation::BitmapSizeTable>(eblc.get());
for (uint32_t i = 0; i < numSizes; ++i, ++sizeTable) {
if (sizeTable->ppemX == size && sizeTable->ppemY == size) {
// TODO: determine if we should dig through IndexSubTableArray/IndexSubTable
// to determine the actual number of glyphs with bitmaps.
// TODO: Ensure that the bitmaps actually cover a significant portion of the strike.
//TODO: Endure that the bitmaps are bi-level.
if (sizeTable->endGlyphIndex >= sizeTable->startGlyphIndex + 3) {
return true;
}
}
}
}
{
AutoTDWriteTable<SkOTTableEmbeddedBitmapScaling> ebsc(typeface->fDWriteFontFace.get());
if (!ebsc.fExists) {
return false;
}
if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling)) {
return false;
}
if (ebsc->version != SkOTTableEmbeddedBitmapScaling::version_initial) {
return false;
}
uint32_t numSizes = SkEndianSwap32(ebsc->numSizes);
if (ebsc.fSize < sizeof(SkOTTableEmbeddedBitmapScaling) +
sizeof(SkOTTableEmbeddedBitmapScaling::BitmapScaleTable) * numSizes)
{
return false;
}
const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable* scaleTable =
SkTAfter<const SkOTTableEmbeddedBitmapScaling::BitmapScaleTable>(ebsc.get());
for (uint32_t i = 0; i < numSizes; ++i, ++scaleTable) {
if (scaleTable->ppemX == size && scaleTable->ppemY == size) {
// EBSC tables are normally only found in bitmap only fonts.
return true;
}
}
}
return false;
}
static bool bothZero(SkScalar a, SkScalar b) {
return 0 == a && 0 == b;
}
// returns false if there is any non-90-rotation or skew
static bool isAxisAligned(const SkScalerContext::Rec& rec) {
return 0 == rec.fPreSkewX &&
(bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
}
SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
const SkDescriptor* desc)
: SkScalerContext(typeface, desc)
, fTypeface(SkRef(typeface))
, fGlyphCount(-1) {
fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
fXform.dx = 0;
fXform.dy = 0;
// In general, all glyphs should use CLEARTYPE_NATURAL_SYMMETRIC
// except when bi-level rendering is requested or there are embedded
// bi-level bitmaps (and the embedded bitmap flag is set and no rotation).
//
// DirectWrite's IDWriteFontFace::GetRecommendedRenderingMode does not do
// this. As a result, determine the actual size of the text and then see if
// there are any embedded bi-level bitmaps of that size. If there are, then
// force bitmaps by requesting bi-level rendering.
//
// FreeType allows for separate ppemX and ppemY, but DirectWrite assumes
// square pixels and only uses ppemY. Therefore the transform must track any
// non-uniform x-scale.
//
// Also, rotated glyphs should have the same absolute advance widths as
// horizontal glyphs and the subpixel flag should not affect glyph shapes.
if (SkMask::kBW_Format == fRec.fMaskFormat) {
// A is the total matrix.
SkMatrix A;
fRec.getSingleMatrix(&A);
// h is where A maps the horizontal baseline.
SkPoint h = SkPoint::Make(SK_Scalar1, 0);
A.mapPoints(&h, 1);
// G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
SkMatrix G;
SkComputeGivensRotation(h, &G);
// GA is the matrix A with rotation removed.
SkMatrix GA(G);
GA.preConcat(A);
// realTextSize is the actual device size we want (as opposed to the size the user requested).
// gdiTextSize is the size we request when GDI compatible.
// If the scale is negative, this means the matrix will do the flip anyway.
SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
// Due to floating point math, the lower bits are suspect. Round carefully.
SkScalar roundedTextSize = SkScalarRoundToScalar(realTextSize * 64.0f) / 64.0f;
SkScalar gdiTextSize = SkScalarFloorToScalar(roundedTextSize);
if (gdiTextSize == 0) {
gdiTextSize = SK_Scalar1;
}
bool hasBitmap = fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag &&
hasBitmapStrike(typeface, SkScalarTruncToInt(gdiTextSize));
bool axisAligned = isAxisAligned(fRec);
bool isBiLevel = SkMask::kBW_Format == fRec.fMaskFormat || (hasBitmap && axisAligned);
if (isBiLevel) {
fTextSizeRender = gdiTextSize;
fRenderingMode = DWRITE_RENDERING_MODE_ALIASED;
fTextureType = DWRITE_TEXTURE_ALIASED_1x1;
fTextSizeMeasure = gdiTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
} else {
} else if (hasBitmap) {
// If rotated but the horizontal text would have used a bitmap,
// render high quality rotated glyphs using the bitmap metrics.
fTextSizeRender = gdiTextSize;
fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
fTextSizeMeasure = gdiTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
} else {
fTextSizeRender = realTextSize;
fRenderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
fTextureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
fTextSizeMeasure = realTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
}
if (this->isSubpixel()) {
fTextSizeMeasure = realTextSize;
fMeasuringMode = DWRITE_MEASURING_MODE_NATURAL;
}
// Remove the realTextSize, as that is the text height scale currently in A.
SkScalar scale = SkScalarInvert(realTextSize);
// fSkXform is the total matrix A without the text height scale.
fSkXform = A;
fSkXform.preScale(scale, scale); //remove the text height scale.
fXform.m11 = SkScalarToFloat(fSkXform.getScaleX());
fXform.m12 = SkScalarToFloat(fSkXform.getSkewY());
fXform.m21 = SkScalarToFloat(fSkXform.getSkewX());
fXform.m22 = SkScalarToFloat(fSkXform.getScaleY());
fXform.dx = 0;
fXform.dy = 0;
// GsA is the non-rotational part of A without the text height scale.
SkMatrix GsA(GA);
GsA.preScale(scale, scale); //remove text height scale, G is rotational so reorders with scale.
fGsA.m11 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleX));
fGsA.m12 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
fGsA.m21 = SkScalarToFloat(GsA.get(SkMatrix::kMSkewX));
fGsA.m22 = SkScalarToFloat(GsA.get(SkMatrix::kMScaleY));
// fG_inv is G inverse, which is fairly simple since G is 2x2 rotational.
fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
-G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
}
SkScalerContext_DW::~SkScalerContext_DW() {
@ -631,9 +841,9 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
{
HRVM(fTypeface->fDWriteFontFace->GetGdiCompatibleGlyphMetrics(
fRec.fTextSize,
fTextSizeMeasure,
1.0f, // pixelsPerDip
&fXform,
&fGsA,
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode,
&glyphId, 1,
&gm),
@ -645,7 +855,7 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
DWRITE_FONT_METRICS dwfm;
fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
SkScalar advanceX = SkScalarMulDiv(fTextSizeMeasure,
SkIntToScalar(gm.advanceWidth),
SkIntToScalar(dwfm.designUnitsPerEm));
@ -654,9 +864,13 @@ void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
}
SkVector vecs[1] = { { advanceX, 0 } };
SkMatrix mat;
fRec.getMatrixFrom2x2(&mat);
mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
if (DWRITE_MEASURING_MODE_GDI_CLASSIC == fMeasuringMode ||
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
{
fG_inv.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
} else {
fSkXform.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
}
glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
@ -683,7 +897,7 @@ void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
run.glyphCount = 1;
run.glyphAdvances = &advance;
run.fontFace = fTypeface->fDWriteFontFace.get();
run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
run.fontEmSize = SkScalarToFloat(fTextSizeRender);
run.bidiLevel = 0;
run.glyphIndices = &glyphId;
run.isSideways = FALSE;
@ -728,7 +942,7 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
DWRITE_MEASURING_MODE_GDI_NATURAL == fMeasuringMode)
{
fTypeface->fDWriteFontFace->GetGdiCompatibleMetrics(
fRec.fTextSize,
fTextSizeRender,
1.0f, // pixelsPerDip
&fXform,
&dwfm);
@ -738,28 +952,28 @@ void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
if (mx) {
mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
mx->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
mx->fAscent = mx->fTop;
mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
mx->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
mx->fBottom = mx->fDescent;
mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
mx->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
mx->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
mx->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem;
mx->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem);
mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
}
if (my) {
my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
my->fTop = -fTextSizeRender * SkIntToScalar(dwfm.ascent) / upem;
my->fAscent = my->fTop;
my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
my->fDescent = fTextSizeRender * SkIntToScalar(dwfm.descent) / upem;
my->fBottom = my->fDescent;
my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
my->fLeading = fTextSizeRender * SkIntToScalar(dwfm.lineGap) / upem;
my->fXHeight = fTextSizeRender * SkIntToScalar(dwfm.xHeight) / upem;
my->fUnderlineThickness = fTextSizeRender * SkIntToScalar(dwfm.underlinePosition) / upem;
my->fUnderlinePosition = -(fTextSizeRender * SkIntToScalar(dwfm.underlineThickness) / upem);
my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
@ -888,7 +1102,7 @@ const void* SkScalerContext_DW::drawDWMask(const SkGlyph& glyph) {
run.glyphCount = 1;
run.glyphAdvances = &advance;
run.fontFace = fTypeface->fDWriteFontFace.get();
run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
run.fontEmSize = SkScalarToFloat(fTextSizeRender);
run.bidiLevel = 0;
run.glyphIndices = &index;
run.isSideways = FALSE;
@ -966,7 +1180,7 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
uint16_t glyphId = glyph.getGlyphID();
//TODO: convert to<->from DIUs? This would make a difference if hinting.
//It may not be needed, it appears that DirectWrite only hints at em size.
HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fTextSizeRender),
&glyphId,
NULL, //advances
NULL, //offsets
@ -976,9 +1190,7 @@ void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
geometryToPath.get()),
"Could not create glyph outline.");
SkMatrix mat;
fRec.getMatrixFrom2x2(&mat);
path->transform(mat);
path->transform(fSkXform);
}
void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
@ -1146,28 +1358,6 @@ int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
}
class AutoDWriteTable {
public:
AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
// Any errors are ignored, user must check fExists anyway.
fontFace->TryGetFontTable(beTag,
reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
}
~AutoDWriteTable() {
if (fExists) {
fFontFace->ReleaseFontTable(fLock);
}
}
const uint8_t* fData;
UINT32 fSize;
BOOL fExists;
private:
// Borrowed reference, the user must ensure the fontFace stays alive.
IDWriteFontFace* fFontFace;
void* fLock;
};
size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
size_t length, void* data) const
{
@ -1260,7 +1450,6 @@ void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
SkScalerContext::kForceAutohinting_Flag |
SkScalerContext::kEmbeddedBitmapText_Flag |
SkScalerContext::kEmbolden_Flag |
SkScalerContext::kLCD_BGROrder_Flag |
SkScalerContext::kLCD_Vertical_Flag;
@ -1362,14 +1551,6 @@ static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance
return true;
}
template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
public:
static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
const T* operator->() const { return reinterpret_cast<const T*>(fData); }
};
SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
const uint32_t* glyphIDs,

109
src/sfnt/SkOTTable_EBDT.h Normal file
Просмотреть файл

@ -0,0 +1,109 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkOTTable_EBDT_DEFINED
#define SkOTTable_EBDT_DEFINED
#include "SkEndian.h"
#include "SkOTTableTypes.h"
#include "SkOTTable_head.h"
#include "SkOTTable_loca.h"
#include "SkTypedEnum.h"
#pragma pack(push, 1)
struct SkOTTableEmbeddedBitmapData {
static const SK_OT_CHAR TAG0 = 'E';
static const SK_OT_CHAR TAG1 = 'B';
static const SK_OT_CHAR TAG2 = 'D';
static const SK_OT_CHAR TAG3 = 'T';
static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapData>::value;
SK_OT_Fixed version;
static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
struct BigGlyphMetrics {
SK_OT_BYTE height;
SK_OT_BYTE width;
SK_OT_CHAR horiBearingX;
SK_OT_CHAR horiBearingY;
SK_OT_BYTE horiAdvance;
SK_OT_CHAR vertBearingX;
SK_OT_CHAR vertBearingY;
SK_OT_BYTE vertAdvance;
};
struct SmallGlyphMetrics {
SK_OT_BYTE height;
SK_OT_BYTE width;
SK_OT_CHAR bearingX;
SK_OT_CHAR bearingY;
SK_OT_BYTE advance;
};
// Small metrics, byte-aligned data.
struct Format1 {
SmallGlyphMetrics smallGlyphMetrics;
//SK_OT_BYTE[] byteAlignedBitmap;
};
// Small metrics, bit-aligned data.
struct Format2 {
SmallGlyphMetrics smallGlyphMetrics;
//SK_OT_BYTE[] bitAlignedBitmap;
};
// Format 3 is not used.
// EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), compressed data.
// Only used on Mac.
struct Format4 {
SK_OT_ULONG whiteTreeOffset;
SK_OT_ULONG blackTreeOffset;
SK_OT_ULONG glyphDataOffset;
};
// EBLC metrics (IndexSubTable::header::indexFormat 2 or 5), bit-aligned data.
struct Format5 {
//SK_OT_BYTE[] bitAlignedBitmap;
};
// Big metrics, byte-aligned data.
struct Format6 {
BigGlyphMetrics bigGlyphMetrics;
//SK_OT_BYTE[] byteAlignedBitmap;
};
// Big metrics, bit-aligned data.
struct Format7 {
BigGlyphMetrics bigGlyphMetrics;
//SK_OT_BYTE[] bitAlignedBitmap;
};
struct EBDTComponent {
SK_OT_USHORT glyphCode; // Component glyph code
SK_OT_CHAR xOffset; // Position of component left
SK_OT_CHAR yOffset; // Position of component top
};
struct Format8 {
SmallGlyphMetrics smallMetrics; // Metrics information for the glyph
SK_OT_BYTE pad; // Pad to short boundary
SK_OT_USHORT numComponents; // Number of components
//EBDTComponent componentArray[numComponents]; // Glyph code, offset array
};
struct Format9 {
BigGlyphMetrics bigMetrics; // Metrics information for the glyph
SK_OT_USHORT numComponents; // Number of components
//EBDTComponent componentArray[numComponents]; // Glyph code, offset array
};
};
#pragma pack(pop)
#endif

152
src/sfnt/SkOTTable_EBLC.h Normal file
Просмотреть файл

@ -0,0 +1,152 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkOTTable_EBLC_DEFINED
#define SkOTTable_EBLC_DEFINED
#include "SkEndian.h"
#include "SkOTTable_EBDT.h"
#include "SkOTTableTypes.h"
#include "SkTypedEnum.h"
#pragma pack(push, 1)
struct SkOTTableEmbeddedBitmapLocation {
static const SK_OT_CHAR TAG0 = 'E';
static const SK_OT_CHAR TAG1 = 'B';
static const SK_OT_CHAR TAG2 = 'L';
static const SK_OT_CHAR TAG3 = 'C';
static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapLocation>::value;
SK_OT_Fixed version;
static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
SK_OT_ULONG numSizes;
struct SbitLineMetrics {
SK_OT_CHAR ascender;
SK_OT_CHAR descender;
SK_OT_BYTE widthMax;
SK_OT_CHAR caretSlopeNumerator;
SK_OT_CHAR caretSlopeDenominator;
SK_OT_CHAR caretOffset;
SK_OT_CHAR minOriginSB;
SK_OT_CHAR minAdvanceSB;
SK_OT_CHAR maxBeforeBL;
SK_OT_CHAR minAfterBL;
SK_OT_CHAR pad1;
SK_OT_CHAR pad2;
};
struct BitmapSizeTable {
SK_OT_ULONG indexSubTableArrayOffset; //offset to indexSubtableArray from beginning of EBLC.
SK_OT_ULONG indexTablesSize; //number of bytes in corresponding index subtables and array
SK_OT_ULONG numberOfIndexSubTables; //an index subtable for each range or format change
SK_OT_ULONG colorRef; //not used; set to 0.
SbitLineMetrics hori; //line metrics for text rendered horizontally
SbitLineMetrics vert; //line metrics for text rendered vertically
SK_OT_USHORT startGlyphIndex; //lowest glyph index for this size
SK_OT_USHORT endGlyphIndex; //highest glyph index for this size
SK_OT_BYTE ppemX; //horizontal pixels per Em
SK_OT_BYTE ppemY; //vertical pixels per Em
struct BitDepth {
SK_TYPED_ENUM(Value, SK_OT_BYTE,
((BW, 1))
((Gray4, 2))
((Gray16, 4))
((Gray256, 8))
SK_SEQ_END,
SK_SEQ_END)
SK_OT_BYTE value;
} bitDepth; //the Microsoft rasterizer v.1.7 or greater supports
union Flags {
struct Field {
//0-7
SK_OT_BYTE_BITFIELD(
Horizontal, // Horizontal small glyph metrics
Vertical, // Vertical small glyph metrics
Reserved02,
Reserved03,
Reserved04,
Reserved05,
Reserved06,
Reserved07)
} field;
struct Raw {
static const SK_OT_CHAR Horizontal = 1u << 0;
static const SK_OT_CHAR Vertical = 1u << 1;
SK_OT_CHAR value;
} raw;
} flags;
}; //bitmapSizeTable[numSizes];
struct IndexSubTableArray {
SK_OT_USHORT firstGlyphIndex; //first glyph code of this range
SK_OT_USHORT lastGlyphIndex; //last glyph code of this range (inclusive)
SK_OT_ULONG additionalOffsetToIndexSubtable; //add to BitmapSizeTable::indexSubTableArrayOffset to get offset from beginning of 'EBLC'
}; //indexSubTableArray[BitmapSizeTable::numberOfIndexSubTables];
struct IndexSubHeader {
SK_OT_USHORT indexFormat; //format of this indexSubTable
SK_OT_USHORT imageFormat; //format of 'EBDT' image data
SK_OT_ULONG imageDataOffset; //offset to image data in 'EBDT' table
};
// Variable metrics glyphs with 4 byte offsets
struct IndexSubTable1 {
IndexSubHeader header;
//SK_OT_ULONG offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph
//glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset
};
// All Glyphs have identical metrics
struct IndexSubTable2 {
IndexSubHeader header;
SK_OT_ULONG imageSize; // all glyphs are of the same size
SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; // all glyphs have the same metrics; glyph data may be compressed, byte-aligned, or bit-aligned
};
// Variable metrics glyphs with 2 byte offsets
struct IndexSubTable3 {
IndexSubHeader header;
//SK_OT_USHORT offsetArray[lastGlyphIndex - firstGlyphIndex + 1 + 1]; //last element points to one past end of last glyph, may have extra element to force even number of elements
//glyphData = offsetArray[glyphIndex - firstGlyphIndex] + imageDataOffset
};
// Variable metrics glyphs with sparse glyph codes
struct IndexSubTable4 {
IndexSubHeader header;
SK_OT_ULONG numGlyphs;
struct CodeOffsetPair {
SK_OT_USHORT glyphCode;
SK_OT_USHORT offset; //location in EBDT
}; //glyphArray[numGlyphs+1]
};
// Constant metrics glyphs with sparse glyph codes
struct IndexSubTable5 {
IndexSubHeader header;
SK_OT_ULONG imageSize; //all glyphs have the same data size
SkOTTableEmbeddedBitmapData::BigGlyphMetrics bigMetrics; //all glyphs have the same metrics
SK_OT_ULONG numGlyphs;
//SK_OT_USHORT glyphCodeArray[numGlyphs] //must have even number of entries (set pad to 0)
};
union IndexSubTable {
IndexSubHeader header;
IndexSubTable1 format1;
IndexSubTable2 format2;
IndexSubTable3 format3;
IndexSubTable4 format4;
IndexSubTable5 format5;
};
};
#pragma pack(pop)
#endif

41
src/sfnt/SkOTTable_EBSC.h Normal file
Просмотреть файл

@ -0,0 +1,41 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkOTTable_EBSC_DEFINED
#define SkOTTable_EBSC_DEFINED
#include "SkEndian.h"
#include "SkOTTable_EBLC.h"
#include "SkOTTableTypes.h"
#pragma pack(push, 1)
struct SkOTTableEmbeddedBitmapScaling {
static const SK_OT_CHAR TAG0 = 'E';
static const SK_OT_CHAR TAG1 = 'S';
static const SK_OT_CHAR TAG2 = 'B';
static const SK_OT_CHAR TAG3 = 'C';
static const SK_OT_ULONG TAG = SkOTTableTAG<SkOTTableEmbeddedBitmapScaling>::value;
SK_OT_Fixed version;
static const SK_OT_Fixed version_initial = SkTEndian_SwapBE32(0x00020000);
SK_OT_ULONG numSizes;
struct BitmapScaleTable {
SkOTTableEmbeddedBitmapLocation::SbitLineMetrics hori;
SkOTTableEmbeddedBitmapLocation::SbitLineMetrics vert;
SK_OT_BYTE ppemX; //target horizontal pixels per EM
SK_OT_BYTE ppemY; //target vertical pixels per EM
SK_OT_BYTE substitutePpemX; //use bitmaps of this size
SK_OT_BYTE substitutePpemY; //use bitmaps of this size
}; //bitmapScaleTable[numSizes];
};
#pragma pack(pop)
#endif