[dwrite] minor

pull/903/head
Ebrahim Byagowi 7 years ago
parent ebccd01974
commit fe18c471a4
  1. 5
      src/dev-run.sh
  2. 118
      src/hb-directwrite.cc

@ -1,8 +1,9 @@
#!/bin/bash #!/bin/bash
# Suggested setup to use the script: # Suggested setup to use the script:
# (on the root of the project) # (on the root of the project)
# $ NOCONFIGURE=1 ./autogen.sh --with-freetype --with-glib --with-gobject --with-cairo # $ NOCONFIGURE=1 ./autogen.sh && mkdir build && cd build
# $ mkdir build && cd build && ../configure && make -j5 && cd .. # $ ../configure --with-freetype --with-glib --with-gobject --with-cairo
# $ make -j5 && cd ..
# $ src/dev-run.sh [FONT-FILE] [TEXT] # $ src/dev-run.sh [FONT-FILE] [TEXT]
# #
# Or, using cmake: # Or, using cmake:

@ -1,4 +1,4 @@
/* /*
* Copyright © 2015-2018 Ebrahim Byagowi * Copyright © 2015-2018 Ebrahim Byagowi
* *
* This is part of HarfBuzz, a text shaping library. * This is part of HarfBuzz, a text shaping library.
@ -71,7 +71,7 @@ public:
// IDWriteFontFileLoader methods // IDWriteFontFileLoader methods
virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey (void const* fontFileReferenceKey, virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey (void const* fontFileReferenceKey,
UINT32 fontFileReferenceKeySize, uint32_t fontFileReferenceKeySize,
OUT IDWriteFontFileStream** fontFileStream) OUT IDWriteFontFileStream** fontFileStream)
{ {
*fontFileStream = mFontFileStream; *fontFileStream = mFontFileStream;
@ -103,9 +103,8 @@ public:
OUT void** fragmentContext) OUT void** fragmentContext)
{ {
// We are required to do bounds checking. // We are required to do bounds checking.
if (fileOffset + fragmentSize > mSize) { if (fileOffset + fragmentSize > mSize)
return E_FAIL; return E_FAIL;
}
// truncate the 64 bit fileOffset to size_t sized index into mData // truncate the 64 bit fileOffset to size_t sized index into mData
size_t index = static_cast<size_t> (fileOffset); size_t index = static_cast<size_t> (fileOffset);
@ -135,7 +134,8 @@ public:
* shaper face data * shaper face data
*/ */
struct hb_directwrite_shaper_face_data_t { struct hb_directwrite_shaper_face_data_t
{
IDWriteFactory *dwriteFactory; IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile; IDWriteFontFile *fontFile;
IDWriteFontFileStream *fontFileStream; IDWriteFontFileStream *fontFileStream;
@ -179,20 +179,16 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
return nullptr; \ return nullptr; \
} HB_STMT_END; } HB_STMT_END;
if (FAILED (hr)) { if (FAILED (hr))
FAIL ("Failed to load font file from data!"); FAIL ("Failed to load font file from data!");
return nullptr;
}
BOOL isSupported; BOOL isSupported;
DWRITE_FONT_FILE_TYPE fileType; DWRITE_FONT_FILE_TYPE fileType;
DWRITE_FONT_FACE_TYPE faceType; DWRITE_FONT_FACE_TYPE faceType;
UINT32 numberOfFaces; uint32_t numberOfFaces;
hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces); hr = fontFile->Analyze (&isSupported, &fileType, &faceType, &numberOfFaces);
if (FAILED (hr) || !isSupported) { if (FAILED (hr) || !isSupported)
FAIL ("Font file is not supported."); FAIL ("Font file is not supported.");
return nullptr;
}
#undef FAIL #undef FAIL
@ -217,7 +213,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *dat
data->fontFace->Release (); data->fontFace->Release ();
if (data->fontFile) if (data->fontFile)
data->fontFile->Release (); data->fontFile->Release ();
if (data->dwriteFactory) { if (data->dwriteFactory)
{
if (data->fontFileLoader) if (data->fontFileLoader)
data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader); data->dwriteFactory->UnregisterFontFileLoader (data->fontFileLoader);
data->dwriteFactory->Release (); data->dwriteFactory->Release ();
@ -237,7 +234,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_shaper_face_data_t *dat
* shaper font data * shaper font data
*/ */
struct hb_directwrite_shaper_font_data_t { struct hb_directwrite_shaper_font_data_t
{
}; };
hb_directwrite_shaper_font_data_t * hb_directwrite_shaper_font_data_t *
@ -324,9 +322,11 @@ public:
, mReadingDirection (readingDirection) , mReadingDirection (readingDirection)
, mCurrentRun (nullptr) { }; , mCurrentRun (nullptr) { };
~TextAnalysis () { ~TextAnalysis ()
{
// delete runs, except mRunHead which is part of the TextAnalysis object // delete runs, except mRunHead which is part of the TextAnalysis object
for (Run *run = mRunHead.nextRun; run;) { for (Run *run = mRunHead.nextRun; run;)
{
Run *origRun = run; Run *origRun = run;
run = run->nextRun; run = run->nextRun;
delete origRun; delete origRun;
@ -334,7 +334,8 @@ public:
} }
STDMETHODIMP GenerateResults (IDWriteTextAnalyzer* textAnalyzer, STDMETHODIMP GenerateResults (IDWriteTextAnalyzer* textAnalyzer,
Run **runHead) { Run **runHead)
{
// Analyzes the text using the script analyzer and returns // Analyzes the text using the script analyzer and returns
// the result as a series of runs. // the result as a series of runs.
@ -350,9 +351,8 @@ public:
mCurrentRun = &mRunHead; mCurrentRun = &mRunHead;
// Call each of the analyzers in sequence, recording their results. // Call each of the analyzers in sequence, recording their results.
if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this))) { if (SUCCEEDED (hr = textAnalyzer->AnalyzeScript (this, 0, mTextLength, this)))
*runHead = &mRunHead; *runHead = &mRunHead;
}
return hr; return hr;
} }
@ -363,12 +363,14 @@ public:
OUT wchar_t const** textString, OUT wchar_t const** textString,
OUT uint32_t* textLength) OUT uint32_t* textLength)
{ {
if (textPosition >= mTextLength) { if (textPosition >= mTextLength)
{
// No text at this position, valid query though. // No text at this position, valid query though.
*textString = nullptr; *textString = nullptr;
*textLength = 0; *textLength = 0;
} }
else { else
{
*textString = mText + textPosition; *textString = mText + textPosition;
*textLength = mTextLength - textPosition; *textLength = mTextLength - textPosition;
} }
@ -379,13 +381,15 @@ public:
OUT wchar_t const** textString, OUT wchar_t const** textString,
OUT uint32_t* textLength) OUT uint32_t* textLength)
{ {
if (textPosition == 0 || textPosition > mTextLength) { if (textPosition == 0 || textPosition > mTextLength)
{
// Either there is no text before here (== 0), or this // Either there is no text before here (== 0), or this
// is an invalid position. The query is considered valid though. // is an invalid position. The query is considered valid though.
*textString = nullptr; *textString = nullptr;
*textLength = 0; *textLength = 0;
} }
else { else
{
*textString = mText; *textString = mText;
*textLength = textPosition; *textLength = textPosition;
} }
@ -458,14 +462,10 @@ protected:
// Split the tail if needed (the length remaining is less than the // Split the tail if needed (the length remaining is less than the
// current run's size). // current run's size).
if (*textLength < mCurrentRun->mTextLength) if (*textLength < mCurrentRun->mTextLength)
{
SplitCurrentRun (mCurrentRun->mTextStart + *textLength); SplitCurrentRun (mCurrentRun->mTextStart + *textLength);
}
else else
{
// Just advance the current run. // Just advance the current run.
mCurrentRun = mCurrentRun->nextRun; mCurrentRun = mCurrentRun->nextRun;
}
*textLength -= origRun->mTextLength; *textLength -= origRun->mTextLength;
// Return a reference to the run that was just current. // Return a reference to the run that was just current.
@ -480,17 +480,14 @@ protected:
// corresponding run for the text position. // corresponding run for the text position.
if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition)) if (mCurrentRun && mCurrentRun->ContainsTextPosition (textPosition))
{
return; return;
}
for (Run *run = &mRunHead; run; run = run->nextRun) { for (Run *run = &mRunHead; run; run = run->nextRun)
if (run->ContainsTextPosition (textPosition)) if (run->ContainsTextPosition (textPosition))
{ {
mCurrentRun = run; mCurrentRun = run;
return; return;
} }
}
//NS_NOTREACHED ("We should always be able to find the text position in one \ //NS_NOTREACHED ("We should always be able to find the text position in one \
// of our runs"); // of our runs");
} }
@ -592,25 +589,23 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
textString[chars_len++] = c; textString[chars_len++] = c;
else if (unlikely (c > 0x10FFFFu)) else if (unlikely (c > 0x10FFFFu))
textString[chars_len++] = 0xFFFDu; textString[chars_len++] = 0xFFFDu;
else { else
{
textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10); textString[chars_len++] = 0xD800u + ((c - 0x10000u) >> 10);
textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1)); textString[chars_len++] = 0xDC00u + ((c - 0x10000u) & ((1u << 10) - 1));
} }
} }
ALLOCATE_ARRAY (WORD, log_clusters, chars_len); ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
// if (num_features) /* Need log_clusters to assign features. */
chars_len = 0;
for (unsigned int i = 0; i < buffer->len; i++)
{ {
/* Need log_clusters to assign features. */ hb_codepoint_t c = buffer->info[i].codepoint;
chars_len = 0; unsigned int cluster = buffer->info[i].cluster;
for (unsigned int i = 0; i < buffer->len; i++) log_clusters[chars_len++] = cluster;
{ if (hb_in_range (c, 0x10000u, 0x10FFFFu))
hb_codepoint_t c = buffer->info[i].codepoint; log_clusters[chars_len++] = cluster; /* Surrogates. */
unsigned int cluster = buffer->info[i].cluster;
log_clusters[chars_len++] = cluster;
if (hb_in_range (c, 0x10000u, 0x10FFFFu))
log_clusters[chars_len++] = cluster; /* Surrogates. */
}
} }
// TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES // TODO: Handle TEST_DISABLE_OPTIONAL_LIGATURES
@ -638,10 +633,7 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
} HB_STMT_END; } HB_STMT_END;
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to generate results."); FAIL ("Analyzer failed to generate results.");
return false;
}
uint32_t maxGlyphCount = 3 * textLength / 2 + 16; uint32_t maxGlyphCount = 3 * textLength / 2 + 16;
uint32_t glyphCount; uint32_t glyphCount;
@ -654,21 +646,23 @@ _hb_directwrite_shape_full (hb_shape_plan_t *shape_plan,
hb_language_to_string (buffer->props.language), 20); hb_language_to_string (buffer->props.language), 20);
} }
DWRITE_TYPOGRAPHIC_FEATURES singleFeatures; // TODO: it does work but doesn't care about ranges
singleFeatures.featureCount = num_features; DWRITE_TYPOGRAPHIC_FEATURES typographic_features;
typographic_features.featureCount = num_features;
if (num_features) if (num_features)
{ {
singleFeatures.features = new DWRITE_FONT_FEATURE[num_features]; typographic_features.features = new DWRITE_FONT_FEATURE[num_features];
for (unsigned int i = 0; i < num_features; ++i) for (unsigned int i = 0; i < num_features; ++i)
{ {
singleFeatures.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG) typographic_features.features[i].nameTag = (DWRITE_FONT_FEATURE_TAG)
hb_uint32_swap (features[i].tag); hb_uint32_swap (features[i].tag);
singleFeatures.features[i].parameter = features[i].value; typographic_features.features[i].parameter = features[i].value;
} }
} }
const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures = const DWRITE_TYPOGRAPHIC_FEATURES* dwFeatures =
(const DWRITE_TYPOGRAPHIC_FEATURES*) &singleFeatures; (const DWRITE_TYPOGRAPHIC_FEATURES*) &typographic_features;
const uint32_t featureRangeLengths[] = { textLength }; const uint32_t featureRangeLengths[] = { textLength };
//
uint16_t* clusterMap = new uint16_t[textLength]; uint16_t* clusterMap = new uint16_t[textLength];
DWRITE_SHAPING_TEXT_PROPERTIES* textProperties = DWRITE_SHAPING_TEXT_PROPERTIES* textProperties =
@ -693,10 +687,7 @@ retry_getglyphs:
goto retry_getglyphs; goto retry_getglyphs;
} }
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get glyphs."); FAIL ("Analyzer failed to get glyphs.");
return false;
}
float* glyphAdvances = new float[maxGlyphCount]; float* glyphAdvances = new float[maxGlyphCount];
DWRITE_GLYPH_OFFSET* glyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount]; DWRITE_GLYPH_OFFSET* glyphOffsets = new DWRITE_GLYPH_OFFSET[maxGlyphCount];
@ -730,10 +721,7 @@ retry_getglyphs:
glyphAdvances, glyphOffsets); glyphAdvances, glyphOffsets);
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get glyph placements."); FAIL ("Analyzer failed to get glyph placements.");
return false;
}
IDWriteTextAnalyzer1* analyzer1; IDWriteTextAnalyzer1* analyzer1;
analyzer->QueryInterface (&analyzer1); analyzer->QueryInterface (&analyzer1);
@ -748,10 +736,7 @@ retry_getglyphs:
glyphProperties, justificationOpportunities); glyphProperties, justificationOpportunities);
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get justification opportunities."); FAIL ("Analyzer failed to get justification opportunities.");
return false;
}
float* justifiedGlyphAdvances = new float[maxGlyphCount]; float* justifiedGlyphAdvances = new float[maxGlyphCount];
DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount]; DWRITE_GLYPH_OFFSET* justifiedGlyphOffsets = new DWRITE_GLYPH_OFFSET[glyphCount];
@ -759,18 +744,12 @@ retry_getglyphs:
glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets); glyphAdvances, glyphOffsets, justifiedGlyphAdvances, justifiedGlyphOffsets);
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get justified glyph advances."); FAIL ("Analyzer failed to get justified glyph advances.");
return false;
}
DWRITE_SCRIPT_PROPERTIES scriptProperties; DWRITE_SCRIPT_PROPERTIES scriptProperties;
hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties); hr = analyzer1->GetScriptProperties (runHead->mScript, &scriptProperties);
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get script properties."); FAIL ("Analyzer failed to get script properties.");
return false;
}
uint32_t justificationCharacter = scriptProperties.justificationCharacter; uint32_t justificationCharacter = scriptProperties.justificationCharacter;
// if a script justificationCharacter is not space, it can have GetJustifiedGlyphs // if a script justificationCharacter is not space, it can have GetJustifiedGlyphs
@ -801,10 +780,7 @@ retry_getglyphs:
goto retry_getjustifiedglyphs; goto retry_getjustifiedglyphs;
} }
if (FAILED (hr)) if (FAILED (hr))
{
FAIL ("Analyzer failed to get justified glyphs."); FAIL ("Analyzer failed to get justified glyphs.");
return false;
}
delete [] clusterMap; delete [] clusterMap;
delete [] glyphIndices; delete [] glyphIndices;
@ -896,7 +872,7 @@ retry_getglyphs:
delete [] glyphOffsets; delete [] glyphOffsets;
if (num_features) if (num_features)
delete [] singleFeatures.features; delete [] typographic_features.features;
/* Wow, done! */ /* Wow, done! */
return true; return true;

Loading…
Cancel
Save